diff --git a/NEW_PROJECT.md b/NEW_PROJECT.md index c3aeb12..7701a24 100644 --- a/NEW_PROJECT.md +++ b/NEW_PROJECT.md @@ -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 и конкретной разводки адаптера; переносимая логика протоколов diff --git a/README.md b/README.md index 0c1001c..3ac3239 100644 --- a/README.md +++ b/README.md @@ -40,9 +40,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#** | @@ -64,6 +65,7 @@ templates/ | Инструмент | Что делает | |---|---| +| [`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 +120,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 | diff --git a/c/firmware-info/tests/test_c2000_build.py b/c/firmware-info/tests/test_c2000_build.py new file mode 100644 index 0000000..0d4e84e --- /dev/null +++ b/c/firmware-info/tests/test_c2000_build.py @@ -0,0 +1,74 @@ +import importlib.util # Загружает общий модуль подготовки непосредственно из проверяемой копии templates. +import json # Проверяет сохранение пользовательских полей при резервировании версии 166. +from pathlib import Path # Все файлы теста находятся в изолированном временном каталоге. +import tempfile # Исключает запись версий и паспортов в рабочие прошивки пользователя. +import unittest # Запускает проверки без зависимостей SETGUI и Qt. + +TOOLS = Path(__file__).resolve().parents[1] / "tools" # Тест переносится вместе с c/firmware-info в полный checkout templates. +SPEC = importlib.util.spec_from_file_location("checked_c2000_build", TOOLS / "c2000_build.py") # Выбирает одну реализацию общего процесса. +BUILD = importlib.util.module_from_spec(SPEC) # Импорт не выполняет prebuild и не меняет счётчики версии. +SPEC.loader.exec_module(BUILD) # Проверяет реальный модуль, а не копию функций внутри теста. + + +class LegacyVersionTests(unittest.TestCase): # Подтверждает совместимость общей подготовки с JSON-конфигурацией 166. + def test_json_counter_increments_once_and_keeps_settings(self): # Перенос в templates не должен удваивать резервирование версии. + with tempfile.TemporaryDirectory() as temporary: # Версия настоящего проекта 166 остаётся неизменной. + project = Path(temporary) # Минимальный проект использует прежние настройки без нового аппаратного профиля. + settings = {"product": "Balsam-166-PM35", "target": "TMS320F28335", "version": [1, 0, 999], "increment_version": True, "max_image_bytes": 32508, "copy_to": "../Bin"} # Patch 999 проверяет перенос в minor по общему контракту версии. + config = project / "firmware_identity.json" # Сохраняемый счётчик расположен в том же JSON, что в ветке 166. + config.write_text(json.dumps(settings), encoding="utf-8") # Русские данные и настройки сохраняются как UTF-8. + templates = TOOLS.parents[2] # Полный путь templates восстанавливается из c/firmware-info/tools. + metadata = BUILD.prepare(project, templates, project / "Debug/generated") # Выполняет настоящий общий prebuild без компиляции и сети. + saved = json.loads(config.read_text(encoding="utf-8")) # Проверяет именно сохранённую версию, а не только возвращённые метаданные. + self.assertEqual(saved["version"], [1, 1, 0]) # Номер увеличен один раз с переносом patch в minor. + self.assertEqual(metadata["version"], saved["version"]) # Паспорт и сохраняемый счётчик описывают одну попытку компиляции. + self.assertEqual(metadata["max_image_bytes"], 32508) # Историческая граница EEPROM 166 остаётся обязательной для postbuild. + self.assertEqual(saved["copy_to"], settings["copy_to"]) # Общий генератор сохраняет пользовательские поля, даже если сеть выполняет Публикатор. + + +class ReleaseLayoutTests(unittest.TestCase): # Проверяет назначение комплекта F2812 и совместимость экспорта для остальных процессоров. + def test_primary_package_follows_target_and_exports_with_receipt(self): # Проверяет пути, байты и паспорта полного комплекта после раскладки и экспорта. + identity = BUILD.load_identity(TOOLS.parents[2]) # Использует действующие функции подписи и копирования общей библиотеки. + for target, purpose in ((None, "eeprom"), ("TMS320F2812", "flash"), ("TMS320F28335", "eeprom")): # Старые вызовы и F28335 сохраняют EEPROM; F2812 использует внешнюю Flash. + with self.subTest(target=target), tempfile.TemporaryDirectory() as temporary: # Каждый вариант получает независимый выпуск и отдельную диагностику. + root = Path(temporary) # Файлы теста не попадают в действующий проект или каталог загрузок. + stage = root / "stage" # Воспроизводит временный каталог защищённого postbuild. + archive_name = "current-build" # Имя архива здесь фиксировано: проверяется раскладка, а не генерация даты. + archive = stage / archive_name # Полная копия компиляции должна получить те же папки, что текущие результаты. + archive.mkdir(parents=True) # Создаёт только каталоги данного проверочного выпуска. + metadata = {"target": target, "version": [1, 2, 3]} # Проверка паспорта должна сохранить процессор и версию конкретного сценария. + metadata_path = archive / "firmware_identity.json" # Общий паспорт остаётся в корне архива после раскладки. + metadata_path.write_text(json.dumps(metadata), encoding="utf-8") # Записывает метаданные в штатной кодировке общей библиотеки. + artifact, image_name = "Firmware", "Firmware_NOGIT000.bin" # Различает исходный OUT и BIN с идентификатором сборки. + companions = {"Firmware.out": b"original OUT", "Firmware.hex": b"original HEX", image_name + ".map": b"original map"} # Сопроводительные файлы обязаны следовать за основным образом без изменения байтов. + variants = {"Firmware_flash.out": "flash", "Firmware_flash_rs.bin": "rs", "Firmware_NOGIT000_can.bin": "can"} # Именованные дополнительные варианты сохраняют прежние независимые назначения. + for folder in (stage, archive): # Готовит одинаковые результаты для текущего выпуска и полного архива. + image = folder / image_name # Каждый экземпляр BIN получает собственные настоящие manifest и SHA-256. + image.write_bytes(b"primary SCI8 payload") # Узнаваемые байты выявляют подмену образа при переносе или экспорте. + identity.seal(image, metadata_path) # Вычисляет контрольные суммы штатной реализацией, а не подставляет фиктивный manifest. + for name, content in companions.items(): # Подготавливает OUT, HEX и карту того же основного комплекта. + (folder / name).write_bytes(content) # Сохраняет эталон для проверки точности переноса. + for name in variants: # Дополнительные образы нужны для проверки сохранения маршрутов flash, rs и can. + (folder / name).write_bytes(name.encode("ascii")) # Отличимые имена в содержимом исключают случайную перестановку файлов. + relative = BUILD.arrange_release(stage, archive_name, artifact, image_name, Path("Firmware_NOGIT000_can.bin"), target=target) # Вызывает ту же раскладку, что действующий postbuild. + self.assertEqual(relative, purpose + "/" + image_name) # Возвращаемый путь должен вести к основному образу в назначении выбранного процессора. + BUILD.write_receipt(stage, archive_name, relative) # Проверяет связь раскладки с указателем последнего выпуска. + receipt = json.loads((stage / "latest_build.json").read_text(encoding="utf-8")) # Читает записанный указатель как его потребитель. + self.assertEqual(receipt["manifest"], relative + ".manifest.json") # Путь импорта должен учитывать flash у F2812 и eeprom у остальных. + exported = identity.export_build(archive, root / "export", relative) # Выполняет настоящий экспорт всего архива в отдельный каталог. + for folder in (stage, archive, exported): # Одновременно проверяет локальный результат, архив и копию для пользователя. + BUILD.verify_package(folder / relative, metadata) # Сверяет реальные байты BIN, размер, SHA-256 и поля паспорта после всех переносов. + self.assertEqual((folder / relative).read_bytes(), b"primary SCI8 payload") # Основной образ сохраняется побайтово. + for suffix in (".manifest.json", ".sha256"): # Оба сопроводительных файла должны лежать рядом с BIN. + self.assertTrue((folder / (relative + suffix)).is_file()) # Обнаруживает потерю manifest или контрольной суммы при раскладке. + for name, content in companions.items(): # OUT, HEX и карта должны повторять назначение основного BIN. + self.assertEqual((folder / purpose / name).read_bytes(), content) # Проверяет путь и точное содержимое каждого файла. + for name, destination in variants.items(): # Проверяет неизменность маршрутов дополнительных вариантов. + self.assertEqual((folder / destination / name).read_bytes(), name.encode("ascii")) # Отдельные flash, rs и can не должны уйти в папку основного образа. + self.assertTrue((folder / "firmware_identity.json").is_file()) # Общий паспорт остаётся доступен в корне каждого комплекта. + if target == "TMS320F2812": # Только для F2812 проверяет отсутствие вводящей в заблуждение папки EEPROM. + self.assertFalse((folder / "eeprom").exists()) # Новый выпуск F2812 должен содержать основной комплект исключительно в flash. + + +if __name__ == "__main__": # Импорт набора проверок не запускает их повторно. + unittest.main() # Позволяет проверить совместимость прямой командой Python. diff --git a/c/firmware-info/tests/test_c2000_postbuild.py b/c/firmware-info/tests/test_c2000_postbuild.py new file mode 100644 index 0000000..9a2809f --- /dev/null +++ b/c/firmware-info/tests/test_c2000_postbuild.py @@ -0,0 +1,87 @@ +"""Проверяет совместимость postbuild, экспорт двух образов и отказ от устаревшего Flash OUT.""" # Фиксирует контракт общего выпуска без зависимости от установленного TI-компилятора. +import json # Формирует паспорт текущей сборки для проверки архива и контрольных сумм. +from pathlib import Path # Создаёт независимые пути проекта, компилятора и результатов в каждом тесте. +import subprocess # Использует штатное исключение ненулевого кода проектного сборщика. +import sys # Подключает общий модуль из каталога tools текущей копии templates. +import tempfile # Изолирует проверочные файлы от реальных прошивок и каталогов GUI. +import unittest # Организует проверки публичного контракта postbuild стандартной библиотекой Python. +from unittest.mock import patch # Подменяет только внешние инструменты, оставляя настоящее архивирование и SHA-256. + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'tools')) # Находит проверяемую реализацию относительно теста без путей конкретной рабочей станции. +import c2000_postbuild as c2000 # Вызывает тот же postbuild, который запускается штатным postcompile.bat. +from identity import verify # Проверяет байты скопированных образов по настоящему manifest. + + +class PostbuildTests(unittest.TestCase): # Проверяет общую цепочку от готового OUT до экспортированной папки выпуска. + def setUp(self): # Для каждой проверки создаёт отдельный проект с типичной структурой CCS. + temporary = tempfile.TemporaryDirectory() # Все файлы сценария принадлежат временному каталогу теста. + self.addCleanup(temporary.cleanup) # Освобождает только каталог данной проверки при любом результате. + self.root = Path(temporary.name) # Корень не зависит от реальной прошивки и установленного templates. + self.build = self.root / 'project/Debug' # Проверяет соглашение о расположении сборщика рядом с конфигурациями CCS. + self.build.mkdir(parents=True) # Подготавливает рабочий каталог внешних инструментов. + self.compiler = self.root / 'compiler' # Позволяет проверить передачу компилятора текущего проекта вместо фиксированного пути. + (self.compiler / 'bin').mkdir(parents=True) # Воспроизводит структуру установленного C2000 compiler. + (self.compiler / 'bin/hex2000.exe').write_bytes(b'fake tool') # Проверка наличия инструмента реальна, а выполнение будет подменено. + self.source = self.root / 'Bin/Firmware.out' # Основной OUT размещён вне Debug, как в рабочем проекте пользователя. + self.source.parent.mkdir() # Создаёт отдельный каталог исходного COFF и итогового Flash COFF. + self.source.write_bytes(b'RAM image') # Даёт узнаваемые байты для проверки, что основной образ не подменён Flash-вариантом. + self.metadata = self.build / 'metadata.json' # Один паспорт используется обоими вариантами текущего выпуска. + self.metadata.write_text(json.dumps({'build_id': 'NOGIT000', 'built_at_utc': '2026-10-14T13:00:00+00:00', 'source': {'commit': None}, 'version': [1, 2, 3]}), encoding='utf-8') # Фиксированное время проверяет выбор папки по prebuild, а не времени файлов. + self.output = self.build / 'firmware' # Локальный выпуск получает оба образа и их сопроводительные файлы. + self.export = self.root / 'GUI' # Экспорт изолирован от настоящего GUI и сетевых ресурсов. + + def fake_tool(self, command, **kwargs): # Имитирует границу внешних инструментов, оставляя реальную логику упаковки и проверки. + if '--postbuild' in command: # Вложенная Flash-сборка обязана использовать режим без повторного Make. + self.assertEqual(Path(command[command.index('--compiler') + 1]), self.compiler.resolve()) # Проверяет выбор текущей версии TI compiler. + self.assertEqual(Path(command[command.index('--build-dir') + 1]), self.build.resolve()) # Проверяет использование текущих объектов и generated-паспорта. + image = Path(command[command.index('--output') + 1]) # Результат должен создаваться по переданному временному пути. + self.assertNotEqual(image.parent, self.source.parent) # Запрещает выдавать существующий OUT из Bin за результат текущего вызова. + image.write_bytes(b'current Flash image') # Создаёт узнаваемый новый COFF для сравнения всех копий. + image.with_suffix('.map').write_text('codestart 0033fff6', encoding='utf-8') # Воспроизводит обязательный второй результат сборщика. + else: # Обычная SCI8-конверсия должна продолжать использовать основной RAM OUT. + expected = 'Firmware_flash.out' if '_flash_rs.bin' in command[command.index('-o') + 1] else self.source.name # Только отдельная RS-конверсия должна брать Flash COFF. + self.assertEqual(Path(command[1]).name, expected) # Проверяет, что EEPROM BIN и Flash RS BIN создаются из разных исходных образов. + Path(command[command.index('-o') + 1]).write_bytes(b'EEPROM image') # Выпускает HEX/BIN с отличимыми байтами основного варианта. + Path(command[command.index('-map') + 1]).write_text('RAM map', encoding='utf-8') # Сохраняет карты, необходимые настоящему архиватору. + return subprocess.CompletedProcess(command, 0) # Подтверждает только имитируемый инструмент, не подменяя проверки выпуска. + + def run_postbuild(self): # Вызывает публичную функцию с теми же путями, что передаёт BAT из CCS. + return c2000.postbuild(self.compiler, self.build, str(self.source.with_suffix('')), self.metadata, self.output, self.export) # Включает настоящий экспорт и проверку manifest. + + def test_project_without_flash_builder_keeps_eeprom_workflow(self): # Старые проекты должны работать без новых настроек или Flash-файлов. + with patch.object(c2000.subprocess, 'run', side_effect=self.fake_tool) as calls: # Подменяет только TI Hex Utility. + result = self.run_postbuild() # Выполняет полный прежний выпуск EEPROM. + self.assertEqual(calls.call_count, 2) # Для HEX и BIN выполнены два вызова; дополнительного сборщика не было. + self.assertEqual(self.source.read_bytes(), b'RAM image') # Основной OUT не изменён упаковкой. + self.assertFalse(self.source.with_name('Firmware_flash.out').exists()) # Отсутствие builder не создаёт фиктивный Flash-образ. + self.assertEqual(verify(result, Path(str(result) + '.manifest.json'))['size_bytes'], len(b'EEPROM image')) # Проверяет настоящее содержимое EEPROM BIN и его паспорт. + + def test_flash_and_eeprom_share_current_export_with_separate_checksums(self): # Новый выпуск должен содержать оба варианта под своими именами. + (self.build.parent / 'build_flash.py').write_text('# Сборщик проекта подключён явно.\n', encoding='utf-8') # Наличие сценария включает дополнительный шаг postbuild. + with patch.object(c2000.subprocess, 'run', side_effect=self.fake_tool) as calls: # Flash и hex2000 имитируются на границе процессов. + self.run_postbuild() # Архиватор и экспорт работают без подмены. + self.assertEqual(calls.call_count, 4) # Один Flash-вызов, две EEPROM-конверсии и отдельный RS BIN подтверждают отсутствие рекурсивного Make. + folder = self.export / 'NOGIT000_2026-10-14_16-00-00_UTC+3' # Имя следует времени prebuild с переводом в московский UTC+3. + for directory in (self.source.parent, self.output, folder): # Проверяет копию для CCS, плоский выпуск и архив для GUI. + self.assertEqual((directory / 'Firmware_flash.out').read_bytes(), b'current Flash image') # Каждая копия содержит новый Flash COFF. + self.assertTrue((directory / 'Firmware_flash.map').is_file()) # Карта Flash не теряется при сохранении или экспорте. + for name in ('Firmware_flash.out', 'Firmware_NOGIT000.bin', 'Firmware_flash_rs.bin'): # Контрольные суммы каждого варианта должны проверяться независимо. + verify(folder / name, folder / (name + '.manifest.json')) # Использует реальные SHA-256 экспортированных байтов. + self.assertEqual((folder / self.source.name).read_bytes(), b'RAM image') # Архив сохраняет исходный RAM OUT вместе с новым Flash OUT. + + def test_failed_or_incomplete_builder_cannot_export_stale_flash(self): # Ошибка или отсутствие карты должны остановить выпуск до экспорта старого COFF. + (self.build.parent / 'build_flash.py').write_text('# Подключён неисправный сборщик для проверки отказа.\n', encoding='utf-8') # Включает путь Flash-проверки. + stale = self.source.with_name('Firmware_flash.out') # В Bin уже есть образ от предыдущей успешной сборки. + stale.write_bytes(b'old Flash image') # Отличимые байты выявят ошибочную повторную публикацию. + for failure in (subprocess.CalledProcessError(1, 'builder'), None): # Проверяет ненулевой код и ложный успех без обязательных результатов. + with self.subTest(failure=failure): # Даёт отдельную диагностику двум независимым отказам. + with patch.object(c2000.subprocess, 'run', side_effect=failure) as calls: # Сборщик либо падает, либо не создаёт файлов. + with self.assertRaises((subprocess.CalledProcessError, ValueError)): # Оба отказа должны выйти наружу как ошибка postbuild. + self.run_postbuild() # Не разрешает продолжение EEPROM-конверсии после сбоя Flash. + self.assertEqual(calls.call_count, 1) # После отказа Flash ни hex2000, ни новый сборщик не запускаются. + self.assertEqual(stale.read_bytes(), b'old Flash image') # Предыдущий образ сохраняется, но не считается новым результатом. + self.assertFalse(self.export.exists()) # Неполная сборка не создаёт выпуск для GUI. + + +if __name__ == '__main__': # Позволяет запускать проверки отдельно или через unittest discover. + unittest.main() # Возвращает ненулевой код при нарушении контракта упаковки или экспорта. diff --git a/c/firmware-info/tests/test_version_iterator.py b/c/firmware-info/tests/test_version_iterator.py new file mode 100644 index 0000000..deb7cc8 --- /dev/null +++ b/c/firmware-info/tests/test_version_iterator.py @@ -0,0 +1,83 @@ +"""Проверяет общий сохраняемый итератор версии до компиляции CCS, Keil и CLI.""" # Запуск: python -m unittest discover -s c/firmware-info/tests -p test_version_iterator.py. +import importlib.util # Загружает тот же генератор, который вызывается штатными BAT templates. +import json # Проверяет исходный JSON и метаданные после резервирования версии. +from pathlib import Path # Изолирует проверочные настройки и generated во временном каталоге. +import tempfile # Удаляет только собственные файлы после каждой проверки. +import unittest # Проверяет последовательность номеров, ручной режим и отказы записи. +from unittest.mock import patch # Воспроизводит ошибки файловой системы без изменения прав пользователя. +TOOL = Path(__file__).resolve().parents[1] / "tools/identity.py" # Находит общую реализацию относительно файла теста. +spec = importlib.util.spec_from_file_location("shared_iterator", TOOL) # Не импортирует проектные обёртки или другой генератор из PATH. +identity = importlib.util.module_from_spec(spec) # Создаёт отдельный экземпляр модуля для изолированной подмены отказов. +spec.loader.exec_module(identity) # Загружает функции без выполнения CLI и без изменения рабочих версий. + + +class VersionIteratorTests(unittest.TestCase): # Проверяет поведение общего prepare независимо от IDE. + def setUp(self): # Готовит настройки другого изделия только во временном каталоге. + temporary = tempfile.TemporaryDirectory(prefix="shared iterator ") # Пробелы в пути не должны влиять на атомарную запись настроек. + self.addCleanup(temporary.cleanup) # Удаляет временные файлы даже после ожидаемого отказа генерации. + self.root = Path(temporary.name) # Ограничивает все изменения проверки собственным каталогом. + self.config = self.root / "config.json" # Отделяет исходную настройку от generated/firmware_identity.json. + self.output = self.root / "generated" # Моделирует отдельный каталог текущей конфигурации сборки. + self.settings = {"product": "Другое изделие", "target": "host", "version": [1, 0, 4], "increment_version": True, "extra": {"keep": "настройка"}} # Дополнительное поле проверяет сохранность проектных настроек в UTF-8. + self.save() # Устанавливает номер, на котором обнаружилась остановка прямого подключения. + + def save(self): # Сохраняет выбранные входные настройки для текущего сценария. + self.config.write_text(json.dumps(self.settings, ensure_ascii=False), encoding="utf-8") # Не использует рабочий счётчик какого-либо проекта. + + def prepare(self): # Запускает публичный общий API с детерминированным состоянием Git. + with patch.object(identity, "git_state", return_value={"commit": None, "dirty": None}): # Доступ к Git не влияет на проверку счётчика. + return identity.prepare(self.root, self.root, self.config, self.output) # Вызывает тот же prepare, что CCS, Keil и CLI. + + def test_sequence_and_matching_outputs(self): # Воспроизводит увеличение после 1.0.4 и отсутствие повторного номера. + for expected in ([1, 0, 5], [1, 0, 6]): # Каждый общий pre-build должен занимать ровно один номер. + metadata = self.prepare() # Генерирует реальный заголовок и JSON после атомарного резервирования. + settings = json.loads(self.config.read_text(encoding="utf-8")) # Читает сохранённый источник следующей версии. + self.assertEqual(settings["version"], expected) # Проверяет увеличение исходного JSON, а не только отображаемой версии. + self.assertEqual(settings["extra"], self.settings["extra"]) # Сохраняет неизвестные общему генератору поля проекта. + self.assertEqual(metadata["version"], expected) # Возвращаемые метаданные содержат уже занятый номер. + self.assertEqual(json.loads((self.output / "firmware_identity.json").read_text(encoding="utf-8"))["version"], expected) # Сохранённый паспорт совпадает с источником версии. + self.assertIn(f"#define FIRMWARE_VERSION_PATCH {expected[2]}U", (self.output / "firmware_identity.h").read_text(encoding="utf-8")) # Компилятор получает тот же patch, что manifest. + + def test_manual_mode_preserves_config_bytes(self): # Старые проекты без флага и явно отключённый итератор сохраняют ручную версию. + for enabled in (None, False): # None обозначает отсутствие поля, а не допустимое значение JSON-флага. + self.settings.pop("increment_version", None) # Сначала моделирует старую конфигурацию без нового переключателя. + if enabled is False: self.settings["increment_version"] = False # Затем проверяет явное отключение без удаления поля. + self.save() # Записывает исходный формат, который генератор не должен переформатировать. + original = self.config.read_bytes() # Сравнивает байты, чтобы заметить любую лишнюю запись. + self.assertEqual(self.prepare()["version"], [1, 0, 4]) # Ручной номер используется без увеличения. + self.assertEqual(self.config.read_bytes(), original) # Исходный JSON остаётся побайтно прежним. + + def test_carry_and_exhaustion(self): # Проверяет ограничения трёх разрядов контракта firmware-info v1. + for previous, expected in (([1, 0, 999], [1, 1, 0]), ([1, 255, 999], [2, 0, 0])): # Patch переносится после 999, minor после 255. + self.settings["version"] = previous # Задаёт последнюю версию перед границей разряда. + self.save() # Передаёт граничное значение публичному prepare через JSON. + self.assertEqual(self.prepare()["version"], expected) # Проверяет перенос вместе с реальной записью настроек. + self.settings["version"] = [255, 255, 999] # Устанавливает последний допустимый номер всего контракта. + self.save() # Сохраняет исходный предел перед ожидаемым отказом. + original = self.config.read_bytes() # Переполнение не должно сбрасывать номер в JSON. + with self.assertRaises(ValueError): self.prepare() # Требует явную ошибку вместо повторного использования версии. + self.assertEqual(self.config.read_bytes(), original) # Сохраняет последний занятый номер без частичной записи. + + def test_invalid_flag_does_not_change_config(self): # Не допускает неявное включение счётчика строками, числами или null. + for value in ("true", "false", 1, 0, None, [], {}): # Только JSON true и false являются допустимыми значениями переключателя. + self.settings["increment_version"] = value # Передаёт неверный тип через настоящий JSON. + self.save() # Фиксирует исходные байты для проверки отказа до резервирования. + original = self.config.read_bytes() # Ошибка настройки не должна занимать номер версии. + with self.assertRaises(ValueError): self.prepare() # Останавливает генерацию до изменения счётчика. + self.assertEqual(self.config.read_bytes(), original) # Подтверждает сохранение исходного JSON при отказе проверки. + + def test_generation_failure_consumes_number(self): # Номер неудачной попытки не должен использоваться следующей сборкой. + with patch.object(identity, "write_atomic", side_effect=OSError("header unavailable")): # Воспроизводит отказ записи заголовка после сохранения следующей версии. + with self.assertRaises(OSError): self.prepare() # Передаёт ошибку вызывающему BAT без маскировки успешным завершением. + self.assertEqual(json.loads(self.config.read_text(encoding="utf-8"))["version"], [1, 0, 5]) # Резервирование фиксируется до генерации выходных файлов. + self.assertEqual(self.prepare()["version"], [1, 0, 6]) # Следующая попытка занимает следующий номер, даже если прежняя не дошла до компиляции. + + def test_failed_config_replace_preserves_original(self): # Атомарная замена не должна портить настройки при отказе файловой системы. + original = self.config.read_bytes() # Сохраняет эталон исходного номера и остальных полей. + with patch.object(identity.Path, "replace", side_effect=PermissionError("config unavailable")): # Имитирует отказ фиксации временного файла вместо записи нового JSON. + with self.assertRaises(PermissionError): self.prepare() # Останавливает pre-build, если номер нельзя надёжно сохранить. + self.assertEqual(self.config.read_bytes(), original) # Исходные настройки не заменены частичным или неверным файлом. + self.assertEqual(list(self.root.glob(".firmware-version-*")), []) # При отказе не остаются собственные временные файлы счётчика. + + +if __name__ == "__main__": unittest.main() # Любое нарушение общего итератора возвращает ненулевой код процесса. diff --git a/c/firmware-info/tools/c2000_build.py b/c/firmware-info/tools/c2000_build.py new file mode 100644 index 0000000..c846423 --- /dev/null +++ b/c/firmware-info/tools/c2000_build.py @@ -0,0 +1,437 @@ +"""Единая подготовка паспорта и проверенного RAM/Flash-комплекта C2000 для CCS и Публикатора.""" # Сетевой выпуск выполняет отдельный Публикатор SETGUI после импорта подготовленной папки. +import argparse # Разбирает одинаковые аргументы защищённого postbuild для CCS Debug и Release. +import base64 # Декодирует точные байты секций COFF из официального XML-вывода TI ofd2000. +from datetime import datetime # Восстанавливает слова UTC из паспорта, созданного перед компиляцией. +import hashlib # Проверяет точные байты конечного BIN и сопроводительного SHA-256. +import importlib.util # Подключает штатный механизм экспорта только после проверки временного выпуска. +import json # Сверяет изделие, аппаратный профиль и идентификацию текущей сборки. +from pathlib import Path # Разрешает пути относительно выбранной конфигурации CCS, а не текущего терминала. +import re # Читает абсолютные EEPROM-символы из карты линкера TI. +import shutil # Копирует только полностью проверенные файлы из временного каталога. +import struct # Разбирает 16-битные слова SCI8 и адреса загрузочных блоков C28x. +import subprocess # Вызывает общую BAT-точку конверсии без публикации во внешнее приложение. +import tempfile # Изолирует непроверенные результаты общего postcompile от постоянных выпусков. +import xml.etree.ElementTree as ET # Проверяет фактические LOAD/RUN адреса Flash COFF без собственного двоичного парсера TI. +import sys # Запускает общий CLI и подключает конвертор без зависимости от GUI. +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / 'python')) # Контракт защищённой Flash берётся из того же checkout templates, что общий сборщик. +from protocan.f28335_flash import APP_START, APP_DATA, APP_STOP, coff_sections, validate_words # Проверяет отсутствие сектора A и описание FAB1 одинаково для COFF и SCI8. + +def numeric_define(header, name): # Читает единственное числовое C-определение без исполнения выражений из заголовка платы. + text = header.read_text(encoding="utf-8-sig") # Поддерживает UTF-8 с BOM для пользовательских заголовков конфигурации. + text = re.sub(r"/\*.*?\*/|//[^\n]*", "", text, flags=re.S) # Удаляет комментарии перед поиском настоящих директив препроцессора. + values = re.findall(r"^\s*#\s*define\s+" + re.escape(name) + r"\s+([^\n]+)", text, re.M) # Требует определение нужного макроса, а не упоминание в тексте. + if len(values) != 1 or not re.fullmatch(r"(?:0[xX][0-9a-fA-F]+|[0-9]+)[uUlL]*", values[0].strip()): # Исключает неоднозначность и выражения, которые могут отличаться от C-препроцессора. + raise ValueError(f"{header}: define {name} once as an integer") # Останавливает выпуск при неподдерживаемой структуре общей разметки. + return int(values[0].strip().rstrip("uUlL"), 0) # Преобразует десятичную либо шестнадцатеричную величину в число Python. + + +def git_state(repository): # Снимает происхождение выбранного рабочего дерева с локальным safe.directory без изменения глобальных настроек Git. + directory = repository.resolve() # Рабочий каталог CCS может быть вложен в репозиторий приложения. + trusted = next((path for path in (directory, *directory.parents) if (path / ".git").exists()), directory) # Git проверяет корень checkout; .git-файл также учитывает подключённый templates submodule. + command = ["git", "-c", "safe.directory=" + trusted.as_posix(), "-C", str(directory)] # Локальное доверие ограничено корнем явно выбранной зависимости или исходников проекта. + try: # Отсутствие Git сохраняет прежний явный NOGIT-контракт общей библиотеки. + commit = subprocess.check_output(command + ["rev-parse", "HEAD"], stderr=subprocess.DEVNULL, text=True, encoding="utf-8").strip() # Получает полный SHA именно компилируемого дерева. + dirty = bool(subprocess.check_output(command + ["status", "--porcelain", "--untracked-files=normal"], stderr=subprocess.DEVNULL, text=True, encoding="utf-8").strip()) # Учитывает новые и изменённые исходники при формировании знака плюс. + return {"commit": commit, "dirty": dirty} # Возвращает совместимую с общим генератором структуру происхождения. + except (OSError, subprocess.CalledProcessError): # Не выдаёт неизвестную ревизию за чистое дерево. + return {"commit": None, "dirty": None} # Генератор пометит такую сборку идентификатором NOGIT000. + + +# Объявляет функцию read_version и её входные параметры. +def read_version(header): + # Читает исходный файл или образ для последующей проверки и разбора. + text = header.read_text(encoding="utf-8-sig") + # Задаёт text по выражению справа; значение используется последующими операциями. + text = re.sub(r"/\*.*?\*/|//[^\n]*", "", text, flags=re.S) + # Задаёт version по выражению справа; значение используется последующими операциями. + version = [] + # Перебирает part, limit in (("MAJOR", 255), ("MINOR", 255), ("PATCH", 999)) в указанном порядке. + for part, limit in (("MAJOR", 255), ("MINOR", 255), ("PATCH", 999)): + # Задаёт name по выражению справа; значение используется последующими операциями. + name = "FIRMWARE_VERSION_" + part + # Задаёт definitions по выражению справа; значение используется последующими операциями. + definitions = re.findall(r"^\s*#\s*define\s+" + name + r"\b([^\n]*)", text, re.M) + # Проверяет условие if len(definitions) != 1 перед выполнением следующего блока. + if len(definitions) != 1: + # Останавливает текущую операцию с исключением ValueError(f"{header}: define {name} exactly once"). + raise ValueError(f"{header}: define {name} exactly once") + # Задаёт value по выражению справа; значение используется последующими операциями. + value = definitions[0].strip() + # Проверяет условие if not re.fullmatch(r"(?:0|[1-9][0-9]*)[uU]?", value) перед выполнением следующего блока. + if not re.fullmatch(r"(?:0|[1-9][0-9]*)[uU]?", value): + # Останавливает текущую операцию с исключением ValueError(f"{header}: {name} must be a decimal integer"). + raise ValueError(f"{header}: {name} must be a decimal integer") + # Задаёт number по выражению справа; значение используется последующими операциями. + number = int(value.rstrip("uU")) + # Проверяет условие if not 0 <= number <= limit перед выполнением следующего блока. + if not 0 <= number <= limit: + # Останавливает текущую операцию с исключением ValueError(f"{header}: {name} must be in 0..{limit}"). + raise ValueError(f"{header}: {name} must be in 0..{limit}") + # Продолжает текущий вызов, список или выражение: version.append(number); порядок аргументов сохраняется. + version.append(number) + # Возвращает version вызывающему коду и завершает функцию. + return version + + +def read_policy(project): # Загружает декларативные настройки памяти платы, оставляя общий алгоритм в templates. + path = project / "firmware_build_profile.json" # Профиль расположен рядом с CCS-проектом и версионируется вместе с linker-файлами. + return json.loads(path.read_text(encoding="utf-8-sig")) if path.is_file() else {} # Старые проекты 166 используют прежний JSON без обязательного нового файла. + + +def configured_version(project, settings): # Поддерживает ручной C-заголовок 167 и сохраняемый JSON-счётчик 166 одной реализацией. + header = read_policy(project).get("version_header") # Источник версии задаётся платой явно, без определения модели по имени каталога. + return read_version(project / header) if header else settings["version"] # Проверку диапазонов JSON выполняет существующий генератор identity. + + +def read_profile(project, templates, eeprom=None): # Получает физическую EEPROM из тех же C-заголовков, которыми пользуется компилятор. + policy = read_policy(project) # Все аппаратные пути и имена макросов остаются данными конкретной платы. + can_profile = policy.get("can_boot_profile") # Явное включение CAN-выпуска не меняет поведение старых проектов без этого поля. + if can_profile not in (None, "f28335-m95m02-ab"): # Поддерживаемый профиль соответствует реальному порту M95M02 с двумя слотами по 130560 октетов. + raise ValueError("Unsupported CAN boot profile: " + str(can_profile)) # Опечатка в профиле не должна незаметно отключать обязательный CAN-образ. + config = policy.get("eeprom") # Отсутствие профиля сохраняет контракт 166 с max_image_bytes в основном JSON. + if not config: # У старого проекта нет дополнительной аппаратной разметки для проверки MAP. + path = project / "firmware_identity.json" # Прямой общий postcompile также поддерживает отдельно переданный готовый паспорт. + settings = json.loads(path.read_text(encoding="utf-8-sig")) if path.is_file() else {} # Отсутствие проектной конфигурации не создаёт вымышленные ограничения памяти. + limit = settings.get("max_image_bytes") # Прежняя конфигурация 166 задаёт предел в физических октетах полного SCI8. + if limit is not None and (type(limit) is not int or limit < 24): # Не допускает отрицательную ёмкость, bool или размер меньше заголовка и терминатора SCI8. + raise ValueError("max_image_bytes must be an integer >= 24") # Не создаёт паспорт с непригодным проектным ограничением. + return {"max_image_bytes": limit} if limit is not None else {} # Старый предел EEPROM также применяется общим postbuild. + selected = numeric_define(project / config["selection_header"], config["selection_macro"]) # Читает только числовое определение, исключая исполнение текста заголовка. + variants = config["variants"] # Таблица связывает значение compiler define, название микросхемы и макрос физической ёмкости. + if str(selected) not in variants: # Неизвестное значение конфигурации не подменяется произвольным профилем. + raise ValueError("Unsupported EEPROM selection: " + str(selected)) # Ошибка возникает до компиляции и создания постоянного выпуска. + chosen = next((value for value in variants.values() if value["name"] == eeprom), None) if eeprom else variants[str(selected)] # CLI override сохраняет согласованный выбор отдельной тестовой сборки. + if chosen is None: # Неподдерживаемый профиль запрещён и при программном вызове общего модуля. + raise ValueError("Unsupported EEPROM profile: " + str(eeprom)) # Не создаёт паспорт с вымышленной ёмкостью. + layout = templates / config["layout_header"] # Разметка читается из фактически компилируемой зависимости, а не из другой копии templates. + total = numeric_define(layout, chosen["bytes_macro"]) # Ёмкость выражена физическими октетами EEPROM согласно общему C-контракту. + words = numeric_define(layout, config["param_words_macro"]) # Число параметров выражено 16-битными словами C28x и включает контрольную сумму. + limit = total - (words + 1) * 2 # Сохраняет параметры и последнее резервное слово; одно слово EEPROM занимает два октета. + if total <= 0 or total % 2 or words <= 0 or limit < 24: # Полная SCI8-таблица требует минимум 22 октета заголовка и два октета терминатора. + raise ValueError("Invalid EEPROM layout") # Не выпускает образ с отрицательной или неполной областью прошивки. + result = {"eeprom": chosen["name"], "eeprom_bytes": total, "eeprom_param_words": words, "max_image_bytes": limit, "ram_ranges": policy["ram_ranges"]} # Паспорт фиксирует аппаратный выбор и допустимые адреса приложения. + if can_profile and chosen["name"] == "M95M02": result["can_boot_profile"] = can_profile # Малая AT25256B не получает неподдерживаемый A/B-образ, даже если проект поддерживает второй аппаратный вариант. + return result # Prebuild сохраняет CAN-профиль, а postbuild проверяет его неизменность вместе с EEPROM и версией. + + +def load_identity(templates): # Загружает действующий генератор паспорта из явно выбранной библиотеки. + spec = importlib.util.spec_from_file_location("unified_identity_tools", templates / "c/firmware-info/tools/identity.py") # Обе схемы CCS используют одинаковый публичный контракт identity. + module = importlib.util.module_from_spec(spec) # Изолированный модуль не меняет импорты SETGUI и других проектов. + spec.loader.exec_module(module) # Ошибка отсутствующей зависимости возвращается вызывающему процессу до записи выпуска. + module.git_state = git_state # Локальное доверие Git ограничено выбранными рабочими деревьями без изменения глобального safe.directory. + return module # Подготовка и упаковка используют одну реализацию формата manifest. + + +def prepare(project, templates, output, eeprom=None, config=None): # Единый prebuild поддерживает исходный счётчик 166 и ручную версию 167. + project, templates, output = project.resolve(), templates.resolve(), output.resolve() # Все относительные пути фиксируются до запуска общих инструментов. + config = config.resolve() if config else project / "firmware_identity.json" # Старые BAT-вызовы могут явно передать прежний файл настроек. + settings = json.loads(config.read_text(encoding="utf-8-sig")) # Читает пользовательские поля без потери дополнительных настроек проекта. + policy, profile = read_policy(project), read_profile(project, templates, eeprom) # Физическая разметка проверяется до изменения счётчика версии. + identity = load_identity(templates) # Подключает генератор той библиотеки, которая включена в компиляцию. + if policy.get("version_header"): # Ручной заголовок остаётся единственным источником версии 167. + settings.update(version=configured_version(project, settings), increment_version=False) # Не увеличивает номер при повторном prebuild или ошибке компиляции. + with tempfile.TemporaryDirectory(prefix="c2000-identity-") as directory: # Временные настройки не переписывают пользовательский JSON. + temporary = Path(directory) / "config.json" # Временный файл нужен только публичному интерфейсу существующего генератора. + temporary.write_text(json.dumps(settings, ensure_ascii=False), encoding="utf-8") # Сохраняет ручной номер и все поля изделия в UTF-8. + metadata = identity.prepare(project, templates, temporary, output) # Генерирует прежние 12 слов паспорта без изменения протокола прошивки. + else: # Проект 166 продолжает резервировать следующий номер непосредственно в своём JSON. + metadata = identity.prepare(project, templates, config, output) # Итератор вызывается ровно один раз, сохраняя старый контракт precompile. + metadata.update(profile) # Предел EEPROM применяется и к старым проектам, и к новым аппаратным профилям. + if "eeprom_bytes" in profile: # Только явный аппаратный профиль требует сверки compiler define и происхождения разметки. + metadata["templates_root"] = str(templates) # Защищает postbuild от проверки по другой копии C-заголовков. + selection = policy["eeprom"] # Имена заголовка и макроса определены декларативным профилем платы. + value = next(key for key, item in selection["variants"].items() if item["name"] == profile["eeprom"]) # Вычисляет точное значение define для выбранной микросхемы. + guard = '\n#include "' + Path(selection["selection_header"]).name + '" /* Проверяет аппаратный профиль текущей компиляции. */\n' # Проверка включается в генерируемый C-заголовок паспорта. + guard += '#if ' + selection["selection_macro"] + ' != ' + value + ' /* Сверяет define компилятора с подготовленным паспортом. */\n#error EEPROM_profile_differs_from_prebuild /* Требует согласованную пересборку платы. */\n#endif /* Завершает проверку профиля EEPROM. */\n' # Compiler-only override не может незаметно изменить физическую разметку. + header = output / "firmware_identity.h" # Добавляет защиту после прежних констант версии и времени. + identity.write_atomic(header, header.read_text(encoding="utf-8") + guard) # Заголовок заменяется атомарно и всегда остаётся в UTF-8. + identity.write_atomic(output / "firmware_identity.json", json.dumps(metadata, ensure_ascii=False, indent=2) + "\n") # Сохраняет фактическую разметку для проверки после линковки. + return metadata # Публичный результат совместим с прежними host-тестами и проектными вызовами. + + +def convert(compiler, build_dir, artifact, metadata_path, stage, tools_templates): # Выполняет только конвертацию во временный каталог до общей проверки выпуска. + spec = importlib.util.spec_from_file_location("unified_c2000_converter", tools_templates / "c/firmware-info/tools/c2000_postbuild.py") # Использует единственную низкоуровневую реализацию hex2000 и сборки дополнительного Flash. + converter = importlib.util.module_from_spec(spec) # Изолирует импорт от старых командных точек входа и исключает рекурсивный postbuild. + sys.path.insert(0, str(tools_templates / "c/firmware-info/tools")) # Соседний identity нужен существующему конвертору при импорте. + try: # Любая ошибка конвертации остаётся внутри staged-выпуска. + spec.loader.exec_module(converter) # Загружает библиотечную функцию без запуска CLI. + source = Path(artifact) # CCS передаёт абсолютный базис OUT либо имя относительно активного BuildDirectory. + source = Path(str(source if source.is_absolute() else build_dir / source) + ".out") # Выбирает конкретный исходный файл текущей сборки. + with tempfile.TemporaryDirectory(prefix=".input-", dir=stage) as directory: # Дополнительные копии конвертора не попадают рядом с постоянным RAM OUT до проверки. + staged = Path(directory) / source.name # Имя артефакта сохраняется для штатного именования Flash и BIN. + shutil.copy2(source, staged) # Передаёт точные байты текущего COFF, сохраняя исходный файл. + converter.postbuild(compiler, build_dir, str(staged.with_suffix("")), metadata_path, stage) # Публикация и сеть отсутствуют: результаты ещё должны пройти проверки общего модуля. + finally: # Импорт другого проекта не должен наследовать временно добавленный каталог инструментов. + sys.path.pop(0) # Возвращает прежний порядок поиска Python-модулей даже при отказе TI. + + +def write_receipt(output, archive_name, image_name): # Передаёт Публикатору точную папку текущего проверенного выпуска. + value = {"schema": 1, "folder": archive_name, "manifest": image_name + ".manifest.json"} # Относительные имена сохраняют переносимость комплекта между компьютерами. + receipt = output / "latest_build.json" # Служебный указатель находится вне папки неизменяемого комплекта. + temporary = receipt.with_suffix(".tmp") # Атомарная замена не оставляет частичный JSON при прерывании записи. + temporary.write_text(json.dumps(value, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") # Записывает только локальный указатель без сетевой публикации. + temporary.replace(receipt) # Указатель меняется лишь после успешной проверки и копирования всех файлов. + + +def atomic_copy(source, destination): # Сохраняет проверенный файл без открытия старого результата на перезапись и без частичного содержимого. + destination = Path(destination) # Нормализует также строковые пути, переданные стандартным shutil.copytree. + with tempfile.NamedTemporaryFile(dir=destination.parent, prefix=".prepared-", delete=False) as stream: # Собственный временный файл наследует права каталога и находится на том же диске для атомарной замены. + temporary = Path(stream.name) # Запоминает только созданный текущим вызовом файл для безопасной очистки. + try: # Ошибка записи или замены должна оставить прежний результат пригодным для чтения. + shutil.copy2(source, temporary) # Сначала полностью записывает новые байты и сохраняет время исходного артефакта. + temporary.replace(destination) # Одной файловой операцией заменяет старый результат после успешной записи временного файла. + finally: # Незавершённый временный файл не должен попадать в будущий комплект Публикатора. + temporary.unlink(missing_ok=True) # Удаляет только собственный незавершённый файл; после успешной замены его уже нет. + return str(destination) # Сохраняет контракт copy_function стандартного shutil.copytree. + + +def verify_embedded(image, metadata, flash=False): # RAM и Flash SCI8 проверяются отдельно по разным допустимым адресам и ограничениям загрузчика. + data = image.read_bytes() # Проверяет содержимое файла, которое будет передано в EEPROM-программатор. + limit = 0xFC00 * 2 - 2 if flash else metadata.get("max_image_bytes", 0xFFFFFFFF) # RS Flash использует внешний буфер 0x200000..0x20FC00 и ещё два октета CRC; RAM BIN ограничен резервом физической EEPROM. + if not 24 <= len(data) <= limit: # Учитывает заголовки SCI8 вместе с кодом, не позволяя переписать резерв параметров либо выйти за буфер RS. + raise ValueError("SCI8 exceeds EEPROM firmware boundary or is too short") # Отвергает слишком большой BIN до создания постоянного каталога выпуска. + if data[:2] != b"\xaa\x08": # 0x08AA — обязательный ключ восьмибитной boot-таблицы TI. + raise ValueError("Invalid SCI8 header") # Не принимает HEX, COFF либо плоский дамп под видом загрузочного BIN. + stamp = datetime.fromisoformat(metadata["built_at_utc"].replace("Z", "+00:00")) # Берёт момент именно того prebuild, который подготовил C-заголовок. + build_id = metadata["build_id"] # Контракт firmware-info v1 хранит ровно восемь ASCII-символов идентификатора. + if not re.fullmatch(r"[0-9a-fA-F]{8}|[0-9a-fA-F]{7}\+|NOGIT000", build_id) or stamp.utcoffset() is None or stamp.utcoffset().total_seconds(): # Исключает неоднозначную дату и неподдерживаемый идентификатор. + raise ValueError("Invalid prebuild identity") # Требует заново выполнить prebuild вместо выпуска чужих метаданных. + words = [1, *metadata["version"], stamp.year, stamp.month * 256 + stamp.day, stamp.hour * 256 + stamp.minute, stamp.second] # Независимо восстанавливает первые восемь 16-битных регистров общего контракта. + words += [ord(build_id[index]) * 256 + ord(build_id[index + 1]) for index in range(0, 8, 2)] # Упаковывает две ASCII-октеты в каждое из четырёх слов идентификатора. + expected = struct.pack("<12H", *words) # TI SCI8 хранит каждое слово полезных данных младшей октетой вперёд. + high, low = struct.unpack_from(" len(data): # Требует полный 32-битный адрес и все октеты полезной нагрузки. + raise ValueError("Truncated SCI8 section") # Не допускает выпуск усечённой секции даже при паспорте в её начале. + high, low = struct.unpack_from("= metadata.get("max_sections", 0xFFFFFFFF): # CAN-порт F28335 принимает не более 64 секций; обычные RAM/Flash-профили сохраняют прежний контракт. + raise ValueError("SCI8 exceeds bootloader section count") # Совместимый размер файла не разрешает таблицу, которую аппаратный загрузчик не сможет разобрать. + blocks.append((address, end)) # Сохраняет проверенный диапазон для контроля следующих блоков и точки входа. + payload = data[offset + 4:offset + 4 + count * 2] # Ищет паспорт только внутри данных, исключая поля заголовка и адреса. + boot += int(flash and address == APP_START and count >= 16) # Ровно один блок содержит полный FAB1; аппаратный boot 0x33FFF6 запрещён. + loaded.update((address + index, value) for index, value in enumerate(struct.unpack("<" + "H" * count, payload))) # Фиксирует реальные 16-битные слова, которые RS-загрузчик запрограммирует во Flash. + found += sum(payload[index:index + 24] == expected for index in range(0, len(payload) - 23, 2)) # Учитывает лишь выровненные на слово экземпляры 12 регистров firmware-info. + offset += 4 + count * 2 # Переходит за полный адрес и полезные слова к следующему размеру. + raise ValueError("Missing SCI8 terminator") # Исчерпание файла без нулевого слова никогда не считается успешной конверсией. + + +def verify_package(image, metadata): # Связывает BIN, manifest и SHA-256 с тем же prebuild и аппаратной EEPROM. + manifest = json.loads(image.with_suffix(image.suffix + ".manifest.json").read_text(encoding="utf-8")) # Один контракт SHA/паспорта обслуживает отдельные RAM BIN, Flash COFF и Flash SCI8. + data = image.read_bytes() # Повторно считывает точные октеты перед постоянной публикацией. + digest = hashlib.sha256(data).hexdigest() # Вычисляет контрольную сумму независимо от общего seal. + if manifest.get("file") != image.name or manifest.get("size_bytes") != len(data) or manifest.get("sha256") != digest: # Требует согласованности имени, размера и содержимого файла. + raise ValueError("BIN does not match its manifest") # Не публикует повреждённый либо перепутанный комплект. + if any(manifest.get(key) != value for key, value in metadata.items()): # Проверяет также eeprom, физическую границу, версию и происхождение компилируемых templates. + raise ValueError("Manifest does not match prebuild identity/EEPROM") # Один лишь корректный SHA не разрешает паспорт другого аппаратного варианта. + if image.with_suffix(image.suffix + ".sha256").read_text(encoding="utf-8").strip() != f"{digest} {image.name}": # Общий sidecar содержит SHA и точное имя через два пробела. + raise ValueError("Invalid BIN SHA-256 sidecar") # Требует целостности всех трёх публикуемых файлов. + + +def verify_linker_profile(map_path, profile): # Сверяет аппаратную настройку Python с фактическими абсолютными символами линкера. + text = map_path.read_text(encoding="utf-8-sig") # MAP текущей конфигурации является обязательным результатом успешной линковки. + expected = {"_EEPROM_TOTAL_BYTES": profile["eeprom_bytes"], "_EEPROM_FIRMWARE_LIMIT_BYTES": profile["max_image_bytes"], "_EEPROM_PARAMS_START_WORD": profile["max_image_bytes"] // 2} # Символы разделяют физические октеты и адресуемые слова C28x. + for name, value in expected.items(): # Проверяет ёмкость, конец прошивки и начало сохраняемых параметров до запуска hex2000. + values = re.findall(r"^\s*(?:\w+\s+)?([0-9a-fA-F]{8})\s+" + re.escape(name) + r"\b", text, re.M) # Принимает формат глобальных TI-символов с номером страницы либо признаком ABS. + if not values or any(int(item, 16) != value for item in values): # Повторные списки MAP обязаны описывать один и тот же профиль. + raise ValueError(f"Linker EEPROM profile mismatch: {name}") # Выявляет define, переданный только компилятору или только линкеру, и устаревшую карту. + + +def verify_flash_coff(image, compiler): # Проверяет реальные секции COFF официальным TI-декодером и возвращает точные Flash-слова загрузки. + tool = compiler / "bin/ofd2000.exe" # Разбирает формат тем же установленным C2000 toolchain, который создал OUT. + document = ET.fromstring(subprocess.check_output([str(tool), "-x", str(image)], stderr=subprocess.STDOUT)) # XML содержит фактические адреса и двоичные данные секций, а не неподтверждённую соседнюю MAP. + coff = document.find(".//ti_coff") # Вариант предназначен строго для COFF ABI F28335. + if coff is None or coff.findtext("file_header/target_id") != "0x9d" or coff.findtext("file_header/exec") != "true": # Не принимает объект другого процессора, ELF либо незалинкованный модуль. + raise ValueError("Expected executable C2000 COFF Flash image") # Явно отделяет JTAG Flash OUT от обычного RAM OUT и чужих архитектур. + sections = {section.findtext("name"): section for section in coff.findall("section")} # Именованные выходные секции соответствуют отдельной Flash-карте линкера 167. + required = {".text": (APP_DATA, APP_STOP, APP_DATA, APP_STOP), ".flash_app": (APP_START, APP_DATA, APP_START, APP_DATA), "flash_rs": (0x8000, 0xC000, APP_DATA, APP_STOP), "ramfuncs": (0xC000, 0xD000, APP_DATA, APP_STOP)} # FAB1 находится в секторе H; все Flash LOAD-секции исключают постоянный сектор A, сохраняя прежние RUN-области RAM. + for name, (run_begin, run_end, load_begin, load_end) in required.items(): # Наличие автономного RAM-загрузчика и InitFlash обязательно для выпуска Flash-варианта. + section = sections.get(name) # Отсутствующая обязательная секция не маскируется другими именами или символами MAP. + if section is None: # Проверяет отдельную карту и startup, а не одно лишь расположение основного кода. + raise ValueError("Missing Flash COFF section: " + name) # Не выдаёт RAM COFF за пригодный для автономной Flash. + run, load, size = (int(section.findtext(field, "0"), 0) for field in ("physical_addr", "virtual_addr", "raw_data_size")) # Длина OFD задана физическими октетами, оба адреса — 16-битными словами CPU. + if not size or size % 2 or not run_begin <= run < run + size // 2 <= run_end or not load_begin <= load < load + size // 2 <= load_end or (name == ".flash_app" and size != 32): # FAB1 занимает ровно 16 слов; прочие секции целиком помещаются в разрешённых LOAD/RUN-областях ниже сектора A. + raise ValueError("Invalid Flash COFF LOAD/RUN section: " + name) # Отвергает stale linker, размещение API во Flash во время стирания и аппаратный вход вне 0x33FFF6. + loaded = {} # Сопоставляет слова всех загружаемых Flash-секций с будущей SCI8-таблицей RS. + for section in sections.values(): # Служебные debug/copy-секции адреса ноль в программирование не входят. + address = int(section.findtext("virtual_addr", "0"), 0) # Для COFF TI это загрузочный адрес содержимого секции. + raw = section.findtext("raw_data") # Пустая .ebss, NOLOAD или DSECT не задаёт байтов прошивки. + if raw is None or not 0x300000 <= address < 0x340000: # Не включает отладочные записи, ROM-таблицы и рабочую RAM в образ Flash. + continue # Права оставшихся загружаемых Flash-слов дополнительно проверит общий SCI8-валидатор. + data = base64.b64decode(raw) # Получает именно те октеты, которые записаны в COFF и должны оказаться в Flash SCI8. + if len(data) % 2: # Любая программируемая секция C28x должна содержать целые 16-битные слова. + raise ValueError("Odd Flash COFF section size") # Не допускает неоднозначную упаковку образа RS. + for index, value in enumerate(struct.unpack("<" + "H" * (len(data) // 2), data)): # Восстанавливает little-endian представление каждого физического слова COFF. + if address + index in loaded: # Два выходных диапазона не должны программировать одно слово повторно. + raise ValueError("Overlapping Flash COFF load sections") # Проверяет реальный OUT независимо от доверия к линкерной карте. + loaded[address + index] = value # Сохраняет ожидаемые данные для независимого сравнения с hex2000. + entry = int(coff.findtext("optional_file_header/entry_point", "0"), 0) # Получает реальную точку входа C runtime из заголовка COFF. + if entry not in loaded or not 0x300000 <= entry < 0x33FF80: # C startup должен находиться в полностью загружаемой исполняемой Flash. + raise ValueError("Flash COFF entry is not loaded") # Исключает OUT со старой RAM-точкой входа или отрезанным startup. + checked_entry, checked_loaded, _ = coff_sections(document) # Общий декодер дополнительно отвергает любой загружаемый RAW вне области приложения, включая OTP и RAM. + if checked_entry != entry or checked_loaded != loaded: raise ValueError('Flash COFF load data mismatch') # Ни одна секция не должна быть потеряна при независимом обходе OFD XML. + validate_words(entry, loaded) # Проверяет FAB1 и CRC по полному согласованному COFF-образу. + return entry, loaded # Полное сравнение с SCI8 обнаружит конверсию другого OUT, потерю секции или подмену одного слова. + + +def verify_flash_release(stage, artifact, metadata, compiler, identity, required=False): # Проверяет и отдельно маркирует Flash COFF/SCI8 в staged-выпуске до любого постоянного копирования. + base = Path(artifact.replace("\\", "/")).name # Использует исходное имя артефакта CCS без директории и расширения OUT. + coff, serial = stage / (base + "_flash.out"), stage / (base + "_flash_rs.bin") # JTAG COFF и RS SCI8 являются разными формами одного отдельного Flash-варианта. + if not coff.exists() and not serial.exists() and not required: # Проекты без build_flash.py и host-фикстуры сохраняют прежний защищённый выпуск RAM. + return # Наличие обычного RAM BIN само по себе не объявляет поддержку Flash. + if not coff.is_file() or not serial.is_file(): # Сборка Flash должна выпустить оба согласованных артефакта. + raise ValueError("Incomplete Flash COFF/SCI8 release") # Не экспортирует один старый OUT вместе с новым RAM-выпуском. + verify_linker_profile(coff.with_suffix(".map"), metadata) # Flash использует физическую EEPROM для параметров и не меняет её профиль при размещении кода внутри CPU. + if verify_flash_coff(coff, compiler) != verify_embedded(serial, metadata, flash=True): # Сравнивает entry и каждое загрузочное слово официального COFF с результатом hex2000. + raise ValueError("Flash SCI8 does not match its COFF") # Отклоняет stale конверсию даже при правильных независимых SHA-файлах. + pairs = [(path, "COFF") for path in stage.rglob(coff.name)] + [(path, "SCI8-FLASH") for path in stage.rglob(serial.name)] # Включает плоские результаты и все их копии внутри текущего архива. + for path, kind in pairs: # Сначала проверяет весь исходный комплект, не меняя даже временных паспортов при первом отказе. + verify_package(path, metadata) # Общий postcompile обязан сохранить текущие version/EEPROM/SHA для каждого результата. + if path.read_bytes() != (coff if kind == "COFF" else serial).read_bytes(): # Архивированная копия должна быть побайтно тем же проверенным вариантом. + raise ValueError("Flash archive differs from staged release") # Не позволяет экспортировать чужой Flash внутри корректного RAM-архива. + with tempfile.TemporaryDirectory(prefix=".variant-", dir=stage) as directory: # Вариантные JSON нужны только для подписи разных форматов и не попадают в постоянный выпуск. + metadata_path = Path(directory) / "metadata.json" # Общий seal принимает обычный путь и не требует изменения соседнего templates. + for path, kind in pairs: # Только проверенные Flash-файлы получают явный признак исполнения и транспортный формат. + specific = dict(metadata, execution="FLASH", image_format=kind, boot_contract="f28335-universal-v1", boot_protected=True, flash_app_start=APP_START, flash_app_stop=APP_STOP) # Паспорт явно отличает защищённое приложение от старого самостоятельного Flash; аппаратная EEPROM сохраняется отдельно. + metadata_path.write_text(json.dumps(specific, ensure_ascii=False), encoding="utf-8") # Сохраняет все поля происхождения и ручную версию из общего prebuild. + identity.seal(path, metadata_path) # Переподписывает конкретный COFF либо SCI8 с явным execution=FLASH только после проверки байтов. + verify_package(path, specific) # Подтверждает согласованность готового вариантного manifest и SHA перед публикацией. + + +def create_can_release(stage, image, metadata, map_path, identity): # Добавляет отдельный CAN BIN только после проверки текущего RAM-образа и его интеграции с загрузчиком. + if not metadata.get("can_boot_profile"): return None # Старые проекты и AT25256B продолжают выпускаться без дополнительного неподдерживаемого файла. + if metadata["can_boot_profile"] != "f28335-m95m02-ab" or metadata.get("target") != "TMS320F28335" or metadata.get("eeprom") != "M95M02": # Профиль связан с конкретными процессором, памятью и A/B-портом. + raise ValueError("CAN profile requires TMS320F28335 with M95M02") # Запрещает переименование произвольного RAM либо Flash BIN в пригодный CAN-образ. + limits = dict(metadata, max_image_bytes=130560, ram_ranges=[[0x8000, 0xE000]], max_sections=64) # Ограничения взяты из f28335_boot_store: длина в октетах, адреса в 16-битных словах CPU. + _entry, loaded = verify_embedded(image, limits) # Проверяет SCI8, паспорт, entry, все секции, перекрытия и защиту RAM загрузчика. + symbols = map_path.read_text(encoding="utf-8", errors="replace") # Использует MAP именно активной линковки, уже проверенный по профилю EEPROM. + for name in ("_F28335CanBoot_Init", "_F28335CanBoot_Ready", "_F28335CanBoot_Service", "_F28335CanBoot_RxISR"): # CAN-приложение должно содержать инициализацию, готовность, основной сервис и обработчик приёма. + matches = re.findall(r"^\s*\d+\s+([0-9a-fA-F]{8})\s+" + re.escape(name) + r"\s*$", symbols, re.M) # Читает адреса экспортированных TI-символов, исключая простые упоминания имени в описании секции. + if not matches or any(int(address, 16) not in loaded for address in matches): # Требует присутствие hook в загружаемом payload текущего BIN, а не только в произвольном MAP. + raise ValueError("CAN application hook missing from SCI8/MAP: " + name) # Старое приложение без READY/CONFIRM нельзя выпускать как автоматически пригодное для CAN A/B. + specific = dict(metadata, execution="RAM", image_format="SCI8-RAM", transport="can", protocol="ProtoCAN Boot", product_type=0x2833, hardware_min=1, hardware_max=1) # Паспорт отделяет CAN от RS Flash и сохраняет прежние ручную версию, SHA и аппаратную идентичность. + can_image = image.with_name(image.stem + "_can.bin") # Отдельный суффикс однозначно показывает назначение файла, сохраняя имя артефакта и Build ID. + can_image.write_bytes(image.read_bytes()) # По CAN передаётся та же полная SCI8-таблица RAM без нового заголовка или изменения адресов секций. + with tempfile.TemporaryDirectory(prefix=".can-metadata-", dir=stage) as directory: # Вариантный паспорт не подменяет исходные метаданные компиляции. + metadata_path = Path(directory) / "metadata.json" # Общий seal читает отдельный временный JSON для конкретного транспортного файла. + metadata_path.write_text(json.dumps(specific, ensure_ascii=False), encoding="utf-8") # Русские поля пользовательского паспорта сохраняются в UTF-8. + identity.seal(can_image, metadata_path) # Создаёт собственные manifest и SHA-256 с точным именем CAN BIN. + verify_package(can_image, specific) # До публикации сверяет все поля нового паспорта и точные байты файла. + archive = stage / identity.build_folder_name(metadata) # Дополняет тот же архив текущей сборки, который уже содержит обычный RAM и варианты Flash. + if not archive.is_dir(): raise ValueError("CAN release requires the current build archive") # Не создаёт отдельный неполный выпуск, который не попадёт в штатный экспорт GUI. + for file in (can_image, can_image.with_suffix(".bin.manifest.json"), can_image.with_suffix(".bin.sha256")): # Все три файла должны одновременно попасть в плоский выпуск и архив. + shutil.copy2(file, archive / file.name) # Копирование ещё выполняется внутри временного staged-комплекта без изменения предыдущих выпусков. + verify_package(archive / can_image.name, specific) # Проверяет архивную копию до копирования в output и каталог GUI. + return can_image # Вызывающий выводит точное имя только после успешного завершения всего защищённого postbuild. + + +def arrange_release(stage, archive_name, artifact, image_name, can_image, target=None): # Получает target проверенного паспорта; необязательный параметр сохраняет прежнюю раскладку старых вызовов. + primary_purpose = "flash" if target == "TMS320F2812" else "eeprom" # F2812 хранит основной SCI8-образ во внешней параллельной Flash; для остальных целей сохраняем EEPROM. + base = Path(artifact.replace("\\", "/")).name # Использует базовое имя CCS, включая случай абсолютного BuildArtifactFileBaseName. + routes = {base + "_flash.out": "flash", base + "_flash.map": "flash", base + "_flash_rs.bin": "rs"} # OUT и карта относятся к JTAG, а отдельный SCI8 Flash BIN передаётся последовательным загрузчиком. + if can_image is not None: routes[can_image.name] = "can" # CAN получает только вариант, прошедший ограничения A/B-слота и проверку прикладных hooks. + shutil.copy2(stage / archive_name / "firmware_identity.json", stage / "firmware_identity.json") # Общий паспорт связывает четыре папки как в текущем локальном выпуске CCS, так и в его неизменяемом архиве. + for folder in (stage / archive_name, stage): # Сначала перестраивает архив, затем плоские результаты того же временного выпуска. + for file in tuple(folder.iterdir()): # Снимок списка исключает повторную обработку создаваемых папок назначения. + if not file.is_file() or file.name == "firmware_identity.json": continue # Архив и исходный общий паспорт остаются на своём уровне без дублирования между назначениями. + purpose = next((route for name, route in routes.items() if file.name == name or file.name.startswith(name + ".")), primary_purpose) # Manifest, SHA, карты и основной OUT/HEX следуют назначению данного процессора; отдельные варианты сохраняют свои маршруты. + destination = folder / purpose # Одинаковые четыре назначения применяются к локальному CCS-выпуску и экспортируемому архиву. + destination.mkdir(exist_ok=True) # Пустая папка неподдержанного CAN/Flash не создаётся и не обещает отсутствующего образа. + file.replace(destination / file.name) # Перемещает только внутри временного stage, не затрагивая ранее опубликованные файлы. + return (Path(primary_purpose) / image_name).as_posix() # Указатель последней сборки и экспорт получают фактическую папку основного BIN, включая flash для F2812. + + +def publish(project, templates, tools_templates, compiler, build_dir, artifact, map_path, output, export=None, eeprom=None): # Выпускает только проверенные результаты конкретной конфигурации CCS. + project, templates, tools_templates = project.resolve(), templates.resolve(), tools_templates.resolve() # Фиксирует выбранные исходники и инструменты независимо от рабочего каталога терминала. + build_dir, compiler = build_dir.resolve(), compiler.resolve() # Общая BAT-точка получает полные пути текущих компилятора и Debug/Release. + metadata_path = build_dir / "generated/firmware_identity.json" # Использует паспорт, подготовленный до компиляции этой конфигурации. + metadata = json.loads(metadata_path.read_text(encoding="utf-8")) # Отсутствующий prebuild останавливает работу до создания выпуска. + profile = read_profile(project, templates, eeprom) # Повторно читает текущий выбор EEPROM и общий резерв параметров. + settings = json.loads((project / "firmware_identity.json").read_text(encoding="utf-8-sig")) if (project / "firmware_identity.json").is_file() else metadata # Сверяет product и target с действующим проектом. + expected = {"product": settings["product"], "target": settings["target"], "version": configured_version(project, settings), **({"templates_root": str(templates)} if "eeprom_bytes" in profile else {}), **profile} # Ручной номер и аппаратный вариант обязаны совпадать с prebuild. + if any(metadata.get(key) != value for key, value in expected.items()) or metadata.get("can_boot_profile") != profile.get("can_boot_profile"): # Включение и отключение CAN после prebuild также требуют пересборки, как изменение версии, EEPROM или зависимости. + raise ValueError("Configuration changed: run prebuild and rebuild before publishing") # Требует пересборку вместо подмены старых метаданных. + verify_linker_profile(map_path.resolve(), profile) if "eeprom_bytes" in profile else None # Проверяет аппаратный выбор линкера, который нельзя вывести только из Python-конфигурации. + with tempfile.TemporaryDirectory(prefix=".verified-release-", dir=build_dir) as directory: # Единственное место, куда общий postcompile пишет до подтверждения пригодности BIN. + stage = Path(directory) # Изолирует все архивы и промежуточные HEX от постоянных каталогов выпуска. + convert(compiler, build_dir, artifact, metadata_path, stage, tools_templates) # Любая ошибка TI или общей библиотеки прерывает публикацию. + image_name = Path(artifact.replace("\\", "/")).name + "_" + metadata["build_id"] + ".bin" # Повторяет штатное имя конкретного образа, не сканируя старые BIN. + image = stage / image_name # Проверяет только результат текущего вызова конвертора. + verify_embedded(image, metadata) # Обязательные проверки EEPROM, полной SCI8-таблицы и реально встроенных 12 слов. + verify_package(image, metadata) # Сверяет SHA и весь паспорт, включая физический профиль EEPROM. + for archived in stage.rglob(image_name): # Проверяет также копии внутри текущего архива перед их публикацией или export. + verify_package(archived, metadata) # Архив обязан содержать те же байты и профиль, что плоский выпуск. + spec = importlib.util.spec_from_file_location("release_identity_tools", tools_templates / "c/firmware-info/tools/identity.py") # Подключает существующий формат именования и экспорта архива без копирования реализации. + identity = importlib.util.module_from_spec(spec) # Создаёт отдельный модуль инструментов, не подменяя компилируемую зависимость паспорта. + spec.loader.exec_module(identity) # Ошибка подключения остаётся внутри временного этапа до постоянных файлов. + verify_flash_release(stage, artifact, metadata, compiler, identity, required=(project / "build_flash.py").is_file()) # Отдельная Flash-сборка требует собственного безопасного COFF/SCI8 и не ослабляет прежние RAM-проверки. + can_image = create_can_release(stage, image, metadata, map_path, identity) # Автоматически создаёт и проверяет CAN-вариант до переноса любого результата в постоянный выпуск. + archive_name = identity.build_folder_name(metadata) # Сохраняет принятые имена архивов с ревизией, признаком изменений и временем UTC+3. + if not (stage / archive_name / image_name).is_file(): # Полный архив является обязательным результатом общей конверсии, а не необязательной старой папкой. + raise ValueError("Common postcompile did not produce the current build archive") # Не публикует неполный комплект без OUT, MAP и паспорта текущего выпуска. + image_name = arrange_release(stage, archive_name, artifact, image_name, can_image, target=metadata["target"]) # Выбираем папку по проверенному target текущей компиляции до копирования в проект и каталог экспорта. + output = output.resolve() # Постоянный каталог появляется только после всех проверок staged-комплекта. + output.mkdir(parents=True, exist_ok=True) # Прежние проверенные выпуски сохраняются при добавлении нового. + for item in sorted(stage.iterdir(), key=lambda item: item.is_dir()): # Переносит только файлы и архив, созданные данным postcompile. + if item.is_dir(): # Архив содержит сопроводительные результаты той же сборки. + shutil.copytree(item, output / item.name, dirs_exist_ok=True, copy_function=atomic_copy) # Сохраняет только проверенный архив с атомарной заменой файлов при повторном выпуске той же компиляции. + else: # Общие служебные файлы, если они появятся, сохраняются в корне текущего выпуска. + atomic_copy(item, output / item.name) # Не открывает старые файлы другой ветки на перезапись и не оставляет частичный BIN/HEX при отказе записи. + verify_package(output / image_name, metadata) # Подтверждает отсутствие повреждения при копировании на постоянный диск. + if export is not None: # Копирование в каталог GUI выполняется последним и лишь для прошедшего проверки архива. + identity.export_build(output / archive_name, export.resolve(), image_name) # Использует общий экспорт уже проверенного локального выпуска. + print(f"[firmware-build] Verified {profile.get('eeprom', settings['target'])} BIN: {output / image_name}") # Показывает пригодный аппаратный профиль и точный путь конечного файла. + if can_image is not None: print(f"[firmware-build] CAN BIN: {output / 'can' / can_image.name}") # После успешного выпуска показывает файл из отдельной папки ProtoCAN. + write_receipt(output, archive_name, image_name) # Фиксирует точную папку выпуска для импорта Публикатором без поиска по времени. + return output / image_name # Даёт тестам и внешним средствам однозначный результат без поиска по времени. + + +def main(argv=None): # Общая точка входа CCS и старых BAT: подготовка и проверка не выполняют сетевую публикацию. + parser = argparse.ArgumentParser(description="Единая подготовка C2000 для CCS и Публикатора SETGUI") # Показывает назначение обеих команд пользователю терминала. + parser.add_argument("command", choices=("prepare", "build")) # Разделяет резервирование версии до компиляции и проверку готового OUT после неё. + for name in ("project", "templates", "tools-templates", "config", "compiler", "build-dir", "metadata", "map", "output", "export"): # Все пути передаются явно или выводятся из публичных соглашений CCS. + parser.add_argument("--" + name, type=Path) # Path исключает интерпретацию аргументов через командную оболочку. + parser.add_argument("--artifact") # Базовое имя OUT передаётся без расширения как штатный макрос CCS. + parser.add_argument("--eeprom", choices=("AT25256B", "M95M02")) # Сохраняет существующий явный выбор тестового аппаратного профиля. + args = parser.parse_args(argv) # Ошибки аргументов завершают процесс до любых изменений версии или файлов выпуска. + tools = Path(__file__).resolve().parents[3] # В полной библиотеке модуль расположен в c/firmware-info/tools. + project = (args.project or (args.build_dir.parent if args.build_dir else Path.cwd())).resolve() # Старый postcompile определяет проект по родителю Debug/Release. + config = args.config or project / "firmware_identity.json" # Старый JSON 166 остаётся совместимым без обязательной миграции. + if args.command == "build" and not config.is_file() and args.build_dir: # Прямой postcompile допускает подготовленный паспорт без отдельного пользовательского JSON. + config = args.metadata or args.build_dir / "generated/firmware_identity.json" # В таком случае доступные проверки определяются реальными метаданными компиляции. + settings = json.loads(config.read_text(encoding="utf-8-sig")) # Изделие и зависимости определяются настройками проекта, а не текущим каталогом. + templates = args.templates or (config.parent / settings["templates"] if settings.get("templates") else tools) # Поддерживает относительный путь общей библиотеки старых проектов. + if args.command == "build" and not args.templates and args.build_dir: # Старый BAT postcompile не передаёт отдельный путь компилируемых исходников templates. + previous = json.loads((args.metadata or args.build_dir / "generated/firmware_identity.json").read_text(encoding="utf-8")) # Использует точный путь, зафиксированный prebuild активной конфигурации. + templates = Path(previous.get("templates_root", templates)) # Проверки EEPROM читают те же заголовки даже при отдельном полном checkout инструментов. + try: # Возвращает CCS ненулевой код при отказе любой проверки. + if args.command == "prepare": # Prebuild вызывается ровно один раз перед компиляцией паспорта. + prepare(project, templates, args.output or args.build_dir / "generated", args.eeprom, config) # При ручной версии исходный JSON не меняется. + else: # Postbuild получает уже подготовленный паспорт текущей конфигурации. + if not args.compiler or not args.build_dir or not args.artifact: # Нельзя подменить отсутствующий артефакт произвольным старым файлом из каталога. + parser.error("build requires --compiler, --build-dir and --artifact") # Показывает обязательные параметры до запуска TI. + metadata = args.build_dir / "generated/firmware_identity.json" # Основное расположение совпадает с прежними конфигурациями CCS. + if args.metadata and args.metadata.resolve() != metadata.resolve(): # Защищённый выпуск использует только паспорт активной конфигурации. + raise ValueError("metadata must belong to the selected build directory") # Не принимает паспорт другой сборки с совпадающим номером версии. + image = Path(args.artifact) # Путь карты по умолчанию находится рядом с выбранным OUT. + image = image if image.is_absolute() else args.build_dir / image # Относительные артефакты разрешаются от BuildDirectory. + publish(project, templates, args.tools_templates or tools, args.compiler, args.build_dir, args.artifact, args.map or image.with_suffix(".map"), args.output or args.build_dir / "firmware", args.export, args.eeprom) # Подготовленный комплект передаётся Публикатору отдельно от сетевых действий. + except (OSError, ValueError, KeyError, TypeError, struct.error, subprocess.CalledProcessError) as error: # Ошибки формата, зависимостей и компилятора не скрываются успешным завершением сборки. + parser.exit(1, f"[firmware-build] ERROR: {error}\n") # Краткая причина остаётся видна в Console CCS. + return 0 # Успех подтверждает подготовку проверенного локального комплекта. + + +if __name__ == "__main__": # Импорт из проектного адаптера или тестов не запускает сборку. + raise SystemExit(main()) # Возвращает командной оболочке фактический результат подготовки. diff --git a/c/firmware-info/tools/c2000_postbuild.py b/c/firmware-info/tools/c2000_postbuild.py index 8bd0c26..7fe3900 100644 --- a/c/firmware-info/tools/c2000_postbuild.py +++ b/c/firmware-info/tools/c2000_postbuild.py @@ -10,11 +10,25 @@ import json from pathlib import Path import re import subprocess +import sys # Запускает проектный сборщик тем же Python, которым выполняется общий postbuild. import tempfile from identity import archive_build, seal, verify +def build_flash_variant(compiler: Path, build_dir: Path, source: Path, stage: Path) -> tuple: # Возвращает файлы дополнительного Flash-образа только для проектов с явным сборщиком. + builder = build_dir.resolve().parent / "build_flash.py" # Соглашение CCS: Debug/Release расположены рядом с проектным сценарием сборки Flash. + if not builder.is_file(): # Отсутствие сценария оставляет прежний выпуск EEPROM без дополнительных требований к проекту. + return () # Пустой список не добавляет Flash-файлы в архив обычного проекта. + image = stage / (source.stem + "_flash.out") # Отдельное имя и временный каталог исключают подмену RAM-образа и использование устаревшего Flash-файла. + subprocess.run([sys.executable, str(builder), "--postbuild", "--compiler", str(compiler.resolve()), "--build-dir", str(build_dir.resolve()), "--output", str(image)], cwd=build_dir, check=True) # Режим postbuild использует уже собранные объекты и запрещает повторный запуск Make. + files = (image, image.with_suffix(".map")) # Карта линковки сопровождает COFF и позволяет проверить адрес аппаратной точки входа. + for file in files: # Оба результата должны быть выпущены текущим вызовом сборщика. + if not file.is_file() or not file.stat().st_size: # Успешный код процесса без непустого результата не считается успешной сборкой. + raise ValueError(f"Flash builder produced no file: {file}") # Ошибка останавливает postbuild до архивирования или экспорта неполного выпуска. + return files # Передаёт проверенные файлы вызывающему шагу для подписи и сохранения. + + def postbuild(compiler: Path, build_dir: Path, artifact: str, metadata: Path, output: Path, export: Path = None) -> Path: # CCS may include the configured output directory in this macro. @@ -47,6 +61,7 @@ def postbuild(compiler: Path, build_dir: Path, artifact: str, stage = Path(temporary) hex_image = stage / (artifact + ".hex") bin_image = stage / (artifact + "_" + build_id + ".bin") + flash_files = build_flash_variant(compiler, build_dir, source, stage) # Сначала собирает дополнительный Flash-вариант; его ошибка не допускает выпуск нового BIN. for image, mode in ((hex_image, "-i"), (bin_image, "-b")): subprocess.run([str(tool), str(source), "-boot", "-sci8", "-map", str(image.with_suffix(image.suffix + ".map")), @@ -55,13 +70,32 @@ def postbuild(compiler: Path, build_dir: Path, artifact: str, raise ValueError(f"hex2000 produced no image: {image}") seal(bin_image, metadata) verify(bin_image, bin_image.with_suffix(bin_image.suffix + ".manifest.json")) + if flash_files: # Проекты со сборщиком получают независимую проверку точных байтов Flash-образа. + seal(flash_files[0], metadata) # Использует тот же паспорт prebuild для второго варианта этой сборки. + verify(flash_files[0], flash_files[0].with_suffix(".out.manifest.json")) # Проверяет размер и SHA-256 перед сохранением результатов. + serial_image = stage / (artifact + "_flash_rs.bin") # Отдельный SCI8 BIN содержит Flash-адреса и предназначен только для новой команды записи по RS. + serial_map = serial_image.with_suffix('.bin.map') # Карта конверсии позволяет отличить Flash-адреса от EEPROM/RAM BIN. + subprocess.run([str(tool), str(flash_files[0]), '-boot', '-sci8', '-map', str(serial_map), '-o', str(serial_image), '-b'], check=True) # Конвертирует именно Flash COFF с загрузочными адресами секций. + if not serial_image.is_file() or not serial_image.stat().st_size: # Пустая конверсия не должна попасть в выпуск либо каталог GUI. + raise ValueError(f'hex2000 produced no Flash RS image: {serial_image}') # Передаёт ошибку конверсии общему postcompile. + seal(serial_image, metadata) # Привязывает RS BIN к той же версии, ревизии и времени текущего prebuild. + verify(serial_image, serial_image.with_suffix('.bin.manifest.json')) # Проверяет точные байты перед копированием в Bin и архив. + flash_files += (serial_image, serial_map, serial_image.with_suffix('.bin.manifest.json'), serial_image.with_suffix('.bin.sha256')) # Включает транспортный BIN, карту и контрольные файлы в общий выпуск Flash. + for file in flash_files: # Сохраняет COFF и карту также рядом с обычным OUT для выбора в CCS. + destination = source.parent / file.name # Каталог исходного OUT задаёт место назначения без путей конкретного изделия в templates. + destination.write_bytes(file.read_bytes()) # Копирует только результаты успешного текущего вызова, сохраняя исходный RAM-образ. for item in stage.iterdir(): item.replace(output / item.name) - result = output / bin_image.name - archive_build(result, metadata, output, ( + result = output / bin_image.name # BIN остаётся основным образом EEPROM и возвращаемым результатом общего postbuild. + flash_archive = tuple(output / file.name for file in flash_files) # После переноса из временного каталога берёт актуальные Flash-файлы из firmware. + if flash_files: # Добавляет сопроводительные файлы только при выполненной сборке Flash. + flash_archive += (output / (flash_files[0].name + ".manifest.json"), output / (flash_files[0].name + ".sha256")) # Архив и GUI получают отдельный паспорт и контрольную сумму Flash COFF. + print(f"[firmware-build] Flash OUT: {source.parent / flash_files[0].name}") # Показывает пользователю CCS конкретный файл для прошивки внутренней Flash через JTAG. + archive_build(result, metadata, output, ( # Сохраняет файлы текущей сборки в архиве и передаёт весь архив в каталог GUI. + source, # Копирует исходный COFF-файл OUT с символами отладки под его именем для загрузки через JTAG из GUI. output / hex_image.name, output / (hex_image.name + ".map"), - output / (bin_image.name + ".map")), export=export) + output / (bin_image.name + ".map"), *flash_archive), export=export) # Экспортирует EEPROM и Flash в одной папке текущего выпуска. print(f"[firmware-build] BIN: {result}") print(f"[firmware-build] Manifest: {result}.manifest.json") print(f"[firmware-build] SHA-256: {result}.sha256") diff --git a/c/firmware-info/tools/identity.py b/c/firmware-info/tools/identity.py index 725d4ea..a338bca 100644 --- a/c/firmware-info/tools/identity.py +++ b/c/firmware-info/tools/identity.py @@ -45,15 +45,34 @@ def write_atomic(path: Path, text: str): temporary.replace(path) +def next_version(version): # Вычисляет следующий номер по ограничениям общего контракта firmware-info v1. + result = list(version) # Сохраняет исходный номер до успешной проверки полного переполнения. + for index, limit in ((2, 999), (1, 255), (0, 255)): # Patch имеет диапазон 0..999, minor и major занимают по одному октету 0..255. + if result[index] < limit: # Находит младший разряд, который ещё можно увеличить. + result[index] += 1 # Резервирует следующий номер попытки сборки, включая будущие неудачные компиляции. + return result # Старшие разряды сохраняются, переполненные младшие уже обнулены. + result[index] = 0 # Переносит единицу в следующий разряд после достижения предела текущего. + raise ValueError("Firmware version exhausted at 255.255.999") # Не допускает повторного использования номера после полного переполнения. + + def prepare(repository: Path, templates: Path, config: Path, output: Path) -> dict: settings = json.loads(config.read_text(encoding="utf-8-sig")) version = settings["version"] - if (len(version) != 3 or any(type(v) is not int for v in version) - or not all(0 <= v <= limit for v, limit in zip(version, (255, 255, 999)))): - raise ValueError("version must be [major 0..255, minor 0..255, patch 0..999]") + if not isinstance(version, list) or len(version) != 3 or any(type(value) is not int or not 0 <= value <= limit for value, limit in zip(version, (255, 255, 999))): # Проверяет JSON-массив трёх целых разрядов до любого изменения сохраняемого счётчика. + raise ValueError("version must be [major 0..255, minor 0..255, patch 0..999]") # Ошибочные типы, логические значения и выход за пределы контракта останавливают pre-build. + if type(settings.get("increment_version", False)) is not bool: # Отсутствующий флаг сохраняет ручной режим старых проектов; строки true/false не считаются настройкой. + raise ValueError("increment_version must be true or false") # Требует явное логическое значение JSON вместо неявного преобразования Python. for field in ("product", "target"): if not isinstance(settings.get(field), str) or not settings[field].strip(): raise ValueError(f"missing {field}") + if settings.get("increment_version", False): # Прямые вызовы templates из CCS, Keil и CLI используют один и тот же сохраняемый итератор. + version = settings["version"] = next_version(version) # Вычисляет номер для JSON, заголовка и метаданных только один раз. + with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", newline="\n", dir=config.parent, prefix=".firmware-version-", delete=False) as stream: # Временный файл на том же диске позволяет атомарно заменить настройки без частичной записи. + temporary = Path(stream.name) # Запоминает только собственный файл, чтобы не затронуть пользовательские данные при очистке. + try: stream.write(json.dumps(settings, ensure_ascii=False, indent=2) + "\n") # Сохраняет новый номер и все дополнительные поля проекта в UTF-8. + except BaseException: stream.close(); temporary.unlink(); raise # Ошибка записи оставляет исходный JSON целым и удаляет незавершённый файл. + try: temporary.replace(config) # Занимает номер до дальнейших шагов, поэтому отказ генерации или компиляции не повторит его. + finally: temporary.unlink(missing_ok=True) # Удаляет временный файл при ошибке замены; после успеха он уже переименован. source, dependency = git_state(repository), git_state(templates) # A clean application built with a modified templates checkout is dirty too. known = source["commit"] is not None and dependency["commit"] is not None diff --git a/c/gas-logger/README.md b/c/gas-logger/README.md index f17c4db..0e10a25 100644 --- a/c/gas-logger/README.md +++ b/c/gas-logger/README.md @@ -1,5 +1,7 @@ # GAS Logger — экспериментальная версия 1 +> GAS `0x3` использует адреса отдельных 16-битных регистров. GAS SLOT `0x4` — отдельный сервис с маской в Word0 и тремя значениями Word1…Word3. Спецификация: `doc/setcan/protocan/OAP.md`; адреса этого документа остаются регистровыми. + Непрерывный регистратор с двумя кольцевыми банками, неизменяемым снимком и общей картой GAS / ProtoCAN GAS / Modbus FC03/FC06. Весь код и проектные/MCU адаптеры находятся в `templates`; приложения подключают ревизию сабмодулем. diff --git a/c/global-time/CMakeLists.txt b/c/global-time/CMakeLists.txt new file mode 100644 index 0000000..88db168 --- /dev/null +++ b/c/global-time/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.13) # Задаёт минимальную версию, совместимую с соседними C-библиотеками templates. +project(global_time C) # Создаёт независимую цель для программных глобальных часов. +add_library(global_time STATIC src/global_time.c) # Собирает переносимое ядро без обязательных MCU заголовков. +target_include_directories(global_time PUBLIC include) # Экспортирует потребителю только публичный контракт часов. +target_compile_features(global_time PUBLIC c_std_99) # Требует C99 для точных целочисленных типов и uint64_t меток. +option(GLOBAL_TIME_BUILD_F28335 "Собирать аппаратный порт TI F28335" OFF) # Позволяет MCU проекту явно включить адаптер со своими TI include-путями. +if(GLOBAL_TIME_BUILD_F28335) # Не навязывает host-приложению аппаратные регистры TI. + target_sources(global_time PRIVATE ports/tms320f28335/global_time_f28335.c) # Добавляет eCAN и необязательный CPU Timer2 порт к той же библиотеке. + target_include_directories(global_time PUBLIC ports/tms320f28335) # Делает аппаратные hooks доступными прошивке потребителя. +endif() # Завершает условное подключение аппаратного адаптера. +option(GLOBAL_TIME_BUILD_TESTS "Собирать host-проверки глобального времени" ON) # Разрешает выключить host-исполняемые файлы в MCU сборке. +if(GLOBAL_TIME_BUILD_TESTS AND NOT GLOBAL_TIME_BUILD_F28335) # Не подмешивает host-модель регистров к настоящему TI порту. + enable_testing() # Регистрирует проверяемые сценарии в CTest. + add_executable(test_global_time tests/test_global_time.c) # Собирает календарные, CAN и монотонные сценарии. + target_link_libraries(test_global_time PRIVATE global_time) # Использует то же ядро, которое подключает прошивка. + add_test(NAME global_time COMMAND test_global_time) # Делает host-проверку доступной через ctest. + add_executable(test_global_time_f28335 tests/test_f28335.c ports/tms320f28335/global_time_f28335.c) # Собирает настоящий аппаратный адаптер с минимальной моделью регистров. + target_include_directories(test_global_time_f28335 PRIVATE tests/f28335_stubs ports/tms320f28335) # Ограничивает подмену заголовков только этой host-целью. + target_link_libraries(test_global_time_f28335 PRIVATE global_time) # Связывает аппаратные hooks с реальным ядром часов. + add_test(NAME global_time_f28335 COMMAND test_global_time_f28335) # Регистрирует eCAN/Timer2 проверку отдельно от календарной. +endif() # Завершает host-проверки без влияния на MCU исходники. diff --git a/c/global-time/README.md b/c/global-time/README.md new file mode 100644 index 0000000..b4e0bf4 --- /dev/null +++ b/c/global-time/README.md @@ -0,0 +1,167 @@ +# Глобальное время + +Программные часы с тактом 1 мс, синхронизацией даты и времени через ProtoCAN +и атомарным получением метки для логгера. Ядро C99 не требует аппаратного RTC, +операционной системы или динамической памяти. Порт TMS320F28335 включает +eCAN-A и необязательный CPU Timer2. Все текстовые файлы — UTF-8. + +## Обмен при запуске + +1. Приложение инициализирует часы до разрешения IRQ и запускает источник 1 мс. +2. После завершения инициализации **всей платы** вызывает `gt_ready()` / + `gt_f28335_ready()`. +3. Из main библиотека отправляет `DISCRETE/FLAGS`, `MsgBody=0x3000`, + `Route=1`, адрес самой платы, `DLC=1`, `DATA=01`. +4. Верхний уровень распознаёт пакет через `gt_parse_ready()`, берёт свою + текущую дату и посылает **один broadcast всем платам**, используя `gt_make_rtc()`. +5. Каждый узел принимает штатный `RTCSETUP`, сравнивает время со своим, + сохраняет величину коррекции и немедленно обновляет календарные часы. + При отсутствии ответа узел повторяет готовность не чаще раза в секунду. + +`RTCSETUP` полностью сохраняет действующий формат ProtoCAN. +Универсальное сообщение готовности здесь определено как новый профиль +`DISCRETE/FLAGS`; ранее такого общего пакета в базовом протоколе не было. +Подробный [контракт обмена](../../doc/setcan/protocan/GLOBAL_TIME.md). +Код верхнего уровня для автоматической отправки времени подключается в его +приложении; библиотека предоставляет кодировщик и распознавание события старта. + +## Метка логгера + +`gt_get()` одним атомарным чтением возвращает: + +| Поле | Значение | +|---|---| +| `seconds`, `millisecond` | секунды от 2000-01-01 и доля 0..999 мс | +| `synchronized` | 0 до первого корректного RTCSETUP, 1 после | +| `uptime_ms` | время работы modulo 2^32, независимое от переводов часов | +| `sync_uptime_ms` | момент приёма последнего опорного пакета | +| `generation` | номер принятой коррекции | +| `correction_ms` | последнее смещение, знаковое 64-битное значение в мс | +| `weekday` | фаза недели 0..6, продвигаемая при смене суток | + +`gt_timestamp_ms()` формирует 64-битную метку от 2000 года. +`gt_calendar()` преобразует снимок в календарь и возвращает 0, пока дата неизвестна. +Для записей, которые должны различать переводы часов, сохраняйте также +`generation`, `synchronized` и/или `uptime_ms`. Календарное время может идти назад +после коррекции. Тайм-ауты следует считать по разности `uptime_ms`. +Без новых broadcast часы продолжают ход по локальному генератору; +возраст синхронизации равен `(uint32_t)(uptime_ms - sync_uptime_ms)`. + +```c +#include "global_time_f28335.h" /* Подключает общую временную базу F28335. */ +gt_stamp stamp; /* Содержит согласованную дату, миллисекунды и качество времени. */ +gt_get(gt_f28335_clock(), &stamp); /* Допускается из main и ISR, включая ISR логгера. */ +uint64_t time_ms = gt_timestamp_ms(&stamp); /* Перед сохранением календарной метки проверяется stamp.synchronized. */ +``` + +Это фрагмент для функции потребителя. Формат хранения существующего логгера +библиотека не меняет. В частности, старое 32-битное поле `time_ms` в GAS logger +и v4 УМП не вмещает календарные миллисекунды: потребителю нужен собственный +формат абсолютной метки либо отдельная временная база и номер поколения. + +## Подключение TMS320F28335 + +Добавьте в сборку `src/global_time.c` и +`ports/tms320f28335/global_time_f28335.c`. Include-пути: `include`, +`ports/tms320f28335`, штатные TI `DSP2833x_headers/include`, +`DSP2833x_common/include` и include компилятора. + +Ресурсы порта: + +| Ресурс | Назначение | +|---|---| +| eCAN-A MBOX7 | RX точного RTCSETUP, любой приоритет, IRQ line0 | +| eCAN-A MBOX8 | TX готовности, ACK проверяется в main | +| CPU Timer2 / INT14 | необязательный собственный такт 1 мс | + +Mailbox 0..6, скорость CAN, GPIO и глобальные маршруты PIE/CANGIM настраивает +приложение. `DBO=0` обязателен; порт отвергает другую раскладку октетов. +MBOX7 использует CANOPC: кадр защищён от аппаратной перезаписи до копирования ISR. +В программной очереди хранится последний broadcast, поскольку более новый +опорный пакет заменяет предыдущий. + +При запрещённых IRQ, **после** `InitECan` и `InitPieVectTable`: + +```c +int ok = gt_f28335_init_periph(5U); /* PERIPH5=Type1/ID5, то есть УМП1; номер берётся из конфигурации платы. */ +if (ok) ok = gt_f28335_timer2_start(150000000UL); /* Частота CPU задаётся проектом в Гц; пример соответствует 150 МГц. */ +``` + +`gt_f28335_init()` позволяет передать Type и ID непосредственно. +`init_periph()` поддерживает физические PERIPH 0..31: Type1/2 и ID0..15; +5 — УМП1, 6 — УМП2, 8 — задатчик. Порт инициализируется до подключения hooks. +Повторный init разрешён только при остановленном собственном Timer2, +отсутствующем TX и запрещённых глобальных IRQ. + +Если Timer2 занят RTOS или приложением, **не вызывайте** `timer2_start()`; +в существующем ISR с периодом ровно 1 мс вызывайте `gt_f28335_tick_1ms()`. +Используйте один источник такта. Отдельный Timer2 продолжает отсчёт и при +медленном main, но длительная блокировка IRQ на несколько миллисекунд приводит +к потере тиков: аппаратный флаг прерывания не считает пропущенные периоды. + +В существующем `ECAN0INTA` ISR перед очисткой общих CAN-флагов и PIEACK: + +```c +gt_f28335_rx_isr(); /* Копирует только MBOX7 и запоминает uptime при приёме, календарь проверяется позднее. */ +``` + +Приложение должно разрешить соответствующий CAN IRQ: `CANGIM.I0EN`, +PIE group9 `INTx5`, CPU `M_INT9`; оставить свой обработчик остальных mailbox +и штатные подтверждения CANGIF/PIEACK. Порт не заменяет общий CAN ISR. +Глобальный `EINT` выполняет приложение после полной настройки. + +После прикладной инициализации и в каждом проходе главного цикла соответственно: + +```c +gt_f28335_ready(); /* Выполняется один раз после загрузки параметров и запуска прикладных подсистем. */ +gt_f28335_service(); /* Выполняется регулярно в main; обработка календаря и CAN не ждёт аппаратного ACK. */ +``` + +Все атомарные чтения и обновления используют TI +`__disable_interrupts()` / `__restore_interrupts()`, сохраняя прежний INTM. +Транспорт ждёт подтверждение CANTA асинхронно и не перезаписывает занятый MBOX8. +При отсутствии других CAN-узлов передача остаётся аппаратному контроллеру +до восстановления шины. CAN ACK не подтверждает обработку пакета мастером; +приход корректного RTCSETUP прекращает повторные объявления готовности. + +## Точность и календарь + +Разрешение локальных часов — 1 мс. Действующий RTCSETUP передаёт только целые +секунды, поэтому сам формат **не гарантирует синхронизацию плат с точностью 1 мс**. +Мастер должен посылать актуальное значение около секундной границы. +Арбитраж CAN и задержка до RX ISR остаются погрешностью; задержка после RX ISR +до обработки в main компенсируется по монотонному счётчику. Для точности между +платами до 1 мс понадобится согласованное расширение проводного протокола. + +Одна шкала времени выбирается верхним уровнем (рекомендуется UTC); кадр не +содержит часовой пояс. Входные годы 2000..2099, дата проверяется по григорианскому +календарю. Формат дня недели 0..6 соответствует проверке существующего +STM32-порта; профиль обозначает 0 как воскресенье. Для совместимости переданная +фаза недели сохраняется без дополнительной проверки соответствия дате. +Некоторые старые клиенты отображают неделю как 1..7; перед отправкой им нужен +перевод воскресенья 7 → 0. +Секундная шкала uint32_t от 2000 года переполнится в феврале 2136 года. +Период между захватом RX uptime и `gt_receive()` должен быть меньше 2^32 мс. + +## Проверки + +Из корня templates: + +```text +python c/global-time/tests/run_tests.py +``` + +`--cc` задаёт GCC/Clang. Для отдельной TI C28x проверки передайте +`--ti-cgt` (каталог компилятора), `--ti-headers` (DSP2833x_headers/include) +и при необходимости `--ti-common` (DSP2833x_common/include). +Объекты и EXE создаются во временном каталоге. CMake также предоставляет +`global_time`, два CTest и опции `GLOBAL_TIME_BUILD_F28335` / +`GLOBAL_TIME_BUILD_TESTS`; MCU проект задаёт свои TI include-пути. + +Проверяются ошибки даты и кадра, високосный февраль, смена года, коррекции +в обе стороны, компенсация очереди через переполнение uptime, ранний broadcast, +повторы готовности, сохранение IRQ, изоляция eCAN mailbox, аппаратный ACK, +значения периода Timer2 и его реальный ISR через назначенный вектор. +TI-проверка компилирует исходники с large/COFF ABI и настоящими заголовками +проекта 28335_periph. Полная линковка конкретной прошивки и проверка на плате +в этот набор не входят. diff --git a/c/global-time/include/global_time.h b/c/global-time/include/global_time.h new file mode 100644 index 0000000..46f406c --- /dev/null +++ b/c/global-time/include/global_time.h @@ -0,0 +1,65 @@ +#ifndef GLOBAL_TIME_H /* Защищает единый контракт часов от повторного включения. */ +#define GLOBAL_TIME_H /* Отмечает подключённый интерфейс программных глобальных часов. */ +#include /* Фиксирует разрядность счётчиков и поддерживает 16-битный char TI C28x. */ +#ifdef __cplusplus /* Сохраняет совместимость C-библиотеки с приложениями C++. */ +extern "C" { /* Экспортирует функции без изменения имён компилятором C++. */ +#endif /* Завершает условное объявление C ABI. */ +#define GT_RTC_ID 0x00000030UL /* ProtoCAN: Route=0, Type/ID=0, BROADCAST=0, RTCSETUP=3 в Body[15:4]. */ +#define GT_READY_BODY 0x3000U /* Контракт GLOBAL_TIME.md: DISCRETE/FLAGS=3, страница общих флагов=0. */ +#define GT_READY_RETRY_MS 1000UL /* Повторяет сообщение готовности раз в секунду до первой синхронизации. */ +typedef struct gt_frame { /* Описывает classic CAN независимо от регистров и размера char процессора. */ + uint32_t id; /* Хранит только 29 бит идентификатора, без служебных битов драйвера. */ + uint16_t extended; /* Единица означает IDE=1; стандартные кадры часы игнорируют. */ + uint16_t remote; /* Единица означает RTR; удалённый запрос не содержит время. */ + uint16_t dlc; /* Считает октеты на линии, а не sizeof элементов массива C28x. */ + uint16_t data[8]; /* Каждый элемент содержит один октет 0..255 даже при CHAR_BIT=16. */ +} gt_frame; /* Завершает переносимый контейнер кадра. */ +typedef struct gt_datetime { /* Представляет календарь без зависимости от time_t и часового пояса ОС. */ + uint16_t year; /* Полный год; входной ProtoCAN поддерживает 2000..2099. */ + uint16_t month; /* Номер месяца 1..12, без BCD-кодирования. */ + uint16_t day; /* Число месяца с проверкой високосного февраля. */ + uint16_t weekday; /* День недели 0..6; профиль использует 0=воскресенье, 1=понедельник. */ + uint16_t hour; /* Часы 0..23 в 24-часовом формате. */ + uint16_t minute; /* Минуты 0..59; leap seconds протокол не передаёт. */ + uint16_t second; /* Секунды 0..59 согласно существующему RTCSETUP. */ + uint16_t millisecond; /* Доля секунды 0..999; RTCSETUP задаёт нулевую долю. */ +} gt_datetime; /* Завершает публичный календарный тип. */ +typedef struct gt_stamp { /* Даёт логгеру согласованную метку и её качество одним чтением. */ + uint32_t seconds; /* Секунды от 2000-01-01 00:00:00 в шкале времени мастера. */ + uint16_t millisecond; /* Миллисекундная доля текущей секунды. */ + uint16_t synchronized; /* Ноль до первого корректного RTCSETUP, единица после него. */ + uint32_t uptime_ms; /* Независимый счётчик работы modulo 2^32; коррекции его не меняют. */ + uint32_t sync_uptime_ms; /* Момент приёма последнего RTCSETUP для оценки давности синхронизации. */ + uint32_t generation; /* Число коррекций; логгер отличает участки до и после перевода часов. */ + int64_t correction_ms; /* Последнее смещение новых часов относительно старых, в миллисекундах. */ + uint16_t weekday; /* Принятый день недели, продвигаемый при каждом переходе через полночь. */ +} gt_stamp; /* Завершает атомарно читаемый снимок. */ +typedef struct gt_port { /* Передаёт ядру короткие критические секции и неблокирующую отправку CAN. */ + void *user; /* Контекст платформы, передаваемый каждому callback без преобразования. */ + uint16_t (*enter)(void *user); /* Запрещает IRQ и возвращает прежнее состояние для вложенных вызовов. */ + void (*leave)(void *user, uint16_t state); /* Восстанавливает прежнее состояние IRQ, включая вызовы из ISR. */ + int (*send)(void *user, const gt_frame *frame); /* Копирует кадр до возврата; 1=принят, 0=занято/ошибка. */ +} gt_port; /* Завершает платформенный контракт; heap и аппаратный RTC не нужны. */ +typedef struct gt_clock { /* Хранит состояние одного узла; инициализация обязательна до разрешения ISR. */ + gt_port port; /* Содержит проверенные callbacks и контекст платформы. */ + volatile gt_stamp stamp; /* Меняется только при удержании блокировки IRQ. */ + uint16_t device_type; /* Три адресных бита ProtoCAN, диапазон 0..7. */ + uint16_t device_id; /* Четыре адресных бита экземпляра, диапазон 0..15. */ + uint16_t ready; /* Устанавливается приложением после завершения всей инициализации платы. */ + uint16_t announced; /* Помнит принятую транспортом отправку готовности, даже если часы уже синхронизированы. */ + uint32_t sent_uptime_ms; /* Ограничивает частоту повторов готовности монотонной шкалой. */ +} gt_clock; /* Состояние допускает статическое выделение памяти на микроконтроллере. */ +int gt_init(gt_clock *clock, const gt_port *port, uint16_t device_type, uint16_t device_id); /* Проверяет адрес/callbacks и явно очищает RAM, включая TI COFF. */ +void gt_tick_1ms(gt_clock *clock); /* Вызывается ровно один раз за аппаратную миллисекунду и выполняет только короткую арифметику. */ +void gt_get(gt_clock *clock, gt_stamp *out); /* Атомарно копирует всю метку; допустим вызов из main, логгера и ISR. */ +void gt_ready(gt_clock *clock); /* Идемпотентно разрешает сообщение «плата инициализирована»; CAN отправляется из poll. */ +void gt_poll(gt_clock *clock); /* Вызывается единственным потребителем в main; не ждёт освобождения CAN. */ +int gt_receive(gt_clock *clock, const gt_frame *frame, uint32_t received_uptime_ms); /* Проверяет RTCSETUP и компенсирует задержку от приёма до обработки, менее 2^32 мс. */ +int gt_make_rtc(const gt_datetime *date, gt_frame *out); /* Даёт верхнему уровню кодировщик штатного 7-октетного broadcast. */ +int gt_parse_ready(const gt_frame *frame, uint16_t *device_type, uint16_t *device_id); /* Позволяет мастеру распознать готовность и выбрать ответ RTCSETUP. */ +int gt_calendar(const gt_stamp *stamp, gt_datetime *out); /* Преобразует согласованный снимок в календарь; до синхронизации возвращает 0. */ +uint64_t gt_timestamp_ms(const gt_stamp *stamp); /* Возвращает широкую метку от 2000 года без переполнения через 49,7 суток. */ +#ifdef __cplusplus /* Закрывает C ABI только для компилятора C++. */ +} /* Завершает блок функций с C-связыванием. */ +#endif /* Завершает проверку языка потребителя. */ +#endif /* Завершает защиту публичного заголовка. */ diff --git a/c/global-time/ports/tms320f28335/global_time_f28335.c b/c/global-time/ports/tms320f28335/global_time_f28335.c new file mode 100644 index 0000000..9a07f78 --- /dev/null +++ b/c/global-time/ports/tms320f28335/global_time_f28335.c @@ -0,0 +1,168 @@ +#include "DSP2833x_Device.h" /* Использует штатные описания 32-битных регистров eCAN, Timer2 и векторов TI. */ +#include "global_time_f28335.h" /* Подключает переносимые часы и контракт интеграции порта. */ +#include /* Явно очищает отложенный RX до первого прохода main, включая TI COFF. */ +#define GT_RX 0x00000080UL /* Бит 7 регистров eCAN соответствует выделенному приёмному MBOX7. */ +#define GT_TX 0x00000100UL /* Бит 8 регистров eCAN соответствует отдельному передающему MBOX8. */ +static gt_clock board_clock; /* Один узел F28335 использует одну глобальную временную шкалу. */ +static gt_frame pending_frame; /* Последний RX хранится до обработки в main; новый broadcast заменяет устаревший. */ +static volatile uint16_t pending_rx; /* Публикует полностью скопированный RX и его монотонную привязку. */ +static uint32_t received_at; /* Запоминает миллисекундный uptime в момент обработки CAN ISR. */ +static uint16_t tx_busy, timer_owned; /* Явно сбрасывается init: TI COFF не гарантирует нули в .ebss. */ +static uint16_t initialized = 0U; /* Запись в .cinit гарантирует безопасный отказ ранних ISR hooks до init даже при TI COFF. */ +static uint16_t enter(void *user) /* Реализует вложенную критическую секцию TI C28x. */ +{ /* Не разрешает прерывания при выходе из уже выполняющегося ISR. */ + (void)user; /* Порт использует один статический экземпляр, поэтому контекст не требуется. */ + return __disable_interrupts(); /* Возвращает предыдущее состояние ST1, необходимое для восстановления INTM. */ +} /* Завершает платформенный вход в критическую секцию. */ +static void leave(void *user, uint16_t state) /* Восстанавливает состояние IRQ до входа в библиотеку. */ +{ /* Сохраняет корректность вызовов и из main, и из ISR. */ + (void)user; /* Отдельный аппаратный экземпляр выбирается статическими регистрами eCAN-A. */ + __restore_interrupts(state); /* Восстанавливает исходный INTM вместо безусловного разрешения IRQ. */ +} /* Завершает платформенный выход из критической секции. */ +static int send(void *user, const gt_frame *frame) /* Копирует пакет готовности в выделенный аппаратный mailbox без ожидания. */ +{ /* Транспорт не перезаписывает кадр, пока контроллер не подтвердит передачу. */ + uint16_t state = enter(0); /* Защищает RMW общих регистров CANME от чужих CAN ISR, сохраняя прежний INTM. */ + (void)user; /* Контекст платформы не нужен для фиксированного eCAN-A MBOX8. */ + if (tx_busy || (ECanaRegs.CANTRS.all & GT_TX)) { /* При занятости сохраняет исходный пакет и предлагает повтор из main. */ + leave(0, state); /* Восстанавливает исходные IRQ и на раннем выходе занятого транспорта. */ + return 0; /* Не теряет готовность и не ждёт окончания аппаратной передачи. */ + } /* Продолжает только при владении свободным MBOX8. */ + EALLOW; /* Открывает запись защищённой конфигурации mailbox контроллера. */ + ECanaRegs.CANME.all &= ~GT_TX; /* Отключает только MBOX8 перед изменением ID и payload. */ + ECanaMboxes.MBOX8.MSGID.all = 0x80000000UL | frame->id; /* IDE в бите 31 eCAN разрешает расширенный ProtoCAN ID. */ + ECanaMboxes.MBOX8.MSGCTRL.all = 1UL; /* DLC=1 и RTR=0 соответствуют единственному октету готовности. */ + ECanaMboxes.MBOX8.MDL.all = frame->data[0]; /* Первый проводной октет располагается в младших восьми битах MDL при DBO=0. */ + ECanaMboxes.MBOX8.MDH.all = 0UL; /* Убирает остатки прежнего payload, хотя DLC передаёт только один октет. */ + ECanaRegs.CANTA.all = GT_TX; /* Сбрасывает только старый ACK MBOX8 записью единицы. */ + ECanaRegs.CANAA.all = GT_TX; /* Сбрасывает только старое подтверждение отмены MBOX8. */ + ECanaRegs.CANME.all |= GT_TX; /* Возвращает MBOX8 в работу, сохраняя чужие mailbox. */ + ECanaRegs.CANTRS.all = GT_TX; /* Запрашивает передачу без блокирующего ожидания ACK шины. */ + EDIS; /* Закрывает запись защищённых регистров после полной публикации кадра. */ + tx_busy = 1U; /* Отмечает владение кадром до CANTA или CANAA, даже при отсутствии других узлов на шине. */ + leave(0, state); /* Освобождает короткую аппаратную секцию сразу после публикации запроса передачи. */ + return 1; /* Подтверждает приём транспортом, но не отдельное прикладное подтверждение мастера. */ +} /* Завершает неблокирующий callback передачи. */ +int gt_f28335_init(uint16_t device_type, uint16_t device_id) /* Настраивает часы и только два выделенных mailbox при запрещённых IRQ. */ +{ /* Приложение заранее задаёт скорость eCAN, GPIO, DBO=0 и общие векторы прерываний. */ + gt_port port; /* Локальная таблица callbacks копируется ядром в постоянное состояние. */ + if (device_type > 7U || device_id > 15U || (ECanaRegs.CANTRS.all & GT_TX) || ECanaRegs.CANMC.bit.DBO) return 0; /* Проверяет адрес и порядок октетов; активную TX-передачу не прерывает повторным init. */ + if (initialized && timer_owned) return 0; /* Требует остановить захваченный Timer2 перед повторным init, сохраняя его владение при отказе. */ + port.user = 0; /* Единственный экземпляр порта не требует внешнего контекста. */ + port.enter = enter; /* Подключает защиту снимка штатным intrinsic TI. */ + port.leave = leave; /* Подключает восстановление предыдущей маски прерываний. */ + port.send = send; /* Подключает отправку в MBOX8 без ожидания свободной шины. */ + if (!gt_init(&board_clock, &port, device_type, device_id)) return 0; /* Сбрасывает RAM до открытия источников IRQ. */ + pending_rx = tx_busy = timer_owned = 0U; /* Явно очищает программные флаги после холодного и тёплого старта. */ + memset(&pending_frame, 0, sizeof(pending_frame)); /* Не читает неопределённую RAM при первом service без полученного пакета. */ + received_at = 0UL; /* Начальная привязка не читается до получения первого кадра. */ + EALLOW; /* Открывает изменение аппаратной конфигурации eCAN-A. */ + ECanaRegs.CANME.all &= ~(GT_RX | GT_TX); /* Временно отключает только выделенные mailbox 7/8. */ + ECanaMboxes.MBOX7.MSGID.all = 0xC0000000UL | GT_RTC_ID; /* IDE=1 и AME=1 включают расширенный ID и локальную маску точного RTCSETUP. */ + ECanaLAMRegs.LAM7.all = 0x10000000UL; /* LAM игнорирует только бит Priority[28]; LAMI=0 сохраняет проверку IDE. */ + ECanaMboxes.MBOX7.MSGCTRL.all = 7UL; /* Задаёт ожидаемые семь октетов; фактический DLC дополнительно проверяется ядром. */ + ECanaMboxes.MBOX8.MSGID.all = 0x80000000UL; /* Подготавливает расширенный TX без AME; адрес будет установлен callback отправки. */ + ECanaMboxes.MBOX8.MSGCTRL.all = 1UL; /* Пакет готовности занимает один октет CAN payload. */ + ECanaRegs.CANMD.all = (ECanaRegs.CANMD.all | GT_RX) & ~GT_TX; /* MBOX7 становится RX, MBOX8 — TX, направления остальных mailbox сохраняются. */ + ECanaRegs.CANOPC.all |= GT_RX; /* Запрещает перезапись RX до чтения ISR; при потере используется следующий периодический broadcast. */ + ECanaRegs.CANMIL.all &= ~GT_RX; /* Направляет MBOX7 в общую линию ECAN0INTA приложения. */ + ECanaRegs.CANMIM.all = (ECanaRegs.CANMIM.all | GT_RX) & ~GT_TX; /* Разрешает IRQ только на RX, а завершение TX проверяет main. */ + ECanaRegs.CANRMP.all = GT_RX; /* Удаляет старый pending только MBOX7 записью единицы. */ + ECanaRegs.CANRML.all = GT_RX; /* Очищает старую потерю приёма только выделенного mailbox. */ + ECanaRegs.CANTA.all = GT_TX; /* Удаляет старый ACK выделенного передатчика, не затрагивая CAN Boot. */ + ECanaRegs.CANAA.all = GT_TX; /* Удаляет старый флаг отмены перед настройкой нового обмена. */ + ECanaRegs.CANME.all |= GT_RX | GT_TX; /* Включает приём синхронизации и передачу готовности. */ + EDIS; /* Закрывает защищённую конфигурацию контроллера. */ + initialized = 1U; /* Публикует готовность самого порта после сброса всех RAM- и аппаратных флагов. */ + return 1; /* Приложение может запускать такт и разрешать общие CAN-прерывания. */ +} /* Завершает настройку без сброса скорости, GPIO и других CAN-сервисов. */ +int gt_f28335_init_periph(uint16_t periph) /* Привязывает часы к физическому адресу периферийной платы. */ +{ /* Использует тот же реестр, что существующий порт CAN Boot F28335. */ + if (periph >= 32U) return 0; /* Адреса PERIPH определены только для 32 устройств, без циклического обрезания. */ + return gt_f28335_init((uint16_t)(1U + periph / 16U), periph % 16U); /* Номера 0..15 используют Type=1, 16..31 — Type=2, младшие четыре бита задают ID. */ +} /* Завершает преобразование физического адреса. */ +gt_clock *gt_f28335_clock(void) /* Предоставляет логгеру общую временную базу платы. */ +{ /* Действует после успешной инициализации порта. */ + return &board_clock; /* Один и тот же объект обслуживают CAN, таймер и все потребители времени. */ +} /* Завершает доступ к экземпляру переносимого ядра. */ +void gt_f28335_ready(void) /* Публикует готовность прикладного оборудования после загрузки параметров. */ +{ /* Не объявляет успех при отказе конфигурации порта. */ + if (initialized) gt_ready(&board_clock); /* Первый пакет будет послан из main даже при уже полученном времени. */ +} /* Завершает hook завершения инициализации платы. */ +void gt_f28335_tick_1ms(void) /* Позволяет использовать существующий периодический ISR вместо Timer2. */ +{ /* Приложение выбирает один источник миллисекунд, исключая двойной отсчёт. */ + if (initialized) gt_tick_1ms(&board_clock); /* Продвигает локальные и календарные часы только после явного init. */ +} /* Завершает универсальный миллисекундный hook. */ +void gt_f28335_rx_isr(void) /* Захватывает CAN-время и момент получения без календарной обработки в ISR. */ +{ /* Вызывается существующим обработчиком ECAN0INTA до очистки CANGIF и PIEACK. */ + uint32_t low, high, uptime; /* Однократные 32-битные чтения не рвут слова аппаратного mailbox. */ + uint16_t i, state; /* Индекс восьми октетов и прежняя маска прерываний. */ + if (!initialized || !(ECanaRegs.CANRMP.all & GT_RX)) return; /* Не читает MBOX7 по прерыванию другого CAN-сервиса. */ + state = enter(0); /* Исключает вложенный таймер между чтением uptime и публикацией полученного кадра. */ + uptime = board_clock.stamp.uptime_ms; /* Фиксирует момент RX в монотонных миллисекундах, независимых от синхронизации. */ + pending_frame.id = ECanaMboxes.MBOX7.MSGID.all & 0x1FFFFFFFUL; /* Удаляет служебные IDE/AME биты регистра из 29-битного ID. */ + pending_frame.extended = (uint16_t)(ECanaMboxes.MBOX7.MSGID.all >> 31U); /* Ядро дополнительно проверит IDE даже при аппаратной фильтрации. */ + pending_frame.remote = ECanaMboxes.MBOX7.MSGCTRL.bit.RTR; /* Сохраняет RTR, чтобы удалённый запрос никогда не устанавливал часы. */ + pending_frame.dlc = ECanaMboxes.MBOX7.MSGCTRL.bit.DLC; /* Сохраняет фактическую длину, включая ошибочный или пустой payload. */ + low = ECanaMboxes.MBOX7.MDL.all; /* Читает первые четыре октета одним 32-битным доступом eCAN. */ + high = ECanaMboxes.MBOX7.MDH.all; /* Читает оставшиеся четыре октета без указателей на байты C28x. */ + for (i = 0U; i < 8U; ++i) pending_frame.data[i] = (uint16_t)(((i < 4U ? low : high) >> (8U * (i % 4U))) & 255UL); /* Извлекает каждый проводной октет при DBO=0 в отдельное 16-битное слово. */ + received_at = uptime; /* Публикует временную привязку того же аппаратного кадра. */ + pending_rx = 1U; /* Отмечает полностью готовый снимок; main читает его под той же блокировкой. */ + ECanaRegs.CANRMP.all = GT_RX; /* Освобождает MBOX7 только после полного копирования защищённого CANOPC кадра. */ + ECanaRegs.CANRML.all = GT_RX; /* Сбрасывает индикатор пропущенного кадра, сохраняя уже скопированное опорное время. */ + leave(0, state); /* Возвращает исходный INTM обработчика CAN. */ +} /* Завершает короткий ISR без отправки, ожидания CAN и расчёта календаря. */ +void gt_f28335_service(void) /* Обрабатывает часы и готовность из единственного основного цикла. */ +{ /* Отложенная календарная работа не увеличивает длительность CAN ISR. */ + gt_frame frame; /* Локальная копия допускает замену следующего pending кадра новым CAN ISR. */ + uint32_t uptime; /* Сохраняет привязку прочитанного кадра до выхода из критической секции. */ + uint16_t state, have_rx; /* Разделяет короткий захват очереди и длительную проверку календаря. */ + if (!initialized) return; /* Не обращается к неинициализированным callbacks после отказа init. */ + state = enter(0); /* Блокирует ISR только на время копирования одного небольшого кадра. */ + have_rx = pending_rx; /* Запоминает наличие кадра перед освобождением слота. */ + frame = pending_frame; /* Копирует payload и заголовок согласованно с моментом RX. */ + uptime = received_at; /* Забирает момент получения того же кадра. */ + pending_rx = 0U; /* Разрешает приём следующего broadcast, пока main рассчитывает дату текущего. */ + leave(0, state); /* Возобновляет IRQ до календарных циклов. */ + if (have_rx) (void)gt_receive(&board_clock, &frame, uptime); /* Проверяет время и добавляет тики, прошедшие с RX ISR. */ + if (tx_busy && ((ECanaRegs.CANTA.all | ECanaRegs.CANAA.all) & GT_TX)) { /* Освобождает TX только после подтверждения передачи либо аппаратной отмены. */ + ECanaRegs.CANTA.all = GT_TX; /* Сбрасывает только ACK собственного mailbox. */ + ECanaRegs.CANAA.all = GT_TX; /* Сбрасывает только флаг отмены собственного mailbox. */ + tx_busy = 0U; /* Следующий gt_poll сможет повторить готовность, если время ещё не получено. */ + } /* При отсутствии ACK запрос остаётся аппаратному CAN для автоматической передачи после восстановления шины. */ + gt_poll(&board_clock); /* Объявляет готовность и ограничивает повторы одной секундой локального времени. */ +} /* Завершает неблокирующий проход обслуживания. */ +__interrupt void gt_f28335_timer2_isr(void) /* Обслуживает прямой CPU INT14 без использования группы PIE. */ +{ /* Этот вектор принадлежит библиотеке только после явного timer2_start. */ + CpuTimer2Regs.TCR.all = 0xC000U; /* TIF[15]=1 очищает флаг, TIE[14]=1 сохраняет IRQ, TSS=0 продолжает счёт. */ + gt_f28335_tick_1ms(); /* Один период Timer2 соответствует одной миллисекунде программных часов. */ +} /* Для прямого INT14 подтверждение PIEACK не требуется. */ +int gt_f28335_timer2_start(uint32_t cpu_hz) /* Опционально запускает выделенный таймер с периодом ровно 1 мс. */ +{ /* Частота поступает от проекта; порт не предполагает жёстко заданные 150 МГц. */ + uint16_t state; /* Сохраняет прежнюю глобальную маску IRQ на время смены вектора. */ + if (!initialized || cpu_hz < 1000UL || cpu_hz % 1000UL != 0UL) return 0; /* Отвергает период с дробным числом тактов вместо накопления скрытого дрейфа. */ + state = enter(0); /* Исключает запуск INT14 со старым вектором и новым периодом. */ + CpuTimer2Regs.TCR.all = 0x0010U; /* TSS[4]=1 останавливает счёт, TIE=0 временно запрещает IRQ Timer2. */ + CpuTimer2Regs.PRD.all = cpu_hz / 1000UL - 1UL; /* Период включает значения PRD..0; при 150 МГц это 149999, то есть 150000 тактов за 1 мс. */ + CpuTimer2Regs.TPR.all = 0U; /* Нулевой младший предделитель означает один такт CPU на шаг счётчика. */ + CpuTimer2Regs.TPRH.all = 0U; /* Нулевой старший предделитель не добавляет деления частоты. */ + EALLOW; /* Разрешает запись защищённой таблицы векторов прерываний TI. */ + PieVectTable.TINT2 = >_f28335_timer2_isr; /* Подключает собственный обработчик прямого CPU Timer2/INT14. */ + EDIS; /* Закрывает доступ к векторной таблице после установки обработчика. */ + IFR &= (uint16_t)~M_INT14; /* Снимает старый pending CPU INT14 до запуска нового периодического такта. */ + IER |= M_INT14; /* Разрешает только INT14, сохраняя маски остальных CPU-прерываний. */ + timer_owned = 1U; /* Позволяет stop изменять Timer2 только после явного захвата этим портом. */ + CpuTimer2Regs.TCR.all = 0xC020U; /* TIF=1 очищает флаг, TIE=1 разрешает IRQ, TRB=1 загружает PRD, TSS=0 запускает таймер. */ + leave(0, state); /* Сохраняет выбор приложения, когда разрешить глобальные прерывания. */ + return 1; /* Приложение должно исключить параллельный вызов tick из своего Timer1. */ +} /* Завершает настройку автономного миллисекундного такта. */ +void gt_f28335_timer2_stop(void) /* Освобождает аппаратный такт, ранее явно запущенный библиотекой. */ +{ /* Не трогает чужой Timer2, если выбран hook существующего таймера. */ + uint16_t state = enter(0); /* Не допускает INT14 между остановкой счётчика и снятием разрешения CPU. */ + if (timer_owned) { /* Ограничивает изменения ресурсом, захваченным этим портом. */ + CpuTimer2Regs.TCR.all = 0x8010U; /* TIF=1 очищает флаг, TSS=1 останавливает таймер, TIE=0 запрещает источник IRQ. */ + IER &= (uint16_t)~M_INT14; /* Убирает только разрешение прямого Timer2 IRQ, сохраняя остальные CPU-сервисы. */ + timer_owned = 0U; /* Фиксирует освобождение источника аппаратного такта. */ + } /* При отсутствии владения никакие регистры таймера не меняются. */ + leave(0, state); /* Возвращает прежнее состояние глобальной маски IRQ. */ +} /* Завершает необязательную остановку аппаратных часов. */ diff --git a/c/global-time/ports/tms320f28335/global_time_f28335.h b/c/global-time/ports/tms320f28335/global_time_f28335.h new file mode 100644 index 0000000..92ccbce --- /dev/null +++ b/c/global-time/ports/tms320f28335/global_time_f28335.h @@ -0,0 +1,19 @@ +#ifndef GLOBAL_TIME_F28335_H /* Защищает порт F28335 от повторного включения. */ +#define GLOBAL_TIME_F28335_H /* Отмечает единственный экземпляр аппаратного порта. */ +#include "global_time.h" /* Экспортирует тот же снимок метки и календарный API, что переносимое ядро. */ +#ifdef __cplusplus /* Сохраняет возможность подключения из приложения C++. */ +extern "C" { /* Фиксирует C ABI аппаратных точек входа. */ +#endif /* Завершает условное открытие C ABI. */ +int gt_f28335_init(uint16_t device_type, uint16_t device_id); /* После InitECan и InitPieVectTable, до IRQ: занимает только eCAN-A MBOX7 RX и MBOX8 TX. */ +int gt_f28335_init_periph(uint16_t periph); /* Преобразует PERIPH 0..31 в Type=1/2, ID=0..15 по реестру ProtoCAN. */ +gt_clock *gt_f28335_clock(void); /* Даёт логгеру ядро для gt_get; указатель действителен после успешного init. */ +void gt_f28335_ready(void); /* Вызывается после успешной инициализации всей платы, затем отправка происходит из service. */ +void gt_f28335_tick_1ms(void); /* Подключается к существующему ISR 1 мс, если отдельный Timer2 не используется. */ +void gt_f28335_rx_isr(void); /* Вызывается общим ECAN0INTA ISR до очистки общих флагов; не выполняет календарных циклов. */ +void gt_f28335_service(void); /* Вызывается в main: применяет последний RX, обслуживает ACK и повторы готовности без ожиданий. */ +int gt_f28335_timer2_start(uint32_t cpu_hz); /* Необязательный такт: занимает CPU Timer2/INT14, принимает частоту CPU в Гц, кратную 1000. */ +void gt_f28335_timer2_stop(void); /* Останавливает только ранее запущенный портом Timer2, сохраняя остальные разрешения CPU IRQ. */ +#ifdef __cplusplus /* Закрывает C ABI при использовании C++. */ +} /* Завершает блок аппаратных функций с C-связыванием. */ +#endif /* Завершает языковую проверку. */ +#endif /* Завершает защиту заголовка порта. */ diff --git a/c/global-time/src/global_time.c b/c/global-time/src/global_time.c new file mode 100644 index 0000000..5ef014c --- /dev/null +++ b/c/global-time/src/global_time.c @@ -0,0 +1,156 @@ +#include "global_time.h" /* Подключает переносимые типы, API часов и фиксированные поля ProtoCAN. */ +#include /* Использует явный сброс состояния вместо предположений о старте TI COFF. */ +static uint16_t month_days(uint16_t year, uint16_t month) /* Вычисляет длину уже проверенного месяца по григорианскому календарю. */ +{ /* Ограничивает область таблицы календаря и условия високосного года. */ + static const uint16_t days[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; /* Число суток каждого месяца обычного года. */ + return (uint16_t)(days[month - 1U] + (month == 2U && year % 4U == 0U && (year % 100U != 0U || year % 400U == 0U))); /* Добавляет 29 февраля, включая исключение для 2100 года. */ +} /* Завершает календарный расчёт без обращения к платформе. */ +static int date_seconds(const gt_datetime *date, uint32_t *seconds) /* Проверяет все входные поля до индексации календарных таблиц. */ +{ /* Собирает секунды эпохи отдельно от критической секции часов. */ + uint16_t year, month; /* Счётчики лет и месяцев нужны только при редкой синхронизации. */ + uint32_t days = 0; /* Накопленные сутки от начала 2000 года; диапазон CAN не превышает 36525 суток. */ + if (!date || date->year < 2000U || date->year > 2099U || date->month < 1U || date->month > 12U) return 0; /* Отвергает неподдерживаемую эпоху и неверный индекс месяца. */ + if (date->day < 1U || date->day > month_days(date->year, date->month) || date->weekday > 6U) return 0; /* Принимает только существующую дату и формат дня недели действующего STM32 RTCSETUP. */ + if (date->hour > 23U || date->minute > 59U || date->second > 59U || date->millisecond > 999U) return 0; /* Исключает перенос некорректных полей в соседние сутки. */ + for (year = 2000U; year < date->year; ++year) days += 365UL + (month_days(year, 2U) == 29U); /* Учитывает каждый полный год относительно фиксированной эпохи. */ + for (month = 1U; month < date->month; ++month) days += month_days(date->year, month); /* Прибавляет полные месяцы текущего года. */ + days += date->day - 1U; /* Переводит календарное число 1..31 в число завершённых суток. */ + *seconds = days * 86400UL + (uint32_t)date->hour * 3600UL + (uint32_t)date->minute * 60UL + date->second; /* Константы задают секунд в сутках, часе и минуте; UL исключает 16-битное умножение C28x. */ + return 1; /* Подтверждает полностью проверенную календарную величину. */ +} /* Завершает преобразование календаря в секундную шкалу. */ +uint64_t gt_timestamp_ms(const gt_stamp *stamp) /* Позволяет логгеру сохранить абсолютное время без потери миллисекунд. */ +{ /* Выполняет расчёт по уже снятому атомарному снимку. */ + return (uint64_t)stamp->seconds * 1000ULL + stamp->millisecond; /* Расширяет до умножения, чтобы календарная метка не переполняла uint32_t. */ +} /* Завершает получение широкой метки времени. */ +int gt_init(gt_clock *clock, const gt_port *port, uint16_t device_type, uint16_t device_id) /* Создаёт часы до запуска прерываний устройства. */ +{ /* Отказывается от конфигурации без реальной защиты общего состояния. */ + if (!clock || !port || !port->enter || !port->leave || !port->send || device_type > 7U || device_id > 15U) return 0; /* Не обрезает ошибочный CAN-адрес до адреса другой платы. */ + memset(clock, 0, sizeof(*clock)); /* Сбрасывает в том числе неинициализированную .ebss TI COFF и старый признак синхронизации. */ + clock->port = *port; /* Сохраняет callbacks без выделения динамической памяти. */ + clock->device_type = device_type; /* Запоминает тип источника пакета готовности. */ + clock->device_id = device_id; /* Запоминает экземпляр источника пакета готовности. */ + clock->stamp.weekday = 6U; /* Начальная локальная эпоха 2000-01-01 приходится на субботу при 0=воскресенье. */ + return 1; /* Разрешает приложению подключать такт и CAN только после успеха. */ +} /* Завершает обязательную явную инициализацию. */ +void gt_tick_1ms(gt_clock *clock) /* Выполняет короткий шаг часов из миллисекундного ISR. */ +{ /* Защищает разрядные переносы и от вложенных читателей. */ + uint16_t state = clock->port.enter(clock->port.user); /* Сохраняет прежний INTM, чтобы выход из ISR не разрешил вложенные IRQ. */ + ++clock->stamp.uptime_ms; /* Продвигает независимое время работы modulo 2^32 миллисекунд. */ + if (++clock->stamp.millisecond == 1000U) { /* Переносит ровно 1000 аппаратных миллисекунд в одну секунду. */ + clock->stamp.millisecond = 0U; /* Начинает следующую секунду с нулевой дробной части. */ + if (++clock->stamp.seconds % 86400UL == 0UL) clock->stamp.weekday = (clock->stamp.weekday + 1U) % 7U; /* При переходе суток продвигает принятый день недели по циклу из семи дней. */ + } /* Завершает редкую секундную ветвь без календарных циклов в ISR. */ + clock->port.leave(clock->port.user, state); /* Восстанавливает исходную маску IRQ вызывающего кода. */ +} /* Завершает единственный источник продвижения часов. */ +void gt_get(gt_clock *clock, gt_stamp *out) /* Снимает согласованные дату, долю секунды и качество синхронизации. */ +{ /* Не допускает разрыва 32/64-битных полей на 16-битной шине C28x. */ + uint16_t state = clock->port.enter(clock->port.user); /* Блокирует изменение снимка таймером и CAN до завершения копирования. */ + *out = clock->stamp; /* Копирует все поля в пределах одной критической секции. */ + clock->port.leave(clock->port.user, state); /* Восстанавливает IRQ без безусловного EINT. */ +} /* Завершает чтение метки для логгера и тайм-аутов. */ +void gt_ready(gt_clock *clock) /* Отмечает фактическое завершение инициализации прикладных подсистем. */ +{ /* Разделяет настройку часов и объявление готовности всей платы. */ + clock->ready = 1U; /* Повторные вызовы не сбрасывают историю отправок или синхронизаций. */ +} /* Передачу сообщения выполнит основной цикл. */ +void gt_poll(gt_clock *clock) /* Обслуживает объявление готовности без задержек и ожидания CAN. */ +{ /* Разрешён один вызывающий основной цикл; callback send копирует временный кадр. */ + gt_stamp now; /* Согласованное время определяет частоту повторов независимо от перевода часов. */ + gt_frame frame; /* Локальный пакет не занимает место в постоянной очереди ядра. */ + if (!clock->ready) return; /* Плата не сообщает об успехе раньше завершения своей инициализации. */ + gt_get(clock, &now); /* Снимает монотонную базу и признак получения RTCSETUP. */ + if (clock->announced && (now.synchronized || (uint32_t)(now.uptime_ms - clock->sent_uptime_ms) < GT_READY_RETRY_MS)) return; /* После синхронизации прекращает повторы, сохраняя обязательную первую отправку. */ + memset(&frame, 0, sizeof(frame)); /* Явно обнуляет RTR и неиспользуемые октеты сообщения. */ + frame.id = 0x18010000UL | ((uint32_t)clock->device_type << 24U) | ((uint32_t)clock->device_id << 20U) | GT_READY_BODY; /* Задаёт стандартный приоритет, Route=1, DISCRETE=1 и FLAGS=3. */ + frame.extended = 1U; /* Использует только штатный расширенный идентификатор ProtoCAN. */ + frame.dlc = 1U; /* Одного октета хватает для общего флага готовности. */ + frame.data[0] = 1U; /* Бит 0 означает завершение инициализации; прочие биты зарезервированы нулями. */ + if (clock->port.send(clock->port.user, &frame)) { /* Не считает занятый mailbox успешной отправкой. */ + clock->announced = 1U; /* Фиксирует приём транспортом, а не отдельный прикладной ACK мастера. */ + clock->sent_uptime_ms = now.uptime_ms; /* Начинает секундный интервал до повтора при отсутствии RTCSETUP. */ + } /* При отказе транспорта следующая итерация main повторит попытку без ожидания. */ +} /* Завершает неблокирующее обслуживание готовности. */ +static int data_frame(const gt_frame *frame) /* Выполняет общую проверку контейнера classic CAN. */ +{ /* Не позволяет служебным битам драйвера участвовать в разборе ID. */ + return frame && frame->extended == 1U && !frame->remote && frame->id <= 0x1FFFFFFFUL; /* Требует IDE=1, RTR=0 и ровно 29 адресных битов. */ +} /* Завершает общую проверку адресного формата. */ +int gt_parse_ready(const gt_frame *frame, uint16_t *device_type, uint16_t *device_id) /* Распознаёт на верхнем уровне только определённый пакет готовности. */ +{ /* Не путает событие старта с пульсом или произвольными дискретными флагами. */ + if (!data_frame(frame) || (frame->id & 0x080FFFFFUL) != (0x08010000UL | GT_READY_BODY) || frame->dlc != 1U || frame->data[0] != 1U) return 0; /* Проверяет Route=1, MsgType=1, Body=0x3000 и единственный разрешённый флаг. */ + if (device_type) *device_type = (uint16_t)((frame->id >> 24U) & 7UL); /* Возвращает трёхбитный тип источника при наличии выходного указателя. */ + if (device_id) *device_id = (uint16_t)((frame->id >> 20U) & 15UL); /* Возвращает четырёхбитный номер экземпляра источника. */ + return 1; /* Верхний уровень может ответить одним общим RTCSETUP всем устройствам. */ +} /* Завершает распознавание стартового события мастером. */ +int gt_make_rtc(const gt_datetime *date, gt_frame *out) /* Кодирует существующую команду синхронизации для верхнего уровня. */ +{ /* Передаёт ровно те семь полей, которые принимает STM32-порт ProtoCAN. */ + uint32_t seconds; /* При проверке календаря получает допустимую секундную величину. */ + if (!out || !date_seconds(date, &seconds) || date->millisecond != 0U) return 0; /* Не отбрасывает ненулевые миллисекунды молча: проводной формат их не содержит. */ + memset(out, 0, sizeof(*out)); /* Нули задают RTR=0, критический приоритет и резерв payload. */ + out->id = GT_RTC_ID; /* Передаёт BROADCAST RTCSETUP от верхнего уровня с нулевым параметром команды. */ + out->extended = 1U; /* Выбирает расширенный 29-битный CAN-кадр. */ + out->dlc = 7U; /* Сохраняет существующий контракт DLC=7 без добавления миллисекундного расширения. */ + out->data[0] = date->hour; /* Первый октет содержит часы в двоичном представлении. */ + out->data[1] = date->minute; /* Второй октет содержит минуты. */ + out->data[2] = date->second; /* Третий октет содержит целые секунды. */ + out->data[3] = date->year - 2000U; /* Четвёртый октет хранит смещение года 0..99 от эпохи 2000. */ + out->data[4] = date->month; /* Пятый октет содержит месяц 1..12. */ + out->data[5] = date->day; /* Шестой октет содержит проверенное число месяца. */ + out->data[6] = date->weekday; /* Седьмой октет сохраняет принятый формат дня недели 0..6. */ + return 1; /* Кадр готов к неблокирующей отправке транспортом мастера. */ +} /* Завершает кодирование общего broadcast. */ +int gt_receive(gt_clock *clock, const gt_frame *frame, uint32_t received_uptime_ms) /* Проверяет и применяет RTCSETUP, привязанный к моменту приёма. */ +{ /* Отвергает некорректные кадры до изменения состояния устройства. */ + gt_datetime date; /* Временный календарь строится из отдельных октетов без struct overlay. */ + uint32_t seconds, elapsed, corrected_seconds, whole_days; /* Содержит секунды мастера, задержку в мс, актуальные секунды и перенос дня недели. */ + uint16_t i, state; /* Индекс проверки payload и сохранённое состояние IRQ. */ + uint16_t corrected_ms; /* Хранит дробную часть отдельно, исключая дорогие 64-битные деления под маской IRQ C28x. */ + if (!data_frame(frame) || (frame->id & 0x0FFFFFFFUL) != GT_RTC_ID || frame->dlc != 7U) return 0; /* Принимает оба приоритета, но только Route=0, Type/ID=0, BROADCAST RTCSETUP с параметром 0. */ + for (i = 0U; i < 7U; ++i) if (frame->data[i] > 255U) return 0; /* C28x хранит октет в 16-битном элементе; старшие биты означают ошибку адаптера. */ + date.hour = frame->data[0]; /* Восстанавливает часы по штатному порядку RTCSETUP. */ + date.minute = frame->data[1]; /* Восстанавливает минуты без BCD-преобразований. */ + date.second = frame->data[2]; /* Восстанавливает целые секунды мастера. */ + date.year = 2000U + frame->data[3]; /* Восстанавливает полный год из двухзначного поля протокола. */ + date.month = frame->data[4]; /* Читает номер месяца до проверки таблицы длительности. */ + date.day = frame->data[5]; /* Читает число месяца для строгой календарной проверки. */ + date.weekday = frame->data[6]; /* Сохраняет присланную мастером фазу недели. */ + date.millisecond = 0U; /* Семь октетов RTCSETUP задают точность источника только до секунды. */ + if (!date_seconds(&date, &seconds)) return 0; /* Неверные даты не сбрасывают часы и признак предыдущей синхронизации. */ + state = clock->port.enter(clock->port.user); /* Защищает сравнение, перенос и публикацию новой временной базы. */ + elapsed = clock->stamp.uptime_ms - received_uptime_ms; /* Учитывает время очереди main, в том числе через переполнение uint32_t uptime. */ + corrected_seconds = seconds + elapsed / 1000UL; /* Прибавляет полные секунды задержки RX; диапазон входных годов и задержка до 2^32 мс помещаются в uint32_t. */ + corrected_ms = (uint16_t)(elapsed % 1000UL); /* Восстанавливает фазу миллисекунд без 64-битного деления в критической секции. */ + clock->stamp.correction_ms = ((int64_t)corrected_seconds - clock->stamp.seconds) * 1000LL + corrected_ms - clock->stamp.millisecond; /* Сохраняет знак и полную величину смещения, расширяя разность секунд до умножения. */ + whole_days = corrected_seconds / 86400UL - seconds / 86400UL; /* Определяет переходы через полночь за время отложенной обработки. */ + clock->stamp.seconds = corrected_seconds; /* Публикует новые секунды независимо от монотонного uptime. */ + clock->stamp.millisecond = corrected_ms; /* Публикует долю секунды, соответствующую текущему локальному тику. */ + clock->stamp.weekday = (uint16_t)((date.weekday + whole_days) % 7UL); /* Сохраняет правильный день недели даже при обработке после полуночи. */ + clock->stamp.sync_uptime_ms = received_uptime_ms; /* Позволяет потребителю вычислить возраст последнего опорного пакета. */ + ++clock->stamp.generation; /* Отмечает любую принятую коррекцию, включая перевод часов назад. */ + clock->stamp.synchronized = 1U; /* Последней записью подтверждает валидность полностью опубликованной даты. */ + clock->port.leave(clock->port.user, state); /* Возвращает прежнюю маску прерываний после атомарного обновления. */ + return 1; /* Сообщает транспорту об успешной обработке синхронизации. */ +} /* Завершает сравнение и немедленную коррекцию часов. */ +int gt_calendar(const gt_stamp *stamp, gt_datetime *out) /* Преобразует снимок для человека без блокировки аппаратного таймера. */ +{ /* Вызывает календарные циклы только по требованию логгера или интерфейса. */ + uint32_t days, remainder; /* Разделяет полные сутки и секунды внутри суток. */ + uint16_t year = 2000U, month = 1U, length; /* Начинает разбор от эпохи библиотеки. */ + if (!stamp || !out || !stamp->synchronized) return 0; /* Не выдаёт локальный отсчёт до синхронизации за известную календарную дату. */ + days = stamp->seconds / 86400UL; /* Выделяет количество завершённых календарных суток. */ + remainder = stamp->seconds % 86400UL; /* Сохраняет секунды текущих суток отдельно от календарных вычислений. */ + while (days >= (uint32_t)(length = (uint16_t)(365U + (month_days(year, 2U) == 29U)))) { /* Вычитает полные годы с учётом григорианских исключений. */ + days -= length; /* Оставляет только сутки после текущего полного года. */ + ++year; /* Переходит к следующему году, включая работу после 2099 без нового CAN-пакета. */ + } /* Завершает поиск календарного года. */ + while (days >= (length = month_days(year, month))) { /* Вычитает полные месяцы найденного года. */ + days -= length; /* Сохраняет остаток суток внутри следующего месяца. */ + ++month; /* Продвигает месяц до того, которому принадлежит остаток. */ + } /* Завершает поиск календарного месяца. */ + out->year = year; /* Возвращает полный календарный год. */ + out->month = month; /* Возвращает месяц в привычном диапазоне 1..12. */ + out->day = (uint16_t)(days + 1UL); /* Переводит нулевой индекс остатка суток в календарное число. */ + out->weekday = stamp->weekday; /* Возвращает фазу недели из согласованного снимка, а не из текущих часов. */ + out->hour = (uint16_t)(remainder / 3600UL); /* Выделяет целые часы внутри суток. */ + out->minute = (uint16_t)((remainder % 3600UL) / 60UL); /* Выделяет минуты после последнего полного часа. */ + out->second = (uint16_t)(remainder % 60UL); /* Возвращает остаток секунд текущей минуты. */ + out->millisecond = stamp->millisecond; /* Сохраняет миллисекундную долю исходного снимка. */ + return 1; /* Подтверждает наличие календарной синхронизации в исходной метке. */ +} /* Завершает календарное представление метки логгера. */ diff --git a/c/global-time/tests/f28335_stubs/DSP2833x_Device.h b/c/global-time/tests/f28335_stubs/DSP2833x_Device.h new file mode 100644 index 0000000..a4659db --- /dev/null +++ b/c/global-time/tests/f28335_stubs/DSP2833x_Device.h @@ -0,0 +1,26 @@ +#ifndef GT_TEST_DSP2833X_DEVICE_H /* Изолирует модель регистров от настоящих заголовков TI. */ +#define GT_TEST_DSP2833X_DEVICE_H /* Предотвращает повторное определение тестовых типов. */ +#include /* Использует одинаковые разрядности полей на host-платформе. */ +#define EALLOW ((void)0) /* Модель не требует аппаратного разрешения защищённой записи. */ +#define EDIS ((void)0) /* Закрытие защищённой записи не меняет модельные регистры. */ +#define __interrupt /* Host-компилятор проверяет обычное тело ISR без ABI TI. */ +#define M_INT14 0x2000U /* CPU INT14 соответствует биту 13 в IER/IFR TMS320F28335. */ +union gt_test_reg { /* Даёт модели 32-битный доступ all и поля, которые использует настоящий порт. */ + uint32_t all; /* Имитирует единственный аппаратный доступ к регистру eCAN. */ + struct { unsigned DLC:4; unsigned RTR:1; unsigned DBO:1; } bit; /* Для модели важны доступные имена; фактическую раскладку проверяет отдельная TI-компиляция. */ +}; /* Завершает минимальную модель регистра. */ +struct gt_test_mbox { union gt_test_reg MSGID, MSGCTRL, MDL, MDH; }; /* Выделяет поля mailbox, реально используемые драйвером. */ +struct gt_test_mboxes { struct gt_test_mbox MBOX7, MBOX8; }; /* Не предоставляет портам доступ к невыделенным mailbox. */ +struct gt_test_ecan { union gt_test_reg CANME, CANMD, CANOPC, CANMIL, CANMIM, CANRMP, CANRML, CANTA, CANAA, CANTRS, CANMC; }; /* Моделирует только задействованные управляющие регистры CAN. */ +struct gt_test_lam { union gt_test_reg LAM7; }; /* Предоставляет локальную маску только своего RX. */ +struct gt_test_timer { union gt_test_reg TCR, PRD, TPR, TPRH; }; /* Хранит настройку периода и предделителей CPU Timer2. */ +struct gt_test_vectors { void (*TINT2)(void); }; /* Позволяет вызвать реальный обработчик порта через установленный им вектор. */ +extern struct gt_test_mboxes ECanaMboxes; /* Делит модельные mailbox между портом и тестом. */ +extern struct gt_test_ecan ECanaRegs; /* Делит управляющие регистры между кодом порта и проверками. */ +extern struct gt_test_lam ECanaLAMRegs; /* Делит состояние аппаратного фильтра. */ +extern struct gt_test_timer CpuTimer2Regs; /* Делит конфигурацию автономного миллисекундного таймера. */ +extern struct gt_test_vectors PieVectTable; /* Делит назначенный Timer2 вектор. */ +extern uint16_t IER, IFR; /* Имитирует CPU-регистры разрешения и ожидания прерываний. */ +uint16_t __disable_interrupts(void); /* Предоставляет модель intrinsic с реальным сохранением прежнего состояния. */ +void __restore_interrupts(uint16_t state); /* Предоставляет модель точного восстановления IRQ. */ +#endif /* Завершает защиту тестовой модели аппаратуры. */ diff --git a/c/global-time/tests/run_tests.py b/c/global-time/tests/run_tests.py new file mode 100644 index 0000000..3410ad2 --- /dev/null +++ b/c/global-time/tests/run_tests.py @@ -0,0 +1,36 @@ +"""Проверяет ядро и настоящий порт на host; опционально компилирует их TI C28x.""" # Описывает границу проверки без обещания аппаратного испытания. +import argparse # Принимает явные пути TI SDK вместо привязки библиотеки к рабочему компьютеру. +import os # Настраивает PATH компилятора, чтобы Windows находила его DLL. +from pathlib import Path # Строит пути относительно самого тестового набора. +import shutil # Находит GCC или Clang в окружении разработчика. +import subprocess # Запускает компиляторы аргументами без shell-интерполяции. +import tempfile # Изолирует все исполняемые и объектные файлы во временном каталоге. +root = Path(__file__).resolve().parents[1] # Определяет корень c/global-time независимо от текущего каталога. +parser = argparse.ArgumentParser(description=__doc__) # Показывает назначение host- и TI-проверок при --help. +parser.add_argument("--cc", default=os.environ.get("CC")) # Разрешает явно выбрать совместимый host-компилятор. +parser.add_argument("--ti-cgt", type=Path) # Принимает каталог TI C2000 compiler с bin/cl2000 и include. +parser.add_argument("--ti-headers", type=Path) # Принимает каталог с настоящим DSP2833x_Device.h проекта или TI SDK. +parser.add_argument("--ti-common", type=Path) # Принимает дополнительный каталог DSP2833x_GlobalPrototypes.h из DSP2833x_common/include. +args = parser.parse_args() # Проверяет параметры до создания любых файлов сборки. +candidates = [args.cc, shutil.which("gcc"), shutil.which("clang"), "C:/msys64/ucrt64/bin/gcc.exe"] # Последний путь обеспечивает привычное Windows-окружение без изменения глобального PATH. +compiler = next((str(Path(p).resolve()) for p in candidates if p and Path(p).is_file()), None) # Выбирает первый существующий компилятор, сохраняя явный --cc в приоритете. +if not compiler: # Не заменяет отсутствие компилятора успешным пустым запуском. + parser.error("Укажите --cc с путём к GCC/Clang") # Даёт воспроизводимое требование для запуска регрессий. +if bool(args.ti_cgt) != bool(args.ti_headers): # TI проверка требует одновременно компилятор и аппаратные заголовки. + parser.error("--ti-cgt и --ti-headers нужно указать вместе") # Предотвращает случайную проверку порта с host-моделью вместо SDK. +env = dict(os.environ) # Сохраняет исходное окружение остальных инструментов. +env["PATH"] = str(Path(compiler).parent) + os.pathsep + env.get("PATH", "") # Добавляет соседние DLL GCC только в дочерние процессы тестов. +with tempfile.TemporaryDirectory(prefix="global-time-") as output: # Удаляет только собственный временный каталог после завершения проверок. + for name, sources, includes in [("core", ["src/global_time.c", "tests/test_global_time.c"], ["include"]), ("f28335", ["src/global_time.c", "ports/tms320f28335/global_time_f28335.c", "tests/test_f28335.c"], ["include", "ports/tms320f28335", "tests/f28335_stubs"])]: # Проверяет ядро отдельно и реальный порт с модельными регистрами. + exe = Path(output) / (name + (".exe" if os.name == "nt" else "")) # Сохраняет host-программы за пределами исходного дерева. + command = [compiler, "-std=c99", "-Wall", "-Wextra", "-Werror", "-pedantic", *["-I" + str(root / p) for p in includes], *[str(root / p) for p in sources], "-o", str(exe)] # Считает все предупреждения ошибками и использует реальные исходники библиотеки. + subprocess.run(command, check=True, env=env, timeout=60) # Не маскирует ошибку компиляции успешным запуском старого EXE. + subprocess.run([str(exe)], check=True, env=env, timeout=30) # Выполняет календарные и аппаратные сценарии с ограниченным временем. + if args.ti_cgt: # Дополнительная проверка нужна для ABI с 16-битным char и настоящих регистров TI. + ti = args.ti_cgt.resolve() # Фиксирует абсолютный корень выбранного SDK компилятора. + for source in ["src/global_time.c", "ports/tms320f28335/global_time_f28335.c"]: # Компилирует оба поставляемых MCU исходника без изменения прошивки потребителя. + obj = Path(output) / (Path(source).stem + ".obj") # Разделяет объектные файлы ядра и аппаратного адаптера. + include_paths = [root / "include", root / "ports/tms320f28335", args.ti_headers.resolve(), ti / "include", *([args.ti_common.resolve()] if args.ti_common else [])] # Отдельно подключает common-заголовки старого TI SDK, не смешивая их с host-моделью. + command = [str(ti / "bin/cl2000.exe"), "--compile_only", "-v28", "-ml", "-mt", "--float_support=fpu32", "--abi=coffabi", "--c99", "-O2", "--opt_for_speed=0", "--display_error_number", *["--include_path=" + str(p) for p in include_paths], "--output_file=" + str(obj), str(root / source)] # Использует large/COFF ABI действующего проекта F28335 и штатные заголовки. + subprocess.run(command, check=True, timeout=60) # Ошибка TI C28x останавливает проверку вместо объявления host-модели достаточной. + print("global-time: TI C28x large/COFF compilation OK") # Подтверждает именно компиляцию объектов, не аппаратные испытания или полную линковку прошивки. diff --git a/c/global-time/tests/test_f28335.c b/c/global-time/tests/test_f28335.c new file mode 100644 index 0000000..76c3cb2 --- /dev/null +++ b/c/global-time/tests/test_f28335.c @@ -0,0 +1,88 @@ +#include "DSP2833x_Device.h" /* Использует host-модель регистров, а не альтернативную реализацию драйвера. */ +#include "global_time_f28335.h" /* Тестирует публичные hooks настоящего аппаратного порта. */ +#ifdef NDEBUG /* Не позволяет Release-сборке превратить аппаратные проверки в пустую программу. */ +#undef NDEBUG /* Включает assert независимо от флагов конфигурации CMake. */ +#endif /* Завершает настройку обязательных проверяющих утверждений. */ +#include /* Проверяет сохранность соседних ресурсов, обработку CAN и период Timer2. */ +#include /* Выводит краткое подтверждение проверенных сценариев. */ +struct gt_test_mboxes ECanaMboxes; /* Выделяет модельные MBOX7 и MBOX8. */ +struct gt_test_ecan ECanaRegs; /* Выделяет модель управляющих регистров eCAN-A. */ +struct gt_test_lam ECanaLAMRegs; /* Выделяет локальную маску RX. */ +struct gt_test_timer CpuTimer2Regs; /* Выделяет модель CPU Timer2. */ +struct gt_test_vectors PieVectTable; /* Хранит реальный адрес ISR, назначенный портом. */ +uint16_t IER, IFR; /* Выделяет модель CPU-масок INT14 и соседних прерываний. */ +static uint16_t masked; /* Сохраняет модельное состояние глобальной маски INTM. */ +uint16_t __disable_interrupts(void) /* Моделирует атомарный запрет IRQ и возвращаемый предыдущий INTM. */ +{ /* Повторный запрет из ISR обязан вернуть уже установленную маску. */ + uint16_t old = masked; /* Сохраняет прежнюю маску до её изменения. */ + masked = 1U; /* Имитирует запрет маскируемых IRQ. */ + return old; /* Позволяет реальному порту точно восстановить предыдущий режим. */ +} /* Завершает модель intrinsic запрета. */ +void __restore_interrupts(uint16_t state) /* Восстанавливает маску, полученную соответствующим входом. */ +{ /* Проверяет, что порт действительно вызвал вход в критическую секцию. */ + assert(masked == 1U); /* Восстановление без предшествующего запрета нарушило бы вложенность. */ + masked = state; /* Сохраняет исходный ISR-контекст без безусловного разрешения IRQ. */ +} /* Завершает модель intrinsic восстановления. */ +static void inject(const gt_frame *frame) /* Доставляет wire-данные в аппаратный RX и вызывает настоящий ISR hook. */ +{ /* Не вызывает gt_receive напрямую, проверяя весь путь распаковки MDL/MDH. */ + uint16_t i; /* Перебирает восемь проводных октетов фиксированного classic CAN. */ + ECanaMboxes.MBOX7.MSGID.all = 0xC0000000UL | frame->id; /* Имитирует расширенный ID и включённую локальную фильтрацию eCAN. */ + ECanaMboxes.MBOX7.MSGCTRL.all = frame->dlc | ((uint32_t)frame->remote << 4U); /* Укладывает DLC и RTR в модельный регистр сообщения. */ + ECanaMboxes.MBOX7.MDL.all = ECanaMboxes.MBOX7.MDH.all = 0UL; /* Сбрасывает старый payload перед имитацией нового приёма. */ + for (i = 0U; i < 8U; ++i) { /* Укладывает данные младшим октетом вперёд, как eCAN при DBO=0. */ + if (i < 4U) ECanaMboxes.MBOX7.MDL.all |= (uint32_t)frame->data[i] << (8U * i); /* Первые четыре октета занимают MDL. */ + else ECanaMboxes.MBOX7.MDH.all |= (uint32_t)frame->data[i] << (8U * (i - 4U)); /* Следующие четыре октета занимают MDH. */ + } /* Завершает аппаратное размещение кадра. */ + ECanaRegs.CANRMP.all = 0x82UL; /* Выставляет RX7 и независимый pending legacy mailbox1. */ + gt_f28335_rx_isr(); /* Захватывает временную привязку и кадр в очередь настоящего порта. */ + assert(ECanaRegs.CANRMP.all == 0x80UL); /* Запись W1C должна содержать только бит собственного mailbox, сохраняя pending соседа на аппаратуре. */ + ECanaRegs.CANRMP.all = 2UL; /* Вручную применяет W1C к обычной RAM модели: RX7 снят, RX1 сохранён. */ +} /* Завершает модель получения кадра без подмены алгоритма порта. */ +int main(void) /* Проверяет аппаратную настройку и общий путь ISR → main → метка логгера. */ +{ /* Модель не утверждает электрические тайминги или CAN ACK настоящего трансивера. */ + gt_stamp stamp; /* Читает время через тот же атомарный API, которым будет пользоваться логгер. */ + gt_datetime date = {2026U, 10U, 19U, 1U, 12U, 34U, 56U, 0U}; /* Независимый календарный эталон: понедельник 19 октября 2026 года. */ + gt_frame frame; /* Содержит broadcast мастера для доставки через модель eCAN. */ + uint16_t i; /* Управляет известным числом тиков до обработки кадра в main. */ + gt_f28335_tick_1ms(); gt_f28335_rx_isr(); gt_f28335_service(); /* Ранние hooks до init обязаны безопасно завершаться. */ + ECanaRegs.CANME.all = 0x7FUL; /* Резервирует существующие mailbox0..6 для legacy CAN, Boot и pulse. */ + ECanaRegs.CANMD.all = 0xFFFFFFFAUL; /* Воспроизводит исходные направления legacy mailbox проекта 28335_periph. */ + ECanaRegs.CANMIM.all = 0x4AUL; /* Имитирует разрешённые RX1/RX3/RX6 других CAN-сервисов. */ + ECanaRegs.CANMIL.all = 0x40UL; /* Фиксирует чужую маршрутизацию IRQ, которую порт обязан сохранить. */ + assert(!gt_f28335_init_periph(32U)); /* Некорректный физический адрес не должен открыть новый CAN-сервис. */ + assert(gt_f28335_init_periph(5U)); /* Настраивает УМП1 как PERIPH5, Type1/ID5. */ + assert(ECanaRegs.CANME.all == 0x1FFUL && (ECanaRegs.CANMD.all & 0x7FUL) == 0x7AUL); /* Проверяет добавление только mailbox7/8 и сохранность чужих направлений. */ + assert(ECanaRegs.CANMIM.all == 0xCAUL && ECanaRegs.CANMIL.all == 0x40UL); /* Проверяет RX7 IRQ line0 без изменения RX1/RX3/RX6. */ + assert(ECanaMboxes.MBOX7.MSGID.all == 0xC0000030UL && ECanaLAMRegs.LAM7.all == 0x10000000UL); /* Фильтр принимает только время мастера с любым приоритетом. */ + ECanaRegs.CANTA.all = ECanaRegs.CANAA.all = ECanaRegs.CANRMP.all = 0UL; /* Применяет к RAM модели W1C, выполненные init на реальной аппаратуре. */ + gt_f28335_service(); /* Проверяет первый проход main при отсутствии входящего кадра. */ + assert(ECanaRegs.CANTRS.all == 0UL); /* Сам init не должен объявить готовность прикладной платы. */ + gt_f28335_ready(); gt_f28335_service(); /* Публикует прикладной успех и запускает передачу из main. */ + assert(ECanaRegs.CANTRS.all == 0x100UL && ECanaMboxes.MBOX8.MSGID.all == 0x99513000UL && ECanaMboxes.MBOX8.MDL.all == 1UL); /* Проверяет точный аппаратный запрос READY с правильным адресом. */ + assert(gt_make_rtc(&date, &frame)); /* Строит штатный RTCSETUP без аппаратного RTC мастера в тесте. */ + inject(&frame); /* Проверяет разбор всех календарных полей через настоящий RX ISR. */ + for (i = 0U; i < 37U; ++i) gt_f28335_tick_1ms(); /* Имитирует 37 мс задержки main при продолжающемся такте. */ + gt_f28335_service(); /* Применяет отложенный RX и сохраняет привязку к исходному моменту приёма. */ + gt_get(gt_f28335_clock(), &stamp); /* Снимает тот же экземпляр часов, что обслуживает порт. */ + assert(gt_calendar(&stamp, &date) && date.year == 2026U && date.month == 10U && date.day == 19U && date.hour == 12U && date.minute == 34U && date.second == 56U && date.millisecond == 37U); /* Проверяет календарь и компенсацию задержки всего пути приёма. */ + assert(stamp.sync_uptime_ms == 0UL && stamp.uptime_ms == 37UL); /* Очередь не должна подменить время RX временем обработки main. */ + ECanaRegs.CANTA.all = 0x100UL; ECanaRegs.CANTRS.all = 0UL; /* Имитирует аппаратный ACK ранее отправленной готовности. */ + gt_f28335_service(); /* Освобождает собственный TX без повторной отправки после синхронизации. */ + ECanaRegs.CANTA.all = ECanaRegs.CANAA.all = 0UL; /* Применяет аппаратное W1C к RAM модели ACK. */ + assert(ECanaRegs.CANTRS.all == 0UL); /* Синхронизация прекращает повторную стартовую рассылку. */ + IER = 0x1001U; IFR = 0x3001U; /* Подготавливает чужие CPU IRQ и старый pending INT14. */ + assert(!gt_f28335_timer2_start(150000001UL)); /* Некратная 1000 частота не должна давать скрытый дробный период. */ + assert(gt_f28335_timer2_start(150000000UL)); /* Настраивает аппаратные 1 мс для типичной частоты F28335 150 МГц. */ + assert(CpuTimer2Regs.PRD.all == 149999UL && CpuTimer2Regs.TPR.all == 0UL && CpuTimer2Regs.TPRH.all == 0UL); /* Проверяет включительный период PRD..0 и отсутствие предделителей. */ + assert(IER == 0x3001U && IFR == 0x1001U && CpuTimer2Regs.TCR.all == 0xC020UL); /* Сохраняет чужие CPU маски и запускает только Timer2. */ + PieVectTable.TINT2(); /* Вызывает реальное тело ISR через вектор, назначенный портом. */ + gt_get(gt_f28335_clock(), &stamp); /* Проверяет единственный миллисекундный шаг собственного ISR. */ + assert(stamp.uptime_ms == 38UL && stamp.millisecond == 38U); /* Timer2 должен добавлять ровно один тик на прерывание. */ + assert(!gt_f28335_init_periph(6U)); /* Повторный init не должен потерять владение работающим Timer2. */ + gt_f28335_timer2_stop(); /* Освобождает ранее захваченный аппаратный такт. */ + assert(IER == 0x1001U && CpuTimer2Regs.TCR.all == 0x8010UL && masked == 0U); /* Остановка сохраняет чужие IRQ и исходный глобальный INTM. */ + ECanaRegs.CANMC.bit.DBO = 1U; /* Имитирует несовместимый порядок октетов контроллера. */ + assert(!gt_f28335_init_periph(6U)); /* Не позволяет молча декодировать другую аппаратную раскладку payload. */ + puts("global-time F28335: eCAN isolation, RX delay, ACK and Timer2 OK"); /* Выводит компактный результат аппаратных сценариев. */ + return 0; /* Завершает проверку после всех обязательных утверждений. */ +} /* Завершает host-регрессию порта TI F28335. */ diff --git a/c/global-time/tests/test_global_time.c b/c/global-time/tests/test_global_time.c new file mode 100644 index 0000000..ecfa67a --- /dev/null +++ b/c/global-time/tests/test_global_time.c @@ -0,0 +1,145 @@ +#include "global_time.h" /* Проверяет настоящий переносимый код часов без подмены его реализации. */ +#ifdef NDEBUG /* Проверки должны выполняться и при Release-сборке CMake. */ +#undef NDEBUG /* Сохраняет assert активным независимо от выбранного уровня оптимизации. */ +#endif /* Завершает принудительное включение проверяющих утверждений. */ +#include /* Останавливает тест при нарушении временного или проводного контракта. */ +#include /* Выводит компактное подтверждение выполнения набора проверок. */ +#include /* Позволяет воспроизвести ненулевую RAM после тёплого старта. */ +static uint16_t irq_mask, depth; /* Моделирует исходную маску IRQ и вложенность критических секций. */ +static int accepted, sends; /* Управляет занятостью транспорта и считает попытки объявления готовности. */ +static gt_frame sent; /* Сохраняет последний кадр для независимой проверки ID и payload. */ +static uint16_t enter(void *user) /* Моделирует TI intrinsic с сохранением предыдущего INTM. */ +{ /* Проверяет, что ядро пользуется единым механизмом защиты состояния. */ + uint16_t previous = irq_mask; /* Сохраняет маску до входа в текущий уровень блокировки. */ + assert(user == &sends); /* Подтверждает неизменную передачу пользовательского контекста. */ + irq_mask = 1U; /* Запрещает модельным прерываниям менять данные до leave. */ + ++depth; /* Отмечает вложенный уровень для контроля парности входа и выхода. */ + return previous; /* Возвращает исходное состояние, включая вызов из уже закрытого ISR. */ +} /* Завершает модель входа в критическую секцию. */ +static void leave(void *user, uint16_t previous) /* Проверяет восстановление предыдущей маски без безусловного разрешения. */ +{ /* Делает нарушения вложенности видимыми в host-тесте. */ + assert(user == &sends && depth > 0U && irq_mask == 1U); /* Выход допустим только из реально захваченной секции. */ + --depth; /* Освобождает один уровень модельной блокировки. */ + irq_mask = previous; /* Возвращает именно исходную маску вызывающего кода. */ +} /* Завершает проверяемую модель выхода. */ +static int send(void *user, const gt_frame *frame) /* Моделирует неблокирующую передачу и копирование временного payload. */ +{ /* Callback не должен выполняться с длинной критической секцией ядра. */ + assert(user == &sends && depth == 0U); /* Проверяет передачу контекста и отсутствие блокировки IRQ на время отправки. */ + ++sends; /* Считает и принятые, и отклонённые транспортом попытки. */ + sent = *frame; /* Сохраняет независимую копию до возврата callback. */ + return accepted; /* Имитирует занятость mailbox без ожидания. */ +} /* Завершает модель транспорта. */ +static void advance(gt_clock *clock, uint32_t milliseconds) /* Продвигает реальный алгоритм через границы календарных полей. */ +{ /* Пошаговый вызов также проверяет миллисекундные переносы в ISR. */ + while (milliseconds--) gt_tick_1ms(clock); /* Не подменяет поведение таймера прямой правкой абсолютного времени. */ +} /* Завершает управляемое продвижение времени. */ +static gt_frame rtc(uint16_t year, uint16_t month, uint16_t day, uint16_t hour, uint16_t minute, uint16_t second) /* Строит календарный эталон кодировщиком верхнего уровня. */ +{ /* Ожидаемые значения времени в тестах проверяются отдельно от кодировщика. */ + gt_datetime date = {year, month, day, 6U, hour, minute, second, 0U}; /* День недели сохраняется как допустимая фаза цикла, исходная суббота=6. */ + gt_frame frame; /* Получает полноценный расширенный CAN кадр. */ + assert(gt_make_rtc(&date, &frame)); /* Корректный календарь обязан кодироваться в существующие семь октетов. */ + return frame; /* Возвращает независимый контейнер для изменения ошибочных полей. */ +} /* Завершает построение тестовых опорных кадров. */ +int main(void) /* Проверяет календарь, коррекции, задержки, переполнения и стартовый CAN-обмен. */ +{ /* Использует только публичный API, кроме целевой установки границы uptime. */ + gt_clock clock; /* Состояние заполняется мусором, имитируя startup без очистки .ebss. */ + gt_port port = {&sends, enter, leave, send}; /* Подключает проверяющие блокировки и управляемый транспорт. */ + gt_stamp stamp, before; /* Два атомарных снимка позволяют проверять отсутствие побочных изменений при ошибке. */ + gt_datetime date; /* Календарный результат проверяется по известным границам дат. */ + gt_frame frame, bad; /* Исходный корректный кадр и копия для отрицательных проверок. */ + uint16_t type, id, index; /* Полученные адресные поля и индекс проверки каждого октета. */ + const uint16_t invalid[7] = {24U, 60U, 60U, 100U, 0U, 0U, 7U}; /* Независимые граничные ошибки каждого календарного поля на линии. */ + memset(&clock, 0xA5, sizeof(clock)); /* Воспроизводит остатки RAM вместо неявной инициализации нулями хоста. */ + assert(!gt_init(&clock, &port, 8U, 0U)); /* Запрещает трёхбитному типу переполниться в направление Route. */ + assert(!gt_init(&clock, &port, 1U, 16U)); /* Запрещает молчаливое обрезание экземпляра до адреса другой платы. */ + assert(gt_init(&clock, &port, 1U, 5U)); /* Создаёт УМП1 по действующему реестру PERIPH. */ + gt_get(&clock, &stamp); /* Проверяет результат явной инициализации всей временной базы. */ + assert(stamp.seconds == 0UL && stamp.uptime_ms == 0UL && !stamp.synchronized && stamp.generation == 0UL); /* До синхронизации календарь не должен выглядеть достоверным. */ + assert(!gt_calendar(&stamp, &date)); /* Не позволяет приложению выдавать локальную эпоху за полученную дату. */ + advance(&clock, 1001UL); /* Пересекает первую секундную границу программного таймера. */ + gt_get(&clock, &stamp); /* Снимает дробную часть после переноса секунды. */ + assert(stamp.seconds == 1UL && stamp.millisecond == 1U && stamp.uptime_ms == 1001UL); /* Проверяет ровно 1000 тиков на секунду без ошибки на единицу. */ + gt_poll(&clock); /* Пытается обслужить отправку до завершения инициализации платы. */ + assert(sends == 0); /* Пакет готовности запрещён до явного ready. */ + gt_ready(&clock); /* Разрешает стартовый пакет только после прикладной готовности. */ + gt_poll(&clock); /* Имитирует занятую CAN передачу при accepted=0. */ + assert(sends == 1 && !clock.announced); /* Занятость транспорта не теряет обязательный пакет инициализации. */ + accepted = 1; /* Освобождает транспорт на следующем проходе main. */ + gt_poll(&clock); /* Повторяет отклонённую попытку без задержки и блокировки IRQ. */ + assert(sends == 2 && sent.id == 0x19513000UL && sent.dlc == 1U && sent.data[0] == 1U); /* Фиксирует проводной эталон READY узла Type=1, ID=5. */ + assert(gt_parse_ready(&sent, &type, &id) && type == 1U && id == 5U); /* Мастер должен узнать физический адрес стартовавшей платы. */ + bad = sent; /* Готовит отрицательный вариант стартового сообщения. */ + bad.id ^= 0x08000000UL; /* Меняет направление на запрос мастера, сохранив payload. */ + assert(!gt_parse_ready(&bad, 0, 0)); /* Исключает распознавание собственного запроса как готовности платы. */ + advance(&clock, 999UL); /* Проверяет ограничение частоты повторов перед секундной границей. */ + gt_poll(&clock); /* Обслуживает CAN на последней миллисекунде запрета повтора. */ + assert(sends == 2); /* Готовность не должна засорять шину на каждом проходе main. */ + advance(&clock, 1UL); /* Достигает точно секундного интервала повторной отправки. */ + gt_poll(&clock); /* Повторяет событие старта при отсутствии ответа временем. */ + assert(sends == 3); /* Потерянный ответ мастера должен приводить к повтору объявления готовности. */ + frame = rtc(2024U, 2U, 28U, 23U, 59U, 59U); /* Задаёт известную границу високосного февраля. */ + assert(frame.id == 0x30UL && frame.dlc == 7U && frame.data[3] == 24U && frame.data[4] == 2U); /* Проверяет совместимый ID и календарный wire format. */ + assert(gt_receive(&clock, &frame, clock.stamp.uptime_ms)); /* Устанавливает первую реальную календарную дату. */ + advance(&clock, 1001UL); /* Пересекает полночь на один миллисекундный тик. */ + gt_get(&clock, &stamp); /* Снимает календарную метку после перехода даты. */ + assert(gt_calendar(&stamp, &date) && date.year == 2024U && date.month == 2U && date.day == 29U && date.hour == 0U && date.millisecond == 1U); /* Проверяет 29 февраля и сброс часов/минут/секунд на полночь. */ + assert(stamp.weekday == 0U && stamp.generation == 1UL); /* День недели циклически продвигается, а тики не создают новые поколения коррекции. */ + assert(gt_timestamp_ms(&stamp) > UINT32_MAX); /* Календарные миллисекунды остаются широкими и не обрезаются до uptime. */ + advance(&clock, 2000UL); /* Даёт мастеру время ответить; уже синхронизированный узел не повторяет READY. */ + gt_poll(&clock); /* Проверяет прекращение стартовых повторов после RTCSETUP. */ + assert(sends == 3); /* Получение календаря завершает повторный запрос времени. */ + before = stamp; /* Сохраняет известную метку для проверки отрицательной коррекции. */ + frame = rtc(2000U, 1U, 1U, 0U, 0U, 0U); /* Задаёт независимый эталон нулевой секунды эпохи библиотеки. */ + assert(gt_receive(&clock, &frame, clock.stamp.uptime_ms)); /* Применяет разрешённый перевод глобальных часов назад. */ + gt_get(&clock, &stamp); /* Снимает результат атомарной коррекции. */ + assert(stamp.seconds == 0UL && stamp.millisecond == 0U && stamp.correction_ms < 0 && stamp.uptime_ms > before.uptime_ms && stamp.generation == 2UL); /* Проверяет независимость тайм-аутов от отрицательной календарной коррекции. */ + assert(gt_timestamp_ms(&stamp) == 0ULL); /* Фиксирует точное начало принятой эпохи. */ + before = stamp; /* Сохраняет состояние до серии ошибочных CAN кадров. */ + for (index = 0U; index < 7U; ++index) { /* Проверяет наличие лишних старших битов в каждом слове, содержащем октет C28x. */ + bad = frame; /* Восстанавливает исходный корректный RTCSETUP перед каждой ошибкой. */ + bad.data[index] = 256U; /* Значение вне одного проводного октета не должно обрезаться до нуля. */ + assert(!gt_receive(&clock, &bad, before.uptime_ms)); /* Отвергает ошибку порта до изменения даты. */ + bad = frame; /* Возвращает корректный исходный кадр для проверки допустимого диапазона поля. */ + bad.data[index] = invalid[index]; /* Подставляет двоичное, но календарно недопустимое значение. */ + assert(!gt_receive(&clock, &bad, before.uptime_ms)); /* Исключает нормализацию ошибочного времени и выход за границы таблицы месяцев. */ + } /* Завершает проверку всей широкой wire-границы. */ + bad = frame; bad.extended = 0U; /* Подготавливает стандартный 11-битный кадр с похожим ID. */ + assert(!gt_receive(&clock, &bad, before.uptime_ms)); /* ProtoCAN требует IDE=1 независимо от численного ID. */ + bad = frame; bad.remote = 1U; /* Подготавливает RTR без реальных календарных данных. */ + assert(!gt_receive(&clock, &bad, before.uptime_ms)); /* Удалённый запрос не устанавливает глобальное время. */ + bad = frame; bad.dlc = 8U; /* Добавляет неописанный восьмой октет без согласованного расширения протокола. */ + assert(!gt_receive(&clock, &bad, before.uptime_ms)); /* Длина существующего RTCSETUP должна быть ровно семь октетов. */ + bad = frame; bad.id |= 0x01000000UL; /* Имитирует broadcast от чужого типа устройства вместо верхнего уровня. */ + assert(!gt_receive(&clock, &bad, before.uptime_ms)); /* Исключает коррекцию по произвольным сообщениям другой платы. */ + bad = frame; bad.data[4] = 2U; bad.data[5] = 30U; /* Подготавливает несуществующее 30 февраля високосного года. */ + assert(!gt_receive(&clock, &bad, before.uptime_ms)); /* Календарные ошибки не нормализуются в другую дату. */ + bad = frame; bad.data[3] = 23U; bad.data[4] = 2U; bad.data[5] = 29U; /* Подготавливает 29 февраля невисокосного года. */ + assert(!gt_receive(&clock, &bad, before.uptime_ms)); /* Отвергает некорректную дату даже при допустимых диапазонах отдельных полей. */ + gt_get(&clock, &stamp); /* Проверяет итоговое состояние после всех отклонённых кадров. */ + assert(stamp.seconds == before.seconds && stamp.generation == before.generation && stamp.synchronized); /* Неверные пакеты не теряют последнюю достоверную синхронизацию. */ + before.seconds = 3160857600UL; /* Независимый календарный эталон: ровно 36584 суток от 2000-01-01 до 2100-03-01. */ + assert(gt_calendar(&before, &date) && date.year == 2100U && date.month == 3U && date.day == 1U); /* Проверяет исключение невисокосного 2100 года при продолжении локального хода часов. */ + clock.stamp.uptime_ms = UINT32_MAX - 4UL; /* Целевым образом размещает монотонный счётчик около переполнения 49,7 суток. */ + advance(&clock, 10UL); /* Пересекает modulo-границу до обработки уже полученного кадра. */ + frame.id |= 0x10000000UL; /* Проверяет допустимость стандартного приоритета RTCSETUP наряду с критическим. */ + assert(gt_receive(&clock, &frame, UINT32_MAX - 4UL)); /* Передаёт момент RX до переполнения, обработку — после. */ + gt_get(&clock, &stamp); /* Снимает скорректированную фазу доли секунды. */ + assert(stamp.seconds == 0UL && stamp.millisecond == 10U && stamp.uptime_ms == 5UL); /* Компенсация очереди должна быть 10 мс, независимо от переполнения uptime. */ + frame = rtc(2023U, 12U, 31U, 23U, 59U, 59U); /* Проверяет смену календарного года при отложенной обработке. */ + before = stamp; /* Запоминает момент RX непосредственно перед задержкой основного цикла. */ + advance(&clock, 1250UL); /* Имитирует долгую прикладную операцию при продолжающемся аппаратном таймере. */ + assert(gt_receive(&clock, &frame, before.uptime_ms)); /* Применяет время по моменту RX, а не по моменту выхода из очереди. */ + gt_get(&clock, &stamp); /* Снимает дату после учёта задержки обработки. */ + assert(gt_calendar(&stamp, &date) && date.year == 2024U && date.month == 1U && date.day == 1U && date.second == 0U && date.millisecond == 250U); /* Проверяет перенос секунды, суток и года с сохранением 250 мс. */ + irq_mask = 1U; /* Имитирует вызов логгера из ISR с уже запрещёнными прерываниями. */ + gt_get(&clock, &stamp); /* Проверяет чтение метки при вложенной критической секции. */ + gt_tick_1ms(&clock); /* Проверяет продвижение часов при исходном INTM=1. */ + assert(irq_mask == 1U && depth == 0U); /* Выходы не должны случайно разрешить IRQ вызывающего обработчика. */ + irq_mask = 0U; /* Восстанавливает модельное окружение main перед новой инициализацией. */ + assert(gt_init(&clock, &port, 2U, 15U)); /* Проверяет холодный reset качества и верхний адрес PERIPH31. */ + assert(gt_receive(&clock, &frame, 0UL)); /* Имитирует broadcast ещё до прикладного ready. */ + gt_ready(&clock); gt_ready(&clock); gt_poll(&clock); /* Повторный ready должен быть идемпотентным, но первая отправка всё равно обязательна. */ + assert(sends == 4 && gt_parse_ready(&sent, &type, &id) && type == 2U && id == 15U); /* Ранняя синхронизация не подавляет сообщение об успешной инициализации платы. */ + puts("global-time: calendar, CAN, correction, IRQ and rollover OK"); /* Возвращает краткое свидетельство пройденных смысловых сценариев. */ + return 0; /* Завершает host-тест только после всех обязательных проверок. */ +} /* Завершает независимую проверку переносимого ядра. */ diff --git a/c/led-indicator/README.md b/c/led-indicator/README.md index 7b36a85..7cbcf69 100644 --- a/c/led-indicator/README.md +++ b/c/led-indicator/README.md @@ -28,7 +28,7 @@ | `OFF` / `ON` | постоянно выключен / включён | | `STARTUP` | три коротких импульса, затем постоянно включён | | `WORK` | 100 мс включён, 900 мс выключен | -| `ACTIVITY` | 50/50 мс | +| `ACTIVITY` | один цикл: 100 мс включён, 900 мс выключен, затем остаётся выключенным | | `WARNING` | 250/250 мс | | `ERROR` | два импульса и пауза | | `CRITICAL` | три импульса и пауза | @@ -86,6 +86,20 @@ for (;;) { не начинает рисунок заново. Для нового импульса события служит `LedIndicator_RestartMode`. +Для индикации приёма вызывайте `LedIndicator_TriggerActivity` либо +`LedIndicator_TriggerActivityAt` на каждый принятый пакет. Свечение занимает +10% секундного цикла: 100 мс включён и 900 мс выключен. Новый приём немедленно +перезапускает фазу свечения, даже внутри предыдущего импульса или паузы; +очереди циклов нет. При интервалах между пакетами меньше 100 мс LED может +гореть непрерывно до истечения 100 мс после последнего пакета. Без нового +события `ACTIVITY` не повторяется. Настраиваемая таблица `patterns` по-прежнему +позволяет изменить длительности и повторение для других применений. + +```c +LedIndicator_TriggerActivityAt(&led, 0U, received_ms); /* Каждый приём запускает цикл канала 0 от миллисекундной метки события. */ +LedIndicator_ProcessAt(&led, now_ms); /* Главный цикл обслуживает окончание свечения без задержек и ожидания следующего пакета. */ +``` + ## STM32F103, STM32F4, STM32G431 и STM32G474 Порт `ports/stm32-hal` принимает конкретный `TIM_HandleTypeDef *`; библиотека diff --git a/c/led-indicator/led_indicator.c b/c/led-indicator/led_indicator.c index 13e998d..c3aaa5f 100644 --- a/c/led-indicator/led_indicator.c +++ b/c/led-indicator/led_indicator.c @@ -18,7 +18,7 @@ static const LedIndicator_Pattern g_default_patterns[LED_INDICATOR_MODE_COUNT] = {{0U}, LEVELS_1, 1U, 1U, 1U}, {{100U, 100U, 100U, 100U, 100U, 100U}, LEVELS_101010, 6U, 0U, 1U}, {{100U, 900U}, LEVELS_10, 2U, 1U, 0U}, - {{50U, 50U}, LEVELS_10, 2U, 1U, 0U}, + {{100U, 900U}, LEVELS_10, 2U, 0U, 0U}, /* Один цикл приёма длится 1000 мс: 100 мс свечения составляют 10%, затем 900 мс паузы и выключение. */ {{250U, 250U}, LEVELS_10, 2U, 1U, 0U}, {{100U, 100U, 100U, 700U}, LEVELS_1010, 4U, 1U, 0U}, {{100U, 100U, 100U, 100U, 100U, 700U}, LEVELS_101010, 6U, 1U, 0U} @@ -220,6 +220,16 @@ uint8_t LedIndicator_RestartMode(LedIndicator *instance, size_t channel, instance->port.now_ms(instance->port.context)); } +uint8_t LedIndicator_TriggerActivityAt(LedIndicator *instance, size_t channel, uint32_t now_ms) /* Каждый пакет начинает ACTIVITY заново, даже если предыдущая вспышка ещё продолжается. */ +{ /* Использует общую проверку канала и принудительный сброс фазы в миллисекундной временной базе. */ + return LedIndicator_RestartModeAt(instance, channel, LED_INDICATOR_MODE_ACTIVITY, now_ms); /* Штатный однократный шаблон завершает цикл выключенным уровнем без свободного повторения. */ +} /* Завершает запуск одного цикла приёма без ожидания окончания свечения либо паузы. */ + +uint8_t LedIndicator_TriggerActivity(LedIndicator *instance, size_t channel) /* Предоставляет тот же перезапуск по событию с использованием часов аппаратного порта. */ +{ /* Сохраняет поведение варианта At для приложения без собственного передаваемого времени. */ + return LedIndicator_RestartMode(instance, channel, LED_INDICATOR_MODE_ACTIVITY); /* Часы порта считываются штатным API один раз на зарегистрированный приём. */ +} /* Завершает неблокирующий запуск цикла приёма с аппаратным источником времени. */ + void LedIndicator_ProcessAt(LedIndicator *instance, uint32_t now_ms) { size_t i; diff --git a/c/led-indicator/led_indicator.h b/c/led-indicator/led_indicator.h index a910599..626fe79 100644 --- a/c/led-indicator/led_indicator.h +++ b/c/led-indicator/led_indicator.h @@ -114,6 +114,12 @@ void LedIndicator_Process(LedIndicator *instance); /** Обновляет выходы с явно переданной меткой времени. */ void LedIndicator_ProcessAt(LedIndicator *instance, uint32_t now_ms); +/** Начинает один цикл ACTIVITY на каждый приём; новый вызов немедленно перезапускает свечение, не создавая очередь. */ +uint8_t LedIndicator_TriggerActivityAt(LedIndicator *instance, size_t channel, uint32_t now_ms); /* Стандартный цикл: 100 мс включён, 900 мс выключен; время задаётся в миллисекундах. */ + +/** Использует часы аппаратного порта для такого же перезапуска цикла при каждом приёме. */ +uint8_t LedIndicator_TriggerActivity(LedIndicator *instance, size_t channel); /* Вызывать из контекста Process; передачу событий из ISR обеспечивает приложение. */ + LedIndicator_Mode LedIndicator_GetMode(const LedIndicator *instance, size_t channel); #ifdef __cplusplus diff --git a/c/led-indicator/tests/test_led_indicator.c b/c/led-indicator/tests/test_led_indicator.c index b72cc9d..8db9fc7 100644 --- a/c/led-indicator/tests/test_led_indicator.c +++ b/c/led-indicator/tests/test_led_indicator.c @@ -85,6 +85,26 @@ int main(void) CHECK(LedIndicator_SetMode(&indicator, 3U, LED_INDICATOR_MODE_ON) == 0U); CHECK(LedIndicator_GetMode(&indicator, 0U) == LED_INDICATOR_MODE_WORK); - puts("led indicator tests passed"); + CHECK(patterns[LED_INDICATOR_MODE_ACTIVITY].duration_ms[0] == 100U && patterns[LED_INDICATOR_MODE_ACTIVITY].duration_ms[1] == 900U && patterns[LED_INDICATOR_MODE_ACTIVITY].repeat == 0U); /* Фиксирует согласованные 10% свечения и один цикл на приём в канонической таблице. */ + CHECK(LedIndicator_TriggerActivityAt(&indicator, 0U, 2500U) != 0U && fake.outputs[0] == 1U); /* Приём сразу включает канал независимо от фазы прежнего WORK. */ + LedIndicator_ProcessAt(&indicator, 2599U); CHECK(fake.outputs[0] == 1U); /* До истечения 100 мс светодиод продолжает гореть. */ + LedIndicator_ProcessAt(&indicator, 2600U); CHECK(fake.outputs[0] == 0U); /* Ровно через 100 мс начинается оставшаяся пауза 900 мс. */ + LedIndicator_ProcessAt(&indicator, 3499U); CHECK(fake.outputs[0] == 0U); /* Конец первого периода не порождает дополнительную вспышку. */ + LedIndicator_ProcessAt(&indicator, 3500U); CHECK(fake.outputs[0] == 0U); /* Однократный ACTIVITY завершается выключенным уровнем на границе 1000 мс. */ + LedIndicator_ProcessAt(&indicator, 4500U); CHECK(fake.outputs[0] == 0U); /* Без новых пакетов свободное периодическое мигание отсутствует. */ + CHECK(LedIndicator_TriggerActivityAt(&indicator, 0U, 5000U) != 0U); /* Начинает новый приём после долгого отсутствия обмена. */ + CHECK(LedIndicator_TriggerActivityAt(&indicator, 0U, 5050U) != 0U); /* Второй пакет приходит внутри текущей фазы свечения. */ + LedIndicator_ProcessAt(&indicator, 5100U); CHECK(fake.outputs[0] == 1U); /* Старый срок выключения больше не действует: отсчёт перезапущен новым пакетом. */ + LedIndicator_ProcessAt(&indicator, 5149U); CHECK(fake.outputs[0] == 1U); /* Новый пакет получает собственные полные 100 мс свечения. */ + LedIndicator_ProcessAt(&indicator, 5150U); CHECK(fake.outputs[0] == 0U); /* Новая фаза паузы начинается ровно от последнего приёма. */ + CHECK(LedIndicator_TriggerActivityAt(&indicator, 0U, 5400U) != 0U && fake.outputs[0] == 1U); /* Приём во время паузы сразу включает LED вместо ожидания границы старого периода. */ + LedIndicator_ProcessAt(&indicator, 5500U); CHECK(fake.outputs[0] == 0U); /* Повторный запуск в паузе не создаёт очередь пропущенных циклов. */ + fake.now = 7000U; CHECK(LedIndicator_TriggerActivity(&indicator, 1U) != 0U && fake.outputs[1] == 1U); /* Проверяет вариант событийного API с часами аппаратного порта и другим каналом. */ + fake.now = 7100U; LedIndicator_Process(&indicator); CHECK(fake.outputs[1] == 0U && fake.outputs[0] == 0U); /* Каналы не перезапускают друг другу фазы и не создают фоновую активность. */ + CHECK(LedIndicator_TriggerActivityAt(&indicator, 0U, UINT32_MAX - 49U) != 0U); /* Начинает импульс непосредственно перед переполнением 32-битного времени. */ + LedIndicator_ProcessAt(&indicator, 49U); CHECK(fake.outputs[0] == 1U); /* Через переполнение прошло 99 мс, поэтому свечение ещё активно. */ + LedIndicator_ProcessAt(&indicator, 50U); CHECK(fake.outputs[0] == 0U); /* Через переполнение прошло ровно 100 мс, и LED гаснет без зависания. */ + CHECK(LedIndicator_TriggerActivityAt(NULL, 0U, 0U) == 0U && LedIndicator_TriggerActivityAt(&indicator, 3U, 0U) == 0U); /* Ошибочный экземпляр и канал не вызывают запись чужого GPIO. */ + puts("led indicator tests passed: receive 100/900 ms, immediate retrigger, no repeat, timer wrap"); /* Показывает прохождение новых событийных сценариев вместе с прежней диагностикой. */ return 0; } diff --git a/c/parallel-nand/docs/MEMORY_GAS.md b/c/parallel-nand/docs/MEMORY_GAS.md index a91be51..4792dd2 100644 --- a/c/parallel-nand/docs/MEMORY_GAS.md +++ b/c/parallel-nand/docs/MEMORY_GAS.md @@ -1,5 +1,7 @@ # Работа с parallel NAND через GAS +> GAS `0x3` использует адреса отдельных 16-битных регистров. GAS SLOT `0x4` — отдельный сервис с маской в Word0 и тремя значениями Word1…Word3. Спецификация: `doc/setcan/protocan/OAP.md`; адреса этого документа остаются регистровыми. + ## Архитектура Внешняя NAND значительно больше общего адресного пространства GAS. Например, diff --git a/c/protocan-boot/.gitignore b/c/protocan-boot/.gitignore new file mode 100644 index 0000000..01b5059 --- /dev/null +++ b/c/protocan-boot/.gitignore @@ -0,0 +1,8 @@ +# Результаты отдельных конфигураций CCS воспроизводятся установленным TI compiler. +/projects/ccs/*/Debug/ +/projects/ccs/*/Release/ +# Служебные локальные настройки IDE и launch не входят в переносимый проект. +/projects/ccs/*/.settings/ +/projects/ccs/*/.launches/ +# Python cache не является исходником общего модуля или проекта. +**/__pycache__/ diff --git a/c/protocan-boot/CMakeLists.txt b/c/protocan-boot/CMakeLists.txt index 2548300..7d253b5 100644 --- a/c/protocan-boot/CMakeLists.txt +++ b/c/protocan-boot/CMakeLists.txt @@ -1,6 +1,6 @@ -# РЎР±РѕСЂРєР° библиотеки protocan_boot. Состав РёСЃС…РѕРґРЅРёРєРѕРІ Рё публичные include-пути задают -# подключение Рє проекту потребителя. Файл также собирает Рё регистрирует хостовые проверки; -# запускать РёС… следует через CTest РёР· каталога СЃР±РѕСЂРєРё. +# Общая C99-библиотека ProtoCAN Boot и аппаратно независимые host-тесты. +# Каждый контроллер сохраняет собственное состояние и отдельный аппаратный порт. +# Дополнительные проекты CCS находятся в projects/ccs и не требуют CMake для TI-сборки. cmake_minimum_required(VERSION 3.13) project(protocan_boot C) @@ -17,7 +17,7 @@ else() target_compile_options(protocan_boot PRIVATE -Wall -Wextra -Wpedantic) endif() -option(PCAN_BOOT_BUILD_TESTS "Собирать тесты ProtoCAN boot" ON) +option(PCAN_BOOT_BUILD_TESTS "Собирать тесты ProtoCAN Boot" ON) # Не включает host-модели в код MCU. if(PCAN_BOOT_BUILD_TESTS) enable_testing() add_executable(test_pcan_boot tests/test_pcan_boot.c) @@ -45,3 +45,32 @@ if(PCAN_BOOT_BUILD_TESTS) add_test(NAME f28335_store_${width} COMMAND test_f28335_store_${width}) endforeach() endif() + +if(PCAN_BOOT_BUILD_TESTS) # Подключает настоящий аппаратно независимый драйвер NOR F2812 и регрессию длительного BUSY. + add_executable(test_f2812_nor tests/test_f2812_nor.c src/pcan_boot.c ports/tms320f2812/nor_flash.c ports/tms320f2812/boot_store.c) # Компилирует production-код вместе с x16 моделью чипа. + target_compile_definitions(test_f2812_nor PRIVATE PCAN_BOOT_WIDE_BYTES BOOT2812_HOST) # Октеты C28x широкие; подменяется только физическая шина памяти. + add_test(NAME f2812_nor COMMAND test_f2812_nor) # Регистрирует проверки CRC, SCI8, границ, manifest и отказов NOR. + add_executable(test_pcan_busy tests/test_pcan_busy.c src/pcan_boot.c) # Использует тот же codec, который обслуживает длинные аппаратные операции. + target_compile_definitions(test_pcan_busy PRIVATE PCAN_BOOT_WIDE_BYTES) # Проверяет wire-статус при 16-битном представлении октета C28x. + add_test(NAME pcan_busy COMMAND test_pcan_busy) # Регистрирует проверку продления session при живом прогрессе erase. +endif() # Включение библиотек без тестов не добавляет host-модель в прошивку. + +if(PCAN_BOOT_BUILD_TESTS) # STM32-порты проверяются с моделью HAL и приватным отображением Flash, без доступа к плате. + foreach(family f103 f407 g474) # Каждый процесс компилирует настоящую реализацию bxCAN/FDCAN одного семейства. + add_executable(test_stm32${family} tests/test_stm32_ports.c ports/stm32${family}/pcan_boot_stm32${family}.c) # Подключает общий сценарий и семейный production-порт. + target_link_libraries(test_stm32${family} PRIVATE protocan_boot) # Использует тот же автомат и CRC, что библиотека устройства. + target_include_directories(test_stm32${family} PRIVATE tests/stm32_stubs) # Только host-цели видят подменённые семейные заголовки HAL. + if(family STREQUAL "f103") # Один сценарий выбирает адреса и аппаратную единицу записи F103. + target_compile_definitions(test_stm32${family} PRIVATE TEST_STM32F103) # F407 использует вторую ветку того же сценария. + endif() # Завершает выбор семейного профиля теста. + if(family STREQUAL "g474") # G474 использует FDCAN, doubleword и обе физические геометрии DBANK. + target_compile_definitions(test_stm32${family} PRIVATE TEST_STM32G474) # Включает G474-модель и проверку старого shifted-DLC HAL. + endif() # Завершает выбор аппаратного профиля G474. + if(MSVC) # Assertions должны исполняться и в Release-конфигурации host-тестов. + target_compile_options(test_stm32${family} PRIVATE /UNDEBUG) # Отменяет NDEBUG, чтобы аппаратные проверки и вызовы не исчезли. + else() # GCC и Clang используют стандартную форму отмены определения макроса. + target_compile_options(test_stm32${family} PRIVATE -UNDEBUG) # Сохраняет проверки границ памяти при любой конфигурации сборки. + endif() # Завершает настройку обязательных assertions. + add_test(NAME stm32${family} COMMAND test_stm32${family}) # Регистрирует регрессию полного обновления и аппаратных отказов. + endforeach() # Завершает регистрацию трёх независимых STM32-портов. +endif() # Без host-тестов CMake по-прежнему собирает только переносимое ядро. diff --git a/c/protocan-boot/README.md b/c/protocan-boot/README.md index de52906..4e1db0e 100644 --- a/c/protocan-boot/README.md +++ b/c/protocan-boot/README.md @@ -10,15 +10,21 @@ CAN 2.0B и 29-битному ProtoCAN ID. Оно реализует сесси CRC32, проверку совместимости, продолжение по номеру следующего блока и безопасный выбор неактивного слота. -Переносимое ядро не содержит HAL, регистров Flash и linker script. -Аппаратные операции предоставляют реализации из `ports/` через callbacks; -startup, карта линковки и настройки конкретной платы остаются в проекте. +Ядро не содержит HAL или регистров Flash. Готовые аппаратные callbacks для +STM32F103C8, STM32F407VE и STM32G474VE находятся в `ports`; подключение описано ниже. +Linker script, startup, тактирование, GPIO и переход в приложение предоставляет +проект устройства. Криптография в этих single-slot портах не реализована. -Для STM32G474VET6 из `candleLight_fw` задаются `slot_count = 1` и -`max_image_size = 480 * 1024`. В этом режиме запись идёт в единственную +Для [STM32G474VET6 из CANdle_stm32](ports/stm32g474/README.md) задаются +`slot_count = 1` и `max_image_size = 480 * 1024`. В этом режиме запись идёт в единственную область приложения, callback `set_pending_slot` не требуется, а аппаратный rollback недоступен. Значение `slot_count = 0` сохраняет прежний A/B-режим. +Для [HOPE G474VET6](ports/stm32g474-hope/README.md) готовый BOOT CANdle +использует тот же main/startup/Flash-порт, но аппаратный адаптер подключает +FDCAN1 к PD0/PD1 по схеме платы. USART1 PA9/PA10 и слот приложения +0x08008000 сохраняются; исходники проекта подключаются из templates. + ## Слои ```text @@ -180,21 +186,37 @@ ctest --test-dir build --output-on-failure ## F28335 / большая EEPROM -[Порт M95M02](ports/tms320f28335/README.md) подключён в `tms_periph/periph_167`. +[Порт M95M02](ports/tms320f28335/README.md) подключён в `28335_periph`, ветка 167. Использует отдельный Flash-загрузчик и два слота EEPROM по 130560 байт. Реализованы readback/CRC, проверка SCI8, журнал метаданных, пробный запуск, CONFIRM/откат, PING/discovery и сервисный паспорт. Первичная установка Flash- загрузчика и выбор Flash boot описаны в README порта. -## Аппаратные порты +## STM32 / прошивка по ProtoCAN -| Порт | Проект платы | Хранилище | -|---|---|---| -| [STM32F103](ports/stm32f103/README.md) | KONOR_ds18b20 | Flash, 52 КиБ, один слот | -| [STM32G474VET](ports/stm32g474vet/README.md) | candleLight_fw | Flash, 480 КиБ, один слот | -| [TMS320F28335](ports/tms320f28335/README.md) | periph_167 | M95M02, 2 × 130560 байт | +| Порт | Источник профиля | Область приложения | Ёмкость | +|---|---|---|---:| +| [STM32F103C8](ports/stm32f103/README.md) | `KONOR_ds18b20/src/bootloader.c` | `0x08003000..0x08010000` | 52 КиБ | +| [STM32F407VE](ports/stm32f407/README.md) | `climate_control_f407vet6_f4/Bootloader/bootloader_f407.c` | `0x08008000..0x08040000` | 224 КиБ | +| [STM32G474VE](ports/stm32g474/README.md) | `CANdle_stm32/src/boot/g474_can_bootloader.c` | `0x08008000..0x08080000` | 480 КиБ | -Основной checkout: `newProject/templates`. Проекты используют эту реализацию; -наличие старого ядра в их вложенных копиях templates не означает отдельный порт. -STM32-порты сохраняют совместимый UART-интерфейс. Настройки платы и linker scripts -остаются в проектах; аппаратные операции загрузчика находятся в `ports`. +Верхние границы исключены. F103/F407 предоставляют готовые CMSIS `boot_main.c` +для исходных проектов и отдельные reusable HAL-порты. G474 предоставляет +reusable HAL FDCAN/Flash-порт, CAN/UART boot main, startup и вход из приложения. +Общие компоненты и правила подключения описаны в +[`ports/stm32-common`](ports/stm32-common/README.md). Это ProtoCAN Boot v1 по +CAN, с отдельной картой памяти относительно USB SET v2-загрузчиков из `set-protocol`. +Конфигурация задаётся по именам полей и принудительно использует `slot_count=1`. +Образы пишутся в логический слот A; A/B-rollback и постоянные commit-метаданные +отсутствуют. Ограничения запуска после потери питания описаны в общей инструкции. + +Проекты KONOR, climate и CANdle G474 подключены к этим исходникам через свои +submodule `templates`; в старых путях оставлены тонкие include-обёртки. +Состав сборок, разметка SRAM-запросов и результаты проверки перечислены в +[`projects/STM32.md`](projects/STM32.md). + +## Самостоятельные проекты CCS + +Готовые проекты **F28335_CAN_AB** (M95M02) и **F2812_CAN_NOR** (AM29LV800BT), +включая необходимые файлы поддержки TI, находятся в `projects/ccs`. +[Импорт, сборка, карты памяти и установка](projects/README.md). diff --git a/c/protocan-boot/include/pcan_boot.h b/c/protocan-boot/include/pcan_boot.h index cf9f7a9..534d42c 100644 --- a/c/protocan-boot/include/pcan_boot.h +++ b/c/protocan-boot/include/pcan_boot.h @@ -164,6 +164,9 @@ bool pcan_boot_process(pcan_boot_t *boot, uint32_t can_id, /** Call regularly with a wrapping monotonic millisecond clock. */ void pcan_boot_poll(pcan_boot_t *boot, uint32_t now_ms); +uint32_t pcan_boot_crc32_update(uint32_t crc, const pcan_boot_byte_t *data, size_t length); /* Общий потоковый CRC32 для readback аппаратных хранилищ; начальное состояние равно нулю. */ +bool pcan_boot_report_busy(pcan_boot_t *boot, pcan_boot_byte_t command, uint32_t now_ms); /* Долгие аппаратные операции сообщают BUSY тем же codec и той же session, что обычный ответ. */ + /** Переносимые операции с 29-битным ProtoCAN ID. */ uint32_t pcan_boot_make_id(pcan_boot_byte_t priority, pcan_boot_byte_t route, pcan_boot_byte_t device_type, pcan_boot_byte_t device_id, diff --git a/c/protocan-boot/ports/README.md b/c/protocan-boot/ports/README.md index bef3599..bb6244f 100644 --- a/c/protocan-boot/ports/README.md +++ b/c/protocan-boot/ports/README.md @@ -5,22 +5,29 @@ | Каталог | МК | Проект | Слоты | |---|---|---|---| -| [stm32f103](stm32f103/README.md) | STM32F103C8T6 | KONOR_ds18b20 | Один, Flash, 52 КиБ | -| [stm32g474vet](stm32g474vet/README.md) | STM32G474VET6 | candleLight_fw | Один, Flash, 480 КиБ | -| [tms320f28335](tms320f28335/README.md) | TMS320F28335 | periph_167 | A/B, M95M02, по 130560 байт | +| [stm32f103](stm32f103/README.md) | STM32F103C8T6 | KONOR_ds18b20, native и HAL | Один, Flash, 52 КиБ | +| [stm32f407](stm32f407/README.md) | STM32F407VET6 | climate_control_f407vet6_f4 | Один, Flash, 224 КиБ | +| [stm32g474](stm32g474/README.md) | STM32G474VET6 | CANdle_stm32 | Один, Flash, 480 КиБ | +| [stm32g474-hope](stm32g474-hope/README.md) | STM32G474VET6 | HOPE, FDCAN1 PD0/PD1 | Один, Flash, 480 КиБ | +| [tms320f2812](tms320f2812/README.md) | TMS320F2812 | projects/ccs/f2812 | NOR AM29LV800BT | +| [tms320f28335](tms320f28335/README.md) | TMS320F28335 | projects/ccs/f28335, 28335_periph | A/B, M95M02, по 130560 байт | + +Совместимость с переносом от 11.10.2026 сохранена: `stm32f103/pcan_boot_f103.c` +с интерфейсом `PcanBootF103_Run()` и [stm32g474vet](stm32g474vet/README.md) +с интерфейсом `PcanBootG474_Run()`. Эти реализации подключаются вместо нового +native/HAL-порта, каждая со своим конфигурационным заголовком. В STM32-проектах остаются `main`, startup, linker script и конфигурационный заголовок платы. Порт компилируется отдельным исходным файлом. STM32-порты сохраняют совместимый UART-интерфейс исходных загрузчиков. -В F28335 проектные `can_boot.c` и `boot_shared.c` подключают общие исходники -в одну единицу компиляции для совместимости со старой системой сборки. -Нельзя одновременно добавлять эти исходники отдельными файлами в тот же target. -Проектные Quiesce, startup и linker script остаются локальными. +В F28335 приложение подключает `f28335_can_application.c` как linked resource; +локальный `can_boot.c` предоставляет `F28335Boot_Quiesce`. Постоянный загрузчик +собирается отдельно. Адрес задаётся номером PERIPH 0–31; общий 3/7 отменён. +Подробности интеграции приведены в README порта и `../projects/README.md`. -Все три проекта подключены к основному `newProject/templates`. Для F103 пути -IDE больше не зависят от junction `lib/c`. Для G474 CMake допускает иной checkout -через `PROTOCAN_BOOT_ROOT`; Keil использует соседний каталог `templates`. +Текущие подключения STM32 описаны в `../projects/STM32.md`, общие правила HAL — +в [stm32-common](stm32-common/README.md). ## Проверка переноса 11.10.2026 diff --git a/c/protocan-boot/ports/stm32-common/README.md b/c/protocan-boot/ports/stm32-common/README.md new file mode 100644 index 0000000..8c30bdf --- /dev/null +++ b/c/protocan-boot/ports/stm32-common/README.md @@ -0,0 +1,109 @@ +# STM32: общий слой ProtoCAN Boot v1 + +Порты [F103C8](../stm32f103/README.md), [F407VE](../stm32f407/README.md) и +[G474VE](../stm32g474/README.md) подключают bxCAN/FDCAN и Flash к текущему `pcan_boot`. +F103/F407 предоставляют как лёгкий CMSIS boot main для существующих проектов, +так и независимый HAL-порт. G474 использует HAL FDCAN/Flash. +`pcan_boot_stm32.inc` включается семейным `.c`; отдельно его компилировать не надо. +Сохраните рядом каталоги `stm32-common` и нужного семейства. + +Reusable `pcan_boot_stm32*.c` не содержит `main` или startup. Готовые `boot_main.c` +и вход из приложения находятся в семейных каталогах. Для F103/F407 общая +CMSIS-реализация транспорта, callbacks и безопасного handoff — `boot_native.inc`; +G474 также содержит `boot_startup.c` для исходных Keil/GCC-сборок. +Тактирование платы, linker и привязка USB/CAN-приложения остаются в проектах. + +KONOR, climate и CANdle G474 уже подключены через свои submodule: локальные +boot main/control заменены include-обёртками, состав Keil/CMake обновлён. +UART использует общий `rs485-boot` с сохранением SETGUI v1 wire-протокола. +[Схема подключённых проектов и проверки сборок](../../projects/STM32.md). + +## Подключение reusable HAL-портов F103/F407 + +1. Добавьте в сборку `src/pcan_boot.c` и семейный `pcan_boot_stm32f103.c` + либо `pcan_boot_stm32f407.c`; в include paths — `include`, каталог порта, + CMSIS, HAL и каталог вашего `stm32f1xx_hal_conf.h` / `stm32f4xx_hal_conf.h`. +2. В HAL включите CAN, FLASH, RCC, GPIO и CORTEX. Выполните `HAL_Init`, настройте + тактирование, SysTick и GPIO, вызовите `HAL_CAN_Init` для CAN1. Настройка скорости + шины принадлежит проекту; исходные устройства используют 500 кбит/с. +3. Выделите CAN1, FIFO0 и банки фильтров 0/1 загрузчику. Перед вызовом init CAN + должен находиться в состоянии READY, без чужих активных фильтров. Init настраивает + адресный фильтр и broadcast discovery, затем вызывает `HAL_CAN_Start`. + Оба приоритета ProtoCAN разрешены, standard и remote кадры отвергаются. +4. Не включайте CAN TX/RX IRQ для этого handle и не отправляйте через него кадры + из других контекстов: порт использует опрос и сам читает TXOK до reset. +5. Вызывайте семейный `poll` из основного цикла только после успешного init. + Стирание Flash выполняется синхронно; вызов из IRQ не допускается. +6. Linker приложения, VTOR и переход после reset должны соответствовать карте + выбранного профиля. Изменение адресов требует отдельного согласования + геометрии стирания, linker и host-клиента. + +Пример для F103; `hcan` уже инициализирован проектом: + +```c +#include "pcan_boot_stm32f103.h" /* Подключает HAL-порт и текущий API общего автомата. */ +static pcan_boot_stm32_t updater; /* Сохраняет состояние между итерациями главного цикла. */ +static bool start_updater(CAN_HandleTypeDef *hcan) /* Вызывается после настройки CAN1, clock tree, GPIO и SysTick. */ +{ /* Настройка идентичности прибора не зависит от аппаратной геометрии Flash. */ + pcan_boot_config_t config = {0}; /* Не зависит от порядка полей расширяемого API. */ + config.device_type = 7U; /* Пример: тип 7 должен совпадать с выбранным адресом в клиенте прошивки. */ + config.device_id = 13U; /* Пример: номер 13 повторяет исходный адрес загрузчика KONOR. */ + config.ack_window = 16U; /* Подтверждает каждые 16 CAN-блоков по восемь байт. */ + config.session_timeout_ms = 30000U; /* Пример: 30 секунд без активности прерывают RAM-сессию. */ + return pcan_boot_stm32f103_init(&updater, hcan, &config); /* Настраивает single-slot геометрию, фильтры 0/1 и запускает CAN. */ +} /* После успеха основной цикл регулярно вызывает pcan_boot_stm32f103_poll(&updater). */ +``` + +Product/HW/FW в примере равны нулю; для изделия задайте их явно и согласуйте +с manifest клиента. Порт сохраняет `ack_window` и `session_timeout_ms`, но сам +задаёт `active_slot=0`, `slot_count=1`, `max_image_size` по физическому профилю. +Конфигурацию `config` можно создавать на стеке; состояние `updater` и `hcan` +должно существовать всё время работы загрузчика. + +## Flash, подтверждения и reset + +- Запись последовательная, блоки по восемь байт; неполная аппаратная единица + допустима только в конце образа и дополняется `FF`. CRC учитывает полезную длину. +- HAL-ошибки и readback каждого слова проверяются; после erase/program Flash + снова блокируется, включая обработанные отказы. На F407 перед readback + вызывается `FLASH_FlushCaches`, чтобы соседние записанные слова не читались + из устаревшей строки Flash-кэша; состояние включения кэшей сохраняется HAL. +- VERIFY перечитывает Flash, сравнивает её CRC и проверяет MSP/Thumb reset vector. + Точка входа должна принадлежать фактическому образу, MSP — основной SRAM, + с выравниванием восемь байт. CCM F407 в данном профиле для стека не используется. +- COMMIT повторно проверяет образ и устанавливает признак в RAM. + REBOOT разрешён только в состоянии COMMITTED. Ответ перед reset должен + завершиться с TXOK; отсутствие mailbox, ошибка шины или тайм-аут 100 мс + не вызывают reset. Для этого HAL tick должен работать при ожидании TX. +- BUSY перед стиранием, между секторами F407 и после erase сохраняет активность + сессии. На однобанковой Flash код не исполняется во время аппаратного стирания; + непрерывные ответы в этот интервал не гарантируются. Настройте тайм-аут клиента + больше максимального времени стирания одной аппаратной операции. + +## Запуск приложения и потеря питания + +Порт не меняет Option Bytes, защиту секторов и VDD; F407 требует 2,7..3,6 В +для программирования x32. Переход из работающего приложения в загрузчик, +backup/SRAM-флаг запроса, отключение периферии и безопасная замена MSP +остаются в `main` и startup устройства. + +`*_vectors_valid()` проверяет только векторы и диапазоны. После внешнего reset +этого недостаточно для доказательства целостности образа: RAM-признак COMMIT +потерян, а частично записанное приложение уже может иметь корректные векторы. +Эти профили сохраняют исходную single-slot модель без постоянных метаданных, +rollback, resume после питания и аутентификации. Для защищённого запуска +проекту нужен отдельный постоянный manifest с полной проверкой образа. + +## Проверка + +`python tests/run_tests.py` из корня `protocan-boot` запускает три production-порта +с моделью HAL и Flash, наряду с существующими проверками ядра и TI-портов. +Можно также использовать обычные CMake/CTest: цели `test_stm32f103`, +`test_stm32f407`, `test_stm32g474` работают на Windows и POSIX. + +Проверяются все хвосты CAN-блока, полный ERASE/DATA/VERIFY/COMMIT/REBOOT, +повреждение readback, отказы HAL/TX, фильтрация RX и сохранность памяти +перед приложением и за верхней границей; для G474 проверяются оба DBANK-режима, +переход между банками, запрет swap, ёмкость Flash и старое shifted-DLC HAL. +Эти тесты не заменяют проверку +на реальной плате с её linker, питанием, трансивером и SysTick. diff --git a/c/protocan-boot/ports/stm32-common/boot_native.inc b/c/protocan-boot/ports/stm32-common/boot_native.inc new file mode 100644 index 0000000..ab01725 --- /dev/null +++ b/c/protocan-boot/ports/stm32-common/boot_native.inc @@ -0,0 +1,127 @@ +static __attribute__((naked, noreturn)) void native_enter(uint32_t sp __attribute__((unused)), uint32_t pc __attribute__((unused))) /* Меняет стек без последующего обращения C-кода к старому кадру функции. */ +{ /* AAPCS передаёт новый MSP в r0, Thumb entry в r1; последовательность совместима с GCC и Arm Compiler 6. */ + __asm volatile("msr msp, r0\n" "movs r2, #0\n" "msr control, r2\n" "dsb\n" "isb\n" "cpsie i\n" "bx r1\n"); /* Возвращает привилегированный режим MSP, синхронизирует конвейер и передаёт управление Thumb-вектору. */ +} /* Завершает переход без эпилога C после замены MSP. */ +void SysTick_Handler(void) { ++ticks_ms; } /* Сохраняет миллисекундные часы только в самостоятельной сборке загрузчика. */ +static bool native_vectors_valid(uint32_t size) /* Проверяет начальный стек и reset handler в пределах фактического образа. */ +{ /* До чтения Flash отвергает некорректный размер. */ + const uint32_t *vectors = (const uint32_t *)(uintptr_t)NATIVE_APP_BASE; /* Таблица векторов лежит в начале зарезервированной области приложения. */ + uint32_t sp, pc; /* Хранит начальные значения Cortex-M без невыровненного доступа. */ + if (size < 8U || size > NATIVE_APP_SIZE) return false; /* Для двух векторов нужно минимум восемь байт; верхняя граница профиля исключена. */ + sp = vectors[0]; pc = vectors[1]; /* Читает MSP и Thumb-точку входа только после проверки геометрии. */ + return sp > 0x20000000UL && sp <= NATIVE_RAM_END && (sp & 7U) == 0U && (pc & 1U) != 0U && (pc & ~1UL) >= NATIVE_APP_BASE && (pc & ~1UL) < NATIVE_APP_BASE + size; /* Требует восемь байт выравнивания стека и точку входа внутри выбранной длины приложения. */ +} /* Структурная проверка не заменяет постоянный manifest после отключения питания. */ +static void native_jump(uint32_t address) /* Отключает загрузочную периферию перед запуском приложения либо ROM. */ +{ /* Вызывающий код предварительно проверяет векторы либо использует фиксированный заводской ROM. */ + uint32_t index; /* Перебирает все банки NVIC Cortex-M3/M4 с запасом до восьми банков. */ + const uint32_t *vectors = (const uint32_t *)(uintptr_t)address; /* Сохраняет адрес новой таблицы до отключения прерываний. */ + uint32_t sp = vectors[0], pc = vectors[1]; /* Считывает аргументы перехода, пока C-стек ещё принадлежит загрузчику. */ + __disable_irq(); SysTick->CTRL = 0U; /* Не позволяет SysTick загрузчика вызвать обработчик нового приложения в промежуточном состоянии. */ + native_peripheral_stop(); /* Семейный порт отключает CAN и используемый UART, не трогая резервную память. */ + for (index = 0U; index < 8U; ++index) { NVIC->ICER[index] = 0xFFFFFFFFUL; NVIC->ICPR[index] = 0xFFFFFFFFUL; } /* Сбрасывает enable/pending всех внешних IRQ записью W1C по CMSIS. */ + SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk | SCB_ICSR_PENDSVCLR_Msk; /* Убирает отложенные SysTick и PendSV до смены VTOR. */ + SCB->VTOR = address; /* Согласует векторизацию с linker нового образа. */ + native_enter(sp, pc); /* Передаёт управление без возврата и без обращения к старому C-стеку. */ +} /* Завершает общую процедуру handoff. */ +static bool native_image_valid(uint32_t size, uint32_t crc) /* Проверяет реальную Flash независимо от CRC принятого CAN/UART-потока. */ +{ /* Одно правило проверки используется обоими транспортами KONOR. */ + return native_vectors_valid(size) && pcan_boot_crc32_update(0U, (const uint8_t *)(uintptr_t)NATIVE_APP_BASE, size) == crc; /* Проверяет точную полезную длину, исключая заполнение FF последней аппаратной единицы. */ +} /* Завершает проверку векторов и readback CRC. */ +static bool native_write_bytes(uint32_t image_size, uint32_t offset, const uint8_t *data, uint16_t length) /* Записывает CAN-блок или UART-часть с одной проверкой физической геометрии. */ +{ /* Неполная аппаратная единица разрешена только в самом конце образа. */ + uint32_t done = 0U; bool ok = true; /* Считает полезные байты и сохраняет результат до восстановления блокировки Flash. */ + if (image_size < 8U || image_size > NATIVE_APP_SIZE || data == NULL || length == 0U || offset > image_size || length > image_size - offset || offset % NATIVE_PROGRAM_UNIT != 0U) return false; /* Проверяет диапазоны вычитанием, исключая переполнение и неправильное выравнивание. */ + if (length % NATIVE_PROGRAM_UNIT != 0U && offset + length != image_size) return false; /* Не допускает повторного программирования уже дополненного слова в середине потока. */ + if (!native_unlock()) return false; /* Не изменяет заблокированную или занятую Flash. */ + while (done < length) { /* Делит полезные октеты на аппаратные полуслова F1 или слова F4. */ + uint32_t word = 0xFFFFFFFFUL, count = length - done; /* По умолчанию хвост аппаратной записи остаётся стёртым FF. */ + if (count > NATIVE_PROGRAM_UNIT) count = NATIVE_PROGRAM_UNIT; /* Не копирует больше одной аппаратной единицы за итерацию. */ + (void)memcpy(&word, data + done, count); /* Не читает за фактическим хвостом последнего блока. */ + if (!native_program(NATIVE_APP_BASE + offset + done, word)) { ok = false; break; } /* Проверяет аппаратные флаги и фактический readback каждого записанного слова. */ + done += count; /* Продвигается только на число полезных байтов без дополнения. */ + } /* Завершает программирование текущей части образа. */ + native_lock(); /* Восстанавливает защиту Flash как после успеха, так и после обработанной ошибки. */ + return ok; /* Передаёт отказ общему CAN либо UART-автомату. */ +} /* Завершает общую безопасную запись Flash. */ +static bool native_send(void *user, uint32_t id, const pcan_boot_byte_t *data, pcan_boot_byte_t length) /* Передаёт служебный CAN-ответ с ожиданием реального TXOK до reset. */ +{ /* Использует только mailbox 0 выделенного загрузочного CAN1. */ + uint32_t start = ticks_ms, low = 0U, high = 0U; uint8_t index; bool sent; /* Сохраняет начало 100-мс тайм-аута и регистровые слова payload. */ + (void)user; /* Самостоятельный загрузчик содержит один статический экземпляр CAN. */ + if (length > 8U || id > 0x1FFFFFFFUL || (length != 0U && data == NULL)) return false; /* Не допускает чтение за DLC или передачу идентификатора шире 29 бит. */ + while ((CAN1->TSR & CAN_TSR_TME0) == 0U) if ((uint32_t)(ticks_ms - start) >= 100U) return false; /* Ограничивает ожидание свободного mailbox 100 миллисекундами с учётом переполнения часов. */ + for (index = 0U; index < length; ++index) { if (index < 4U) low |= (uint32_t)data[index] << (index * 8U); else high |= (uint32_t)data[index] << ((index - 4U) * 8U); } /* Читает только фактические октеты DLC, оставляя остальные позиции нулевыми. */ + CAN1->TSR = CAN_TSR_RQCP0; /* Сбрасывает прежние TXOK/ошибки mailbox 0 записью W1C. */ + CAN1->sTxMailBox[0].TDTR = length; CAN1->sTxMailBox[0].TDLR = low; CAN1->sTxMailBox[0].TDHR = high; /* Загружает длину и два безопасно сформированных слова данных. */ + CAN1->sTxMailBox[0].TIR = (id << 3U) | CAN_TI0R_IDE | CAN_TI0R_TXRQ; /* Запускает расширенный data-кадр ProtoCAN без remote-флага. */ + while ((CAN1->TSR & CAN_TSR_RQCP0) == 0U) if ((uint32_t)(ticks_ms - start) >= 100U) { CAN1->TSR = CAN_TSR_ABRQ0; return false; } /* Прерывает неподтверждённую передачу и запрещает reset после тайм-аута. */ + sent = (CAN1->TSR & CAN_TSR_TXOK0) != 0U; CAN1->TSR = CAN_TSR_RQCP0; /* Проверяет ACK шины до очистки аппаратного результата. */ + return sent; /* Ядро перезапустит MCU только после успешно отправленного ответа. */ +} /* Завершает синхронную передачу ответа CAN. */ +static bool native_erase_slot(void *user, pcan_boot_byte_t slot) /* Подключает проверенное стирание профиля к текущему ProtoCAN API. */ +{ /* Аппаратная реализация семейства никогда не затрагивает загрузчик или EEPROM-кольцо. */ + bool ok; (void)user; /* Хранит результат до финального обновления времени сессии. */ + if (slot != 0U || boot.manifest.image_size < 8U || boot.manifest.image_size > NATIVE_APP_SIZE) return false; /* Разрешает только логический слот A и полный набор векторов. */ + (void)pcan_boot_report_busy(&boot, PCAN_BOOT_CMD_ERASE, ticks_ms); /* Предупреждает клиента перед синхронным Flash stall. */ + ok = native_erase(boot.manifest.image_size); /* Стирает только реально необходимые страницы или секторы. */ + if (ok) (void)pcan_boot_report_busy(&boot, PCAN_BOOT_CMD_ERASE, ticks_ms); /* Продлевает сессию после завершения длительной аппаратной операции. */ + return ok; /* Сообщает результат стирания общему автомату. */ +} /* Завершает callback стирания CAN. */ +static bool native_write_slot(void *user, pcan_boot_byte_t slot, uint32_t offset, const pcan_boot_byte_t *data, pcan_boot_byte_t length) /* Подключает единый Flash writer к последовательным блокам CAN. */ +{ /* Последовательность номеров блоков и максимум DLC уже проверены общим автоматом. */ + (void)user; /* Единственный образ управляется статическим экземпляром загрузчика. */ + return slot == 0U && offset == boot.bytes_received && native_write_bytes(boot.manifest.image_size, offset, data, length); /* Не допускает произвольное смещение даже при прямом вызове callback. */ +} /* Завершает callback записи CAN. */ +static pcan_boot_status_t native_verify(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *manifest) /* Различает повреждение реальной Flash и неверную таблицу векторов. */ +{ /* Операция не доверяет одному CRC входящего потока. */ + (void)user; /* Использует фиксированную область выбранного семейного профиля. */ + if (slot != 0U || manifest == NULL || !native_vectors_valid(manifest->image_size)) return PCAN_BOOT_STATUS_INVALID_SIZE; /* Отвергает неверный слот, геометрию и точку входа до чтения всего образа. */ + return native_image_valid(manifest->image_size, manifest->image_crc32) ? PCAN_BOOT_STATUS_OK : PCAN_BOOT_STATUS_CRC_ERROR; /* Перечитывает Flash общим CRC32 ProtoCAN. */ +} /* Завершает независимую проверку принятого образа. */ +static bool native_commit(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *manifest) { return native_verify(user, slot, manifest) == PCAN_BOOT_STATUS_OK; } /* COMMIT повторно проверяет single-slot образ без имитации постоянных метаданных. */ +static bool native_can_reboot(void *user) { (void)user; return boot.state == PCAN_BOOT_STATE_COMMITTED; } /* Протокольный reset разрешён только после VERIFY и COMMIT. */ +static void native_reboot(void *user) { (void)user; NVIC_SystemReset(); } /* Вызывается ядром только после успешного TXOK ответа REBOOT. */ +static bool native_init(void) /* Инициализирует текущий API ядра без позиционных структур старой версии. */ +{ /* Идентичность устройства задаёт профиль либо конфигурация проекта. */ + pcan_boot_config_t config = {0}; pcan_boot_port_t callbacks = {0}; /* Обнуляет необязательные поля и callbacks расширяемого интерфейса. */ + config.device_type = PCAN_BOOT_DEVICE_TYPE; config.device_id = PCAN_BOOT_DEVICE_ID; config.product_type = PCAN_BOOT_PRODUCT_TYPE; /* Сохраняет адрес и Product исходного проекта. */ + config.hardware_revision = PCAN_BOOT_HW_REVISION; config.firmware_version = PCAN_BOOT_FW_VERSION; /* Сохраняет совместимость manifest по HW/FW. */ + config.active_slot = 0U; config.slot_count = 1U; config.max_image_size = NATIVE_APP_SIZE; /* Явно использует single-slot A вместо прежней фиктивной A/B-конфигурации. */ + config.ack_window = PCAN_BOOT_ACK_WINDOW; config.session_timeout_ms = 30000UL; /* Сохраняет исходное окно ACK и прерывает неактивную RAM-сессию через 30 секунд. */ + callbacks.send = native_send; callbacks.erase_slot = native_erase_slot; callbacks.write_slot = native_write_slot; /* Подключает аппаратный транспорт и защищённую область Flash. */ + callbacks.verify_status = native_verify; callbacks.set_pending_slot = native_commit; callbacks.can_reboot = native_can_reboot; callbacks.reboot = native_reboot; /* Подключает readback, COMMIT и согласованную политику reset. */ + return pcan_boot_init(&boot, &config, &callbacks, NULL); /* Проверяет конфигурацию и создаёт единственный экземпляр общего автомата. */ +} /* Завершает настройку ProtoCAN независимо от включения аппаратной шины. */ +static bool native_can_init(void) /* Настраивает выделенный CAN1 и два фильтра для адресных запросов и discovery. */ +{ /* Тактирование GPIO и CAN включает семейная функция; UART во время Flash/CAN init не изменяется. */ + static const uint8_t shifts[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U}; /* RCC кодирует APB1: значения 0..3 без деления, 4..7 дают делители 2,4,8,16. */ + uint32_t clock = SystemCoreClock >> shifts[(RCC->CFGR >> NATIVE_PPRE1_SHIFT) & 7U]; /* Получает действительную частоту APB1 в Гц, без удвоения timer clocks. */ + uint32_t tq, btr = 0U, started, index; bool found = false; /* Сохраняет bit timing, тайм-аут init и индекс фильтра. */ + if (clock % PCAN_BOOT_CAN_BITRATE != 0U) return false; /* Не округляет скорость шины при неподходящем clock tree. */ + for (tq = 18U; tq >= 8U; --tq) { /* Сохраняет диапазон 8..18 time quanta из исходного KONOR. */ + uint32_t divisor = clock / PCAN_BOOT_CAN_BITRATE, prescaler = divisor / tq, ts2 = tq / 5U; /* Выбирает sample point около 80% при допустимом целочисленном делителе. */ + if (divisor % tq == 0U && prescaler >= 1U && prescaler <= 1024U) { btr = ((ts2 - 1U) << 20U) | ((tq - 2U - ts2) << 16U) | (prescaler - 1U); found = true; break; } /* Кодирует BRP/TS1/TS2 с аппаратным смещением минус один и SJW=1 tq. */ + } /* Завершает поиск точной скорости для штатного тактирования F103/F407. */ + if (!found) return false; /* Не включает шину с неизвестными битовыми интервалами. */ + native_gpio_init(); CAN1->MCR = CAN_MCR_INRQ | CAN_MCR_ABOM; started = ticks_ms; /* Включает семейные GPIO и запрашивает init с автоматическим восстановлением bus-off. */ + while ((CAN1->MSR & CAN_MSR_INAK) == 0U) if ((uint32_t)(ticks_ms - started) >= 100U) return false; /* Ограничивает вход в CAN init ста миллисекундами. */ + CAN1->BTR = btr; CAN1->FMR |= CAN_FMR_FINIT; CAN1->FA1R = 0U; CAN1->FS1R |= 3U; CAN1->FM1R &= ~3UL; CAN1->FFA1R &= ~3UL; /* Настраивает только два 32-битных mask-фильтра в FIFO0 и отключает чужие банки загрузчика. */ + for (index = 0U; index < 2U; ++index) { /* Банк 0 принимает собственный адрес, банк 1 — только broadcast discovery. */ + uint32_t id = index == 0U ? pcan_boot_make_id(0U, 0U, PCAN_BOOT_DEVICE_TYPE, PCAN_BOOT_DEVICE_ID, 0U, 0U) : pcan_boot_make_id(0U, 0U, 7U, 15U, PCAN_BOOT_MSG_DISCOVERY, 0U); /* Не маскирует приоритет, сохраняя оба штатных уровня ProtoCAN. */ + uint32_t mask = index == 0U ? 0x0FF00000UL : 0x0FFFFFFFUL; /* Адресный фильтр оставляет MsgType/Body открытыми; discovery сравнивает их точно. */ + CAN1->sFilterRegister[index].FR1 = (id << 3U) | CAN_RI0R_IDE; CAN1->sFilterRegister[index].FR2 = (mask << 3U) | CAN_RI0R_IDE | CAN_RI0R_RTR; /* Исключает standard и remote кадры на аппаратном уровне. */ + } /* Завершает настройку обоих фильтров. */ + CAN1->FA1R |= 3U; CAN1->FMR &= ~CAN_FMR_FINIT; CAN1->MCR &= ~CAN_MCR_INRQ; started = ticks_ms; /* Активирует фильтры и переводит CAN в рабочий режим. */ + while ((CAN1->MSR & CAN_MSR_INAK) != 0U) if ((uint32_t)(ticks_ms - started) >= 100U) return false; /* Отсутствие доступной шины не должно навсегда блокировать обычный запуск приложения. */ + return true; /* Рабочий CAN готов принимать адресные команды и discovery. */ +} /* Завершает общую аппаратную настройку bxCAN. */ +static void native_can_poll(void) /* Обрабатывает не больше трёх кадров — аппаратной глубины FIFO bxCAN. */ +{ /* Длительные операции Flash выполняются только из основного цикла. */ + uint32_t count; pcan_boot_poll(&boot, ticks_ms); /* Обновляет тайм-аут сессии и отложенное discovery независимо от входящих команд. */ + for (count = 0U; count < 3U && (CAN1->RF0R & CAN_RF0R_FMP0) != 0U; ++count) { /* Ограничивает время одного вызова на нагруженной шине. */ + uint32_t rir = CAN1->sFIFOMailBox[0].RIR, low = CAN1->sFIFOMailBox[0].RDLR, high = CAN1->sFIFOMailBox[0].RDHR; /* Сохраняет поля до освобождения аппаратного FIFO. */ + uint8_t dlc = (uint8_t)(CAN1->sFIFOMailBox[0].RDTR & 15U), data[8], index; /* Читает входящий DLC отдельно от фиксированного буфера classic CAN. */ + for (index = 0U; index < 8U; ++index) data[index] = (uint8_t)(index < 4U ? low >> (index * 8U) : high >> ((index - 4U) * 8U)); /* Извлекает октеты без невыровненного чтения аппаратных регистров. */ + CAN1->RF0R |= CAN_RF0R_RFOM0; /* Освобождает обработанный элемент FIFO0 до потенциально долгого erase. */ + if ((rir & CAN_RI0R_IDE) != 0U && (rir & CAN_RI0R_RTR) == 0U && dlc <= 8U) { pcan_boot_poll(&boot, ticks_ms); (void)pcan_boot_process(&boot, (rir >> 3U) & 0x1FFFFFFFUL, data, dlc); } /* Повторно проверяет формат внешнего кадра и вызывает общий автомат. */ + } /* Завершает ограниченный пакет входящих кадров. */ +} /* Завершает обслуживание транспорта и часов ядра. */ diff --git a/c/protocan-boot/ports/stm32-common/pcan_boot_stm32.h b/c/protocan-boot/ports/stm32-common/pcan_boot_stm32.h new file mode 100644 index 0000000..095c3db --- /dev/null +++ b/c/protocan-boot/ports/stm32-common/pcan_boot_stm32.h @@ -0,0 +1,10 @@ +#ifndef PCAN_BOOT_STM32_H /* Защищает общие объявления двух STM32-портов от повторного включения. */ +#define PCAN_BOOT_STM32_H /* Фиксирует включение интерфейса single-slot загрузчика. */ +#include "../../include/pcan_boot.h" /* Использует актуальные именованные поля конфигурации и callbacks ядра. */ +typedef struct { /* Состояние принадлежит одному загрузчику и одному выделенному bxCAN. */ + pcan_boot_t boot; /* Хранит сессию, manifest, CRC потока и состояние общего автомата. */ + void *can; /* Ссылается на CAN_HandleTypeDef bxCAN либо FDCAN_HandleTypeDef G474; время жизни задаёт проект. */ + uint32_t written; /* Следующее допустимое смещение записи, в байтах от начала приложения. */ + bool ready; /* Разрешает reset только после проверки Flash и успешного COMMIT текущего образа. */ +} pcan_boot_stm32_t; /* Не содержит startup, main или обработчиков прерываний проекта. */ +#endif /* Завершает общий интерфейс STM32F103/F407. */ diff --git a/c/protocan-boot/ports/stm32-common/pcan_boot_stm32.inc b/c/protocan-boot/ports/stm32-common/pcan_boot_stm32.inc new file mode 100644 index 0000000..66e3859 --- /dev/null +++ b/c/protocan-boot/ports/stm32-common/pcan_boot_stm32.inc @@ -0,0 +1,167 @@ +static bool send_frame(void *user, uint32_t id, const pcan_boot_byte_t *data, pcan_boot_byte_t dlc) /* Передаёт только объявленные октеты и дожидается физического завершения ACK. */ +{ /* Порт владеет CAN1 без TX IRQ, поэтому флаги завершения не очищаются чужим обработчиком. */ + pcan_boot_stm32_t *port = user; /* Получает состояние выделенного аппаратного порта. */ + CAN_HandleTypeDef *can = port->can; /* Восстанавливает тип handle семейства HAL текущей единицы трансляции. */ + CAN_TxHeaderTypeDef header = {0}; /* Не оставляет мусора в стандартном ID и timestamp-флагах. */ + uint8_t bytes[8] = {0}; /* CAN 2.0 передаёт не больше восьми октетов; короткий payload дополняется безопасными нулями. */ + uint32_t mailbox, mask, started = HAL_GetTick(); /* Запоминает mailbox, его TXOK-флаг и начало тайм-аута в мс. */ + if (dlc > 8U || id > 0x1FFFFFFFUL || (dlc != 0U && data == NULL)) return false; /* Запрещает чтение за payload и идентификатор шире 29 бит. */ + if (dlc != 0U) (void)memcpy(bytes, data, dlc); /* Не читает отсутствующие байты коротких служебных сообщений. */ + while (HAL_CAN_GetTxMailboxesFreeLevel(can) == 0U) { /* Ожидает освобождения аппаратного передатчика. */ + if ((uint32_t)(HAL_GetTick() - started) >= 100U) return false; /* Ограничивает ожидание 100 мс, включая переполнение счётчика времени. */ + } /* Завершает ожидание свободного mailbox. */ + header.ExtId = id; /* Передаёт адресный ProtoCAN ID без преобразования полей. */ + header.IDE = CAN_ID_EXT; /* ProtoCAN использует только расширенные 29-битные идентификаторы. */ + header.RTR = CAN_RTR_DATA; /* Все ответы загрузчика содержат обычные данные, а не remote-запрос. */ + header.DLC = dlc; /* Фиксирует фактическое число объявленных октетов кадра. */ + can->Instance->TSR = CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2; /* Очищает прежние TXOK/ошибки записью W1C перед новой отправкой; CAN принадлежит только этому порту. */ + if (HAL_CAN_AddTxMessage(can, &header, bytes, &mailbox) != HAL_OK) return false; /* Не считает не поставленный в очередь ответ отправленным. */ + while (HAL_CAN_IsTxMessagePending(can, mailbox) != 0U) { /* Сохраняет CAN до завершения ответа, включая команду REBOOT. */ + if ((uint32_t)(HAL_GetTick() - started) >= 100U) { /* Не зависает навсегда при отсутствии ACK от шины. */ + (void)HAL_CAN_AbortTxRequest(can, mailbox); /* Снимает просроченный запрос передачи перед возвратом ошибки. */ + return false; /* Ядро не выполнит reset после неподтверждённого ответа. */ + } /* Завершает обработку тайм-аута TX. */ + } /* Аппаратная передача завершилась либо была отвергнута CAN. */ + mask = mailbox == CAN_TX_MAILBOX0 ? CAN_TSR_TXOK0 : mailbox == CAN_TX_MAILBOX1 ? CAN_TSR_TXOK1 : CAN_TSR_TXOK2; /* Сопоставляет bitmask mailbox HAL с флагом успешной передачи bxCAN. */ + return (can->Instance->TSR & mask) != 0U; /* Отличает подтверждённый ACK от снятия запроса вследствие ошибки. */ +} /* Завершает синхронный транспорт служебных ответов. */ +bool STM32_BOOT_VECTORS(void) /* Проверяет только структурную корректность таблицы векторов установленного приложения. */ +{ /* Проверка CRC образа выполняется отдельно при VERIFY. */ + const uint32_t *vectors = (const uint32_t *)(uintptr_t)STM32_BOOT_BASE; /* Читает первые два слова из фиксированной области приложения. */ + uint32_t sp = vectors[0], pc = vectors[1]; /* Извлекает начальный стек и Thumb-адрес reset handler. */ + return sp > 0x20000000UL && sp <= STM32_BOOT_RAM_END && (sp & 7U) == 0U && (pc & 1U) != 0U && (pc & ~1UL) >= STM32_BOOT_BASE && (pc & ~1UL) < STM32_BOOT_END; /* Требует доступный стек с выравниванием 8 байт и точку входа внутри приложения. */ +} /* Завершает проверку векторов без изменения MCU. */ +static bool erase_slot(void *user, pcan_boot_byte_t slot) /* Стирает единственную область после проверки manifest общим ядром. */ +{ /* Сохранение старого приложения и rollback в этом профиле отсутствуют. */ + pcan_boot_stm32_t *port = user; /* Получает manifest и состояние активации текущего загрузчика. */ + uint32_t size = port->boot.manifest.image_size; /* Ограничивает стирание фактической длиной образа в байтах. */ + bool ok, locked; /* Сохраняет результаты операции и последующего восстановления защиты Flash. */ + if (slot != 0U || size < 8U || size > STM32_BOOT_END - STM32_BOOT_BASE) return false; /* Не допускает чужой слот, неполные векторы и выход за область приложения. */ + port->ready = false; /* Инвалидирует разрешение reset до первого изменения Flash. */ + port->written = 0U; /* Начинает последовательную запись заново после стирания. */ + (void)pcan_boot_report_busy(&port->boot, PCAN_BOOT_CMD_ERASE, HAL_GetTick()); /* Предупреждает клиента перед синхронным блокированием Flash. */ + if (HAL_FLASH_Unlock() != HAL_OK) return false; /* Не продолжает работу при отказе разблокировки Flash. */ + ok = erase_region(port, size); /* Выполняет семейную операцию по страницам F1 либо секторам F4. */ + locked = HAL_FLASH_Lock() == HAL_OK; /* Восстанавливает защиту Flash и при успехе, и при отказе стирания. */ + if (ok && locked) (void)pcan_boot_report_busy(&port->boot, PCAN_BOOT_CMD_ERASE, HAL_GetTick()); /* Обновляет время после блокировки Flash, чтобы длительное стирание не погасило сессию. */ + return ok && locked; /* Не подтверждает ERASE при любом аппаратном отказе. */ +} /* Завершает callback стирания. */ +static bool write_slot(void *user, pcan_boot_byte_t slot, uint32_t offset, const pcan_boot_byte_t *data, pcan_boot_byte_t length) /* Программирует последовательные блоки без пересечения защищённых областей. */ +{ /* Крайний неполный блок дополняется единицами до аппаратной единицы программирования. */ + pcan_boot_stm32_t *port = user; /* Получает длину manifest и ожидаемое следующее смещение. */ + uint32_t done = 0U, size = port->boot.manifest.image_size; /* Считает только полезные байты без дополнения FF. */ + bool ok = true, locked; /* Позволяет гарантированно закрыть Flash после любой ошибки. */ + if (slot != 0U || data == NULL || length == 0U || length > 8U || size < 8U || size > STM32_BOOT_END - STM32_BOOT_BASE || offset != port->written || offset > size || length > size - offset || (offset % STM32_BOOT_UNIT) != 0U) return false; /* Проверяет адреса до сложения, выравнивание и принадлежность текущему образу. */ + if ((length % STM32_BOOT_UNIT) != 0U && offset + length != size) return false; /* Дополнение FF допустимо только у последнего блока; повторная запись слова запрещена. */ + if (HAL_FLASH_Unlock() != HAL_OK) return false; /* Не выполняет запись при заблокированной Flash. */ + while (done < length) { /* Разбивает CAN-блок на аппаратные полуслова F1 либо слова F4. */ + uint32_t value = 0xFFFFFFFFUL, portion = length - done; /* Стертое значение FF заполняет только хвост последней аппаратной записи. */ + uint32_t address = STM32_BOOT_BASE + offset + done; /* Адрес остаётся в заранее проверенной области приложения. */ + HAL_StatusTypeDef status; /* Отделяет аппаратное завершение записи от последующей синхронизации Flash-кэша. */ + if (portion > STM32_BOOT_UNIT) portion = STM32_BOOT_UNIT; /* Ограничивает копирование размером аппаратной записи. */ + (void)memcpy(&value, data + done, portion); /* Не читает за фактическим payload последнего блока. */ + status = HAL_FLASH_Program(STM32_BOOT_PROGRAM, address, value); /* Дожидается завершения программирования выбранной аппаратной единицы. */ + STM32_BOOT_SYNC(); /* На F407 сбрасывает строки Flash-кэша после записи, чтобы readback соседнего слова не получил старое FF. */ + if (status != HAL_OK || memcmp((const void *)(uintptr_t)address, &value, STM32_BOOT_UNIT) != 0) { /* Проверяет результат HAL и чтение записанного значения, включая хвост FF. */ + ok = false; /* Делает частично записанный образ непригодным для VERIFY/COMMIT. */ + break; /* Не продолжает программирование после первого отказа. */ + } /* Завершает проверку результата программирования. */ + done += portion; /* Продвигает полезное смещение без включения дополнения FF в CRC. */ + } /* Завершает аппаратные записи текущего CAN-блока. */ + locked = HAL_FLASH_Lock() == HAL_OK; /* Обязательно восстанавливает аппаратную блокировку Flash. */ + if (ok && locked) port->written += length; /* Подтверждает смещение только после полного успеха и блокировки. */ + return ok && locked; /* Ошибка передаётся общему автомату как FLASH_ERROR. */ +} /* Завершает callback последовательной записи. */ +static pcan_boot_status_t verify_image(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *manifest) /* Перечитывает реальную Flash вместо доверия одному CRC входящего потока. */ +{ /* Проверяет геометрию до доступа к памяти и точный размер переданных данных. */ + pcan_boot_stm32_t *port = user; /* Получает фактический счётчик успешно записанных байтов. */ + const uint8_t *image = (const uint8_t *)(uintptr_t)STM32_BOOT_BASE; /* Отображает фиксированную область приложения в адресное пространство MCU. */ + uint32_t offset, crc = 0U; /* Начинает общий потоковый CRC32 с нуля. */ + if (slot != 0U || manifest == NULL || manifest->image_size < 8U || manifest->image_size > STM32_BOOT_END - STM32_BOOT_BASE || port->written != manifest->image_size) return PCAN_BOOT_STATUS_INVALID_SIZE; /* Не читает произвольную память по недостоверному manifest. */ + for (offset = 0U; offset < manifest->image_size;) { /* Проверяет весь полезный образ ограниченными порциями. */ + uint32_t count = manifest->image_size - offset; /* Вычисляет остаток в байтах без выхода за границу образа. */ + if (count > 1024U) count = 1024U; /* Порция 1 КиБ ограничивает объём одного вызова потокового CRC. */ + crc = pcan_boot_crc32_update(crc, image + offset, count); /* Использует общий полином ProtoCAN и не включает дополнение FF. */ + offset += count; /* Продвигает позицию чтения проверенного образа. */ + } /* Завершает чтение Flash для независимой проверки CRC. */ + if (crc != manifest->image_crc32) return PCAN_BOOT_STATUS_CRC_ERROR; /* Обнаруживает повреждение памяти после успешного приёма CAN. */ + if (!STM32_BOOT_VECTORS() || ((*(const uint32_t *)(const void *)(image + 4U)) & ~1UL) >= STM32_BOOT_BASE + manifest->image_size) return PCAN_BOOT_STATUS_INVALID_SIZE; /* Не принимает reset handler вне фактически загруженного образа. */ + return PCAN_BOOT_STATUS_OK; /* Реальная Flash и векторы соответствуют полученному manifest. */ +} /* Завершает проверку записанного образа. */ +static bool commit_image(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *manifest) /* Активирует только повторно проверенный single-slot образ. */ +{ /* Не имитирует постоянные A/B-метаданные или защиту от потери питания. */ + pcan_boot_stm32_t *port = user; /* Получает RAM-признак успешного COMMIT текущей сессии. */ + port->ready = verify_image(user, slot, manifest) == PCAN_BOOT_STATUS_OK; /* Перечитывает Flash перед разрешением reset. */ + return port->ready; /* Ядро перейдёт в COMMITTED только при успешной проверке. */ +} /* Завершает активацию без записи служебных страниц. */ +static bool can_reboot(void *user) /* Запрещает программный запуск недописанного приложения по команде протокола. */ +{ /* Политика запуска после внешнего reset остаётся обязанностью проекта. */ + pcan_boot_stm32_t *port = user; /* Получает состояние текущей сессии и подтверждение COMMIT. */ + return port->ready && port->boot.state == PCAN_BOOT_STATE_COMMITTED; /* ABORT, новая сессия и ошибки сами по себе не дают права reset. */ +} /* Завершает проверку допустимости протокольного reset. */ +static void reboot(void *user) /* Выполняет reset только после синхронно отправленного ответа ядра. */ +{ /* Повторно проверяет RAM-разрешение непосредственно перед сбросом. */ + if (can_reboot(user)) NVIC_SystemReset(); /* Использует штатный CMSIS reset, оставляя startup и выбор приложения проекту. */ +} /* Завершает callback перезапуска. */ +bool STM32_BOOT_INIT(pcan_boot_stm32_t *port, CAN_HandleTypeDef *can, const pcan_boot_config_t *config) /* Подключает текущий API ядра к выделенным CAN1 и single-slot Flash. */ +{ /* Тактирование, GPIO, bitrate, HAL_Init и SysTick должны быть настроены проектом заранее. */ + pcan_boot_port_t callbacks = {0}; /* Новые необязательные callbacks ядра всегда остаются явно нулевыми. */ + pcan_boot_config_t single; /* Копирует идентичность прибора, переопределяя геометрию профиля. */ + CAN_FilterTypeDef filter = {0}; /* Подготавливает адресный фильтр 0 и discovery-фильтр 1 в FIFO0. */ + uint32_t id, mask; /* Содержит идентификатор и аппаратную маску IDE/RTR сдвига bxCAN. */ + if (port == NULL || can == NULL || config == NULL || can->Instance != CAN1) return false; /* Отклоняет неверные указатели и неподдерживаемый CAN2. */ + single = *config; /* Сохраняет DeviceType/ID, Product, HW, FW, ack_window и тайм-аут сессии проекта. */ + single.active_slot = 0U; /* Single-slot обновление всегда адресует логический слот A. */ + single.slot_count = 1U; /* Исключает старую имитацию single-slot через фиктивный active_slot=1. */ + single.max_image_size = STM32_BOOT_END - STM32_BOOT_BASE; /* Ядро отвергает превышение физической области ещё до erase. */ + callbacks.send = send_frame; /* Подключает синхронную отправку подтверждённых CAN-ответов. */ + callbacks.erase_slot = erase_slot; /* Подключает стирание только области приложения. */ + callbacks.write_slot = write_slot; /* Подключает последовательное программирование с readback каждого слова. */ + callbacks.verify_status = verify_image; /* Возвращает отдельные статусы CRC_ERROR и INVALID_SIZE для Flash/vectors. */ + callbacks.set_pending_slot = commit_image; /* Согласует COMMIT с проверкой реального образа и RAM-признаком активации. */ + callbacks.can_reboot = can_reboot; /* Не позволяет REBOOT обойти проверку завершённого образа. */ + callbacks.reboot = reboot; /* Выполняет CMSIS reset после подтверждения ответа на шине. */ + (void)memset(port, 0, sizeof(*port)); /* Очищает старые счётчики и разрешение активации до настройки сессии. */ + port->can = can; /* Сохраняет заранее инициализированный handle HAL. */ + if (!pcan_boot_init(&port->boot, &single, &callbacks, port)) { port->can = NULL; return false; } /* При ошибке адреса оставляет последующий poll безопасным. */ + id = pcan_boot_make_id(0U, PCAN_BOOT_ROUTE_FROM_PM, single.device_type, single.device_id, 0U, 0U) << 3U; /* Переводит адрес прибора в регистровый формат bxCAN. */ + mask = (0x0FF00000UL << 3U) | 6U; /* Проверяет Route/Type/ID, IDE=1 и RTR=0; приоритет, MsgType и Body остаются открытыми. */ + id |= 4U; /* Устанавливает IDE в бите 2 аппаратного фильтра bxCAN. */ + filter.FilterBank = 0U; /* Выделенный загрузчик использует первый банк фильтров. */ + filter.FilterMode = CAN_FILTERMODE_IDMASK; /* Сравнивает адрес по маске вместо списка отдельных команд. */ + filter.FilterScale = CAN_FILTERSCALE_32BIT; /* Сохраняет все 29 бит расширенного идентификатора. */ + filter.FilterIdHigh = id >> 16U; /* Передаёт HAL старшую половину регистрового идентификатора. */ + filter.FilterIdLow = id & 0xFFFFU; /* Передаёт HAL младшую половину, включая IDE/RTR. */ + filter.FilterMaskIdHigh = mask >> 16U; /* Маскирует адрес прибора и направление обмена. */ + filter.FilterMaskIdLow = mask & 0xFFFFU; /* Отвергает стандартные и remote-кадры до программного разбора. */ + filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; /* Приём выполняется опросом FIFO0 без IRQ. */ + filter.FilterActivation = ENABLE; /* Включает настроенный адресный фильтр. */ + filter.SlaveStartFilterBank = 14U; /* Стандартная граница банков CAN1/CAN2 в HAL; порт не использует CAN2. */ + if (HAL_CAN_ConfigFilter(can, &filter) != HAL_OK) { port->can = NULL; return false; } /* Не запускает загрузчик с неподтверждённой настройкой адресного фильтра. */ + id = (pcan_boot_make_id(0U, PCAN_BOOT_ROUTE_FROM_PM, 7U, 15U, PCAN_BOOT_MSG_DISCOVERY, 0U) << 3U) | 4U; /* Отдельно разрешает штатный broadcast discovery, сохраняя запрет broadcast-записи. */ + mask = (0x0FFFFFFFUL << 3U) | 6U; /* Проверяет всё кроме приоритета, включая MsgType=DISCOVERY и пустой Body. */ + filter.FilterBank = 1U; /* Второй выделенный банк обслуживает только обнаружение устройств. */ + filter.FilterIdHigh = id >> 16U; /* Записывает старшую половину broadcast discovery ID. */ + filter.FilterIdLow = id & 0xFFFFU; /* Записывает младшую половину с IDE=1 и RTR=0. */ + filter.FilterMaskIdHigh = mask >> 16U; /* Ограничивает тип и адрес broadcast запроса. */ + filter.FilterMaskIdLow = mask & 0xFFFFU; /* Ограничивает Body и формат кадра discovery. */ + if (HAL_CAN_ConfigFilter(can, &filter) != HAL_OK || HAL_CAN_Start(can) != HAL_OK) { port->can = NULL; return false; } /* Обезвреживает poll при отказе второго фильтра либо запуска CAN. */ + return true; /* Оба фильтра настроены, CAN успешно вышел из режима init. */ +} /* Завершает настройку одного аппаратного порта. */ +void STM32_BOOT_POLL(pcan_boot_stm32_t *port) /* Обслуживает загрузчик только из основного цикла, где допустимо синхронное стирание. */ +{ /* Вызов из CAN IRQ не допускается из-за длительных операций Flash. */ + CAN_HandleTypeDef *can; /* Получает аппаратный handle после проверки состояния порта. */ + uint32_t count; /* Ограничивает обработку глубиной аппаратного FIFO bxCAN. */ + if (port == NULL || port->can == NULL) return; /* Позволяет безопасно пропустить ещё не настроенный порт. */ + can = port->can; /* Восстанавливает семейный HAL-тип handle. */ + pcan_boot_poll(&port->boot, HAL_GetTick()); /* Обновляет монотонное время и тайм-аут сессии до приёма команд. */ + for (count = 0U; count < 3U && HAL_CAN_GetRxFifoFillLevel(can, CAN_RX_FIFO0) != 0U; ++count) { /* Не позволяет непрерывной нагрузке CAN захватить весь главный цикл. */ + CAN_RxHeaderTypeDef header = {0}; /* Принимает IDE/RTR/DLC независимо от аппаратной настройки фильтра. */ + uint8_t data[8]; /* Выделяет максимальный payload одного classic CAN-кадра. */ + if (HAL_CAN_GetRxMessage(can, CAN_RX_FIFO0, &header, data) != HAL_OK) break; /* Не разбирает неполученный кадр при аппаратной ошибке. */ + if (header.IDE == CAN_ID_EXT && header.RTR == CAN_RTR_DATA && header.DLC <= 8U && header.ExtId <= 0x1FFFFFFFUL) { /* Повторно проверяет внешний ввод до вызова общего decoder. */ + pcan_boot_poll(&port->boot, HAL_GetTick()); /* Учитывает время предыдущего синхронного erase перед следующей командой. */ + (void)pcan_boot_process(&port->boot, header.ExtId, data, (uint8_t)header.DLC); /* Передаёт адресные команды и восьмибайтовые блоки общему автомату. */ + } /* Завершает обработку допустимого формата кадра. */ + } /* Возвращает управление приложению после ограниченного пакета входящих кадров. */ +} /* Завершает обслуживание транспорта и таймеров. */ diff --git a/c/protocan-boot/ports/stm32f103/README.md b/c/protocan-boot/ports/stm32f103/README.md index 3c60fb4..9f71abb 100644 --- a/c/protocan-boot/ports/stm32f103/README.md +++ b/c/protocan-boot/ports/stm32f103/README.md @@ -1,15 +1,57 @@ -# ProtoCAN Boot: stm32f103 +# STM32F103C8: ProtoCAN Boot v1 -Порт вынесен из `KONOR_ds18b20` в общий `templates/c/protocan-boot`. -Скомпилировать `pcan_boot_f103.c` и `../../src/pcan_boot.c` отдельными единицами. -Добавить в include path `../../include`, каталог настроек платы и заголовки SDK МК. -Скопировать `pcan_boot_f103_config.template.h` в проект как `pcan_boot_f103_config.h`. -Вызвать `PcanBootF103_Run()` из `main`. Не компилировать старую аппаратную реализацию параллельно. +Для совместимости с переносом от 11.10.2026 сохранён `pcan_boot_f103.c`: +он компилируется вместе с `../../src/pcan_boot.c`, использует локальный +`pcan_boot_f103_config.h` по соседнему шаблону и запускается через +`PcanBootF103_Run()`. Ему нужны `proto.h/proto.c`, STM32F1 CMSIS и +`boot_control.h` из проекта платы. Подключайте его вместо описанных ниже +native/HAL-реализаций, чтобы избежать дублирования обработчиков периферии. -В проекте остаются startup, linker script, конфигурация платы и обработчик -ENTER_BOOT приложения. Перенос сохраняет UART-интерфейс и общую запись Flash. -Для F103 нужен proto.h/proto.c из проекта (совместимый UART-кодек), STM32F1 CMSIS и boot_control.h с картой памяти/backup magic. +## Подключённый KONOR без HAL -Используется один слот приложения: 52 КиБ с 0x08003000. -Откат A/B не поддерживается. CRC и векторы проверяются перед запуском. -Конфигурационный шаблон соответствует исходной плате и требует проверки при переносе. +`boot_main.c` содержит извлечённый CMSIS-загрузчик CAN/UART, `boot_request.c` — +вход из приложения через BKP DR1, `boot_profile.h` — общие адреса и magic. +`KONOR_ds18b20/src/bootloader.c`, `src/boot_control.c`, `inc/boot_control.h` +теперь включают эти файлы из `lib/c/protocan-boot/ports/stm32f103`. +Keil BOOT компилирует общие `pcan_boot.c` и `rs485_boot.c`; локальный `proto.c` +исключён только из загрузчика, приложение продолжает использовать свой parser. +UART BEGIN/DATA/END/STATUS сохраняют SETGUI v1, 512000 бод и PA9/PA10. +Номера блоков, CRC и сессии CAN обслуживает только общий ProtoCAN-автомат. +Оба транспорта используют один Flash writer; одновременная запись блокируется. + +Native вариант не нужно собирать вместе с reusable HAL `.c` ниже. + +## Reusable HAL-порт + +Аппаратный single-slot профиль извлечён из `KONOR_ds18b20/src/bootloader.c`. +Прямые операции с регистрами адаптированы к современному STM32CubeF1 HAL; +UART SETGUI parser исходного проекта в этот CAN-порт не входит. + +| Область | Начало | Конец, исключён | Размер | +|---|---|---|---:| +| Загрузчик | `0x08000000` | `0x08003000` | 12 КиБ | +| Приложение | `0x08003000` | `0x08010000` | 52 КиБ | +| SRAM для MSP | `0x20000000` | `0x20005000` | 20 КиБ | + +MSP может совпадать с верхней границей SRAM, но не с нижней; выравнивание — +восемь байт. Страница Flash — 1024 байта, единица записи — полуслово 16 бит. +Профиль предназначен для штатных 64 КиБ Flash STM32F103C8, без использования +недокументированного расширения памяти. + +Подключайте `pcan_boot_stm32f103.c`, общий `src/pcan_boot.c` и сохраните соседний +каталог `stm32-common`. STM32CubeF1 HAL должен включать CAN и Flash/FlashEx. +Для определения CMSIS обычно используется `STM32F103xB`; физический профиль +этого порта остаётся C8 с 64 КиБ. + +Проект настраивает CAN1 и GPIO: исходная плата использует PA11 RX, PA12 TX, +500 кбит/с, DeviceType=7 / DeviceID=13. Значения адреса задавайте через +`pcan_boot_config_t` и согласуйте с host-клиентом. На стороне Flash всегда +используется логический слот A. + +Вызывайте `pcan_boot_stm32f103_init` после `HAL_CAN_Init`, затем +`pcan_boot_stm32f103_poll` из основного цикла. Linker приложения и VTOR должны +указывать на `0x08003000`. В загрузчике зарезервируйте весь диапазон до этого +адреса и проверьте размер итогового образа по MAP: HAL-сборка может оказаться +крупнее исходного загрузчика с прямым доступом к регистрам. + +[Общая инструкция, пример, ограничения COMMIT и запуска после reset](../stm32-common/README.md). diff --git a/c/protocan-boot/ports/stm32f103/boot_main.c b/c/protocan-boot/ports/stm32f103/boot_main.c new file mode 100644 index 0000000..5b89b95 --- /dev/null +++ b/c/protocan-boot/ports/stm32f103/boot_main.c @@ -0,0 +1,95 @@ +#include "boot_profile.h" /* Сохраняет карту памяти, BKP-запросы и CAN-адрес исходного KONOR. */ +#include "../../include/pcan_boot.h" /* Использует единственную текущую машину состояний ProtoCAN из templates. */ +#include "../../../rs485-boot/include/rs485_boot.h" /* Повторно использует общий SETGUI v1 UART-автомат вместо локальной копии parser/CRC. */ +#include "stm32f10x.h" /* Работает с существующим CMSIS/StdPeriph проекта без добавления HAL. */ +#include /* Предоставляет безопасное копирование коротких хвостов Flash. */ +#define NATIVE_APP_BASE BOOT_APP_ADDRESS /* Выбирает начало приложения после 12 КиБ загрузчика. */ +#define NATIVE_APP_SIZE (BOOT_FLASH_END - BOOT_APP_ADDRESS) /* Ограничивает обновление 52 КиБ штатной Flash C8. */ +#define NATIVE_RAM_END 0x20005000UL /* Начальный MSP допускается до верхней границы 20 КиБ SRAM. */ +#define NATIVE_PROGRAM_UNIT 2U /* Контроллер Flash STM32F103 записывает полуслова по два байта. */ +#define NATIVE_PPRE1_SHIFT 8U /* STM32F1 размещает делитель APB1 в RCC_CFGR[10:8]. */ +static pcan_boot_t boot; static volatile uint32_t ticks_ms; /* Хранит CAN-сессию и монотонный счётчик SysTick загрузчика. */ +static rs485_boot_t uart_boot; /* Хранит UART parser, повторяемую запись блоков и статус общего SETGUI v1-автомата. */ +static bool native_wait(void) /* Ограничивает ожидание Flash и проверяет аппаратные ошибки программирования. */ +{ /* На однобанковой Flash CPU может останавливаться до завершения операции. */ + uint32_t guard = SystemCoreClock; /* Конечный бюджет проверок численно равен HCLK в Гц; это число итераций CPU, а не аппаратный тайм-аут. */ + while ((FLASH->SR & FLASH_SR_BSY) != 0U && guard != 0U) --guard; /* Не продолжает запись до освобождения контроллера Flash. */ + return (FLASH->SR & (FLASH_SR_BSY | FLASH_SR_PGERR | FLASH_SR_WRPRTERR)) == 0U; /* Ошибки записи или защиты делают аппаратную операцию неуспешной. */ +} /* Завершает ожидание Flash с аппаратной проверкой. */ +static bool native_unlock(void) /* Открывает Flash для одной ограниченной операции. */ +{ /* Не меняет Option Bytes или защиту загрузчика. */ + if ((FLASH->SR & FLASH_SR_BSY) != 0U) return false; /* Не посылает ключи занятому контроллеру. */ + FLASH->SR = FLASH_SR_PGERR | FLASH_SR_WRPRTERR | FLASH_SR_EOP; /* Очищает завершение и прежние ошибки записью W1C. */ + if ((FLASH->CR & FLASH_CR_LOCK) != 0U) { FLASH->KEYR = 0x45670123UL; FLASH->KEYR = 0xCDEF89ABUL; } /* Использует обязательную последовательность ключей STM32F1 из RM0008. */ + return (FLASH->CR & FLASH_CR_LOCK) == 0U; /* Проверяет фактическое снятие аппаратной блокировки. */ +} /* Завершает разблокировку без сохранения разрешения между командами. */ +static void native_lock(void) { FLASH->CR = FLASH_CR_LOCK; } /* Снимает PG/PER и восстанавливает LOCK даже после обработанной ошибки. */ +static bool native_program(uint32_t address, uint32_t value) /* Записывает и перечитывает одно выровненное полуслово. */ +{ /* Границы и выравнивание заранее проверяет общий writer. */ + volatile uint16_t *destination = (volatile uint16_t *)(uintptr_t)address; /* Выбирает аппаратную 16-битную операцию F103. */ + FLASH->SR = FLASH_SR_PGERR | FLASH_SR_WRPRTERR | FLASH_SR_EOP; FLASH->CR = FLASH_CR_PG; /* Очищает прежний результат и разрешает программирование полуслова. */ + *destination = (uint16_t)value; /* Передаёт младшие 16 бит, включая FF-дополнение неполного хвоста. */ + if (!native_wait()) return false; /* Не подтверждает запись при BUSY или аппаратной ошибке. */ + FLASH->CR = 0U; return *destination == (uint16_t)value; /* Убирает PG и проверяет реально прочитанное полуслово. */ +} /* Завершает одну аппаратную запись. */ +static bool native_erase(uint32_t size) /* Стирает страницы приложения, не пересекая область загрузчика. */ +{ /* Общая геометрия страницы задаётся единственным профилем F103C8. */ + uint32_t address, end; bool ok = true; /* Хранит исключённый конец стирания и результат до блокировки Flash. */ + if (size < 8U || size > NATIVE_APP_SIZE) return false; /* Не стирает Flash для пустого или слишком большого образа. */ + end = BOOT_APP_ADDRESS + ((size + BOOT_PAGE_SIZE - 1U) & ~(BOOT_PAGE_SIZE - 1U)); /* Округляет конец вверх к странице 1024 байта внутри профиля. */ + if (end > BOOT_FLASH_END || !native_unlock()) return false; /* Проверяет округлённую верхнюю границу до первого стирания. */ + for (address = BOOT_APP_ADDRESS; address < end; address += BOOT_PAGE_SIZE) { /* Обходит только страницы, покрывающие полезный образ. */ + FLASH->SR = FLASH_SR_PGERR | FLASH_SR_WRPRTERR | FLASH_SR_EOP; FLASH->CR = FLASH_CR_PER; FLASH->AR = address; FLASH->CR |= FLASH_CR_STRT; /* Запускает erase одной конкретной страницы вместо mass erase. */ + if (!native_wait()) { ok = false; break; } /* Прекращает стирание на первой аппаратной ошибке. */ + } /* Завершает ограниченный диапазон страниц. */ + native_lock(); return ok; /* Обязательно закрывает Flash после успешного или прерванного erase. */ +} /* Завершает аппаратное стирание F1. */ +static void native_gpio_init(void) /* Сохраняет исходную разводку CAN1 KONOR: PA11 RX и PA12 TX. */ +{ /* UART на PA9/PA10 остаётся независимым загрузочным транспортом. */ + uint32_t value; RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN; RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; /* Включает GPIOA, AFIO и CAN1 в соответствующих APB-доменах. */ + value = GPIOA->CRH; value &= ~((0xFUL << 12U) | (0xFUL << 16U)); value |= (0x8UL << 12U) | (0xBUL << 16U); GPIOA->CRH = value; /* Настраивает PA11 как вход с подтяжкой, PA12 как AF push-pull согласно RM0008. */ + GPIOA->BSRR = 1UL << 11U; /* Выбирает подтяжку CAN RX вверх, соответствующую рецессивному состоянию неподключённой линии. */ +} /* Завершает настройку физического CAN-порта. */ +static void native_peripheral_stop(void) { USART1->CR1 = 0U; RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST; RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN1RST; } /* Отключает загрузочный USART и сбрасывает CAN перед handoff. */ +#include "../stm32-common/boot_native.inc" /* Подключает общий транспорт, single-slot callbacks, CRC readback и безопасный переход MSP. */ +static bool uart_transmit(void *user, const uint8_t *data, uint16_t length) /* Отправляет кадры SETGUI v1 с ожиданием последнего стоп-бита. */ +{ /* Использует прежнюю скорость USART1 512000 бод без управления RS-485 DE. */ + uint16_t index; (void)user; /* UART-автомат использует единственный статический аппаратный порт. */ + for (index = 0U; index < length; ++index) { while ((USART1->SR & USART_SR_TXE) == 0U) {} USART1->DR = data[index]; } /* Передаёт только объявленные байты полного кадра. */ + while ((USART1->SR & USART_SR_TC) == 0U) {} return true; /* Дожидается физического завершения ответа перед возможным reset. */ +} /* Завершает аппаратную передачу UART. */ +static bool uart_erase(void *user, uint32_t size) { (void)user; return boot.state == PCAN_BOOT_STATE_IDLE && native_erase(size); } /* Не позволяет UART стереть Flash во время открытой CAN-сессии. */ +static bool uart_write(void *user, uint32_t offset, const uint8_t *data, uint16_t length) { (void)user; return native_write_bytes(uart_boot.image_size, offset, data, length); } /* Использует ту же проверку диапазонов и аппаратную запись, что CAN. */ +static bool uart_read(void *user, uint32_t offset, uint8_t *data, uint16_t length) /* Позволяет общему UART-автомату подтвердить повторно присланный блок. */ +{ /* Проверяет размер до сложения адреса, исключая переполнение. */ + (void)user; if (data == NULL || offset > NATIVE_APP_SIZE || length > NATIVE_APP_SIZE - offset) return false; /* Не читает за областью приложения. */ + (void)memcpy(data, (const void *)(uintptr_t)(NATIVE_APP_BASE + offset), length); return true; /* Копирует только объявленный безопасный диапазон Flash. */ +} /* Завершает UART readback для повторов передачи. */ +static bool uart_image_valid(void *user, uint32_t size, uint32_t crc) { (void)user; return native_image_valid(size, crc); } /* Перед END использует тот же CRC Flash и проверку векторов, что CAN VERIFY. */ +static void uart_init(void) /* Инициализирует существующий TTL UART и общий SETGUI v1-автомат. */ +{ /* Локальный Proto parser исходного проекта загрузчику больше не нужен. */ + uint32_t value; rs485_boot_config_t config = {BOOT_APP_ADDRESS, NATIVE_APP_SIZE, RS485_BOOT_MAX_BLOCK}; rs485_boot_port_t callbacks = {0}; /* Сохраняет прежний wire-протокол и предел 504 полезных байта на DATA. */ + RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN; value = GPIOA->CRH; value &= ~((0xFUL << 4U) | (0xFUL << 8U)); value |= (0xBUL << 4U) | (0x4UL << 8U); GPIOA->CRH = value; /* Настраивает PA9 TX AF-PP и PA10 RX floating, как исходный KONOR. */ + USART1->BRR = (SystemCoreClock + 256000UL) / 512000UL; USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; /* При штатном APB2=HCLK сохраняет округлённую скорость 512000 бод, 8-N-1. */ + callbacks.transmit = uart_transmit; callbacks.erase = uart_erase; callbacks.write = uart_write; callbacks.read = uart_read; callbacks.image_valid = uart_image_valid; callbacks.reboot = native_reboot; /* Подключает аппаратные операции к общему UART-автомату. */ + (void)rs485_boot_init(&uart_boot, &config, &callbacks, NULL); /* Инициализирует parser и RAM-сессию отдельного транспорта. */ +} /* Завершает настройку UART без локальной копии codec. */ +static void uart_poll(void) /* Обслуживает UART из главного цикла без прерываний и выделения памяти. */ +{ /* Во время CAN-сессии UART BEGIN отвергается callback стирания. */ + uint32_t status = USART1->SR; uint8_t byte; /* Сохраняет статус до чтения регистра данных. */ + if ((status & (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE)) != 0U) { byte = (uint8_t)USART1->DR; (void)byte; } /* Снимает аппаратные ошибки чтением SR/DR и отбрасывает повреждённый байт. */ + else if ((status & USART_SR_RXNE) != 0U) { byte = (uint8_t)USART1->DR; rs485_boot_feed(&uart_boot, &byte, 1U); } /* Передаёт исправный байт общему parser с прежним кадрированием A5 5A. */ +} /* Завершает неблокирующий приём UART. */ +int main(void) /* Самостоятельная точка входа общего загрузчика KONOR для Keil/GCC. */ +{ /* Тактирование и startup остаются в исходном проекте и выполняются до main. */ + uint16_t request; bool can_ready; /* Хранит одноразовое назначение reset и результат включения CAN. */ + RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN; PWR->CR |= PWR_CR_DBP; request = (uint16_t)BKP->DR1; BKP->DR1 = 0U; /* Потребляет совместимый BKP-запрос ровно один раз. */ + if (request == BOOT_REQUEST_SYSTEM_MAGIC) { /* Сохраняет исходную подготовку периферии перед переходом в заводской UART-загрузчик. */ + __disable_irq(); RCC->APB1RSTR = 0U; RCC->APB2RSTR = 0U; RCC->AHBENR = 0x00000014UL; RCC->APB2ENR = 0U; RCC->APB1ENR = 0U; /* Как исходный KONOR, оставляет только AHB Flash/SRAM и отключает внешнюю APB-периферию перед System Memory. */ + native_jump(0x1FFFF000UL); /* AN2606: фиксированное начало System Memory STM32F103 medium density, дальнейший переход выполняется без доступа к старому MSP. */ + } /* Завершает совместимую ветку заводского загрузчика. */ + if (request != BOOT_REQUEST_FIRMWARE_MAGIC && native_vectors_valid(NATIVE_APP_SIZE)) native_jump(BOOT_APP_ADDRESS); /* Сохраняет немедленный обычный запуск KONOR при допустимых векторах приложения. */ + SystemCoreClockUpdate(); if (SysTick_Config(SystemCoreClock / 1000U) != 0U || !native_init()) for (;;) {} /* Создаёт миллисекундный tick и проверяет текущую конфигурацию ProtoCAN до обработки команд. */ + uart_init(); can_ready = native_can_init(); /* При отказе CAN сохраняет доступный UART-канал восстановления. */ + for (;;) { uart_poll(); if (can_ready && uart_boot.state != RS485_BOOT_RECEIVING) native_can_poll(); } /* Не позволяет двум транспортам одновременно изменять одну область Flash. */ +} /* Завершает самостоятельный загрузчик; управление остаётся в сервисном цикле до успешного обновления. */ diff --git a/c/protocan-boot/ports/stm32f103/boot_profile.h b/c/protocan-boot/ports/stm32f103/boot_profile.h new file mode 100644 index 0000000..0e89187 --- /dev/null +++ b/c/protocan-boot/ports/stm32f103/boot_profile.h @@ -0,0 +1,17 @@ +#ifndef PCAN_BOOT_F103_PROFILE_H /* Согласует загрузчик и приложение KONOR с одной картой памяти. */ +#define PCAN_BOOT_F103_PROFILE_H /* Исключает повторное определение аппаратных констант. */ +#define BOOT_APP_ADDRESS 0x08003000UL /* Приложение KONOR начинается после 12 КиБ защищаемого загрузчика. */ +#define BOOT_FLASH_END 0x08010000UL /* Верхняя исключённая граница штатных 64 КиБ Flash STM32F103C8. */ +#define BOOT_PAGE_SIZE 1024UL /* Средняя плотность STM32F103C8 использует страницы Flash по 1024 байта. */ +#define BOOT_REQUEST_FIRMWARE_MAGIC 0xB007U /* Сохраняет совместимость существующего запроса обновления в BKP DR1. */ +#define BOOT_REQUEST_SYSTEM_MAGIC 0xB315U /* Сохраняет запрос перехода в заводской UART-загрузчик AN3155. */ +#define PCAN_BOOT_DEVICE_TYPE 7U /* Адрес исходного загрузчика KONOR: DeviceType=7. */ +#define PCAN_BOOT_DEVICE_ID 13U /* Адрес исходного загрузчика KONOR: DeviceID=13. */ +#define PCAN_BOOT_PRODUCT_TYPE 0U /* Исходный ProductType KONOR; должен совпадать с manifest клиента. */ +#define PCAN_BOOT_HW_REVISION 0U /* Исходная ревизия платы, согласованная с диапазоном HW manifest. */ +#define PCAN_BOOT_FW_VERSION 0U /* Версия самого загрузчика KONOR; версию приложения сообщает приложение. */ +#define PCAN_BOOT_ACK_WINDOW 16U /* Подтверждает каждые 16 блоков ProtoCAN по восемь байт. */ +#define PCAN_BOOT_CAN_BITRATE 500000UL /* Исходная скорость CAN-загрузчика, бит в секунду. */ +void Boot_RequestFirmware(void); /* Записывает запрос обновления в BKP DR1 и выполняет программный reset. */ +void Boot_RequestSystemMemory(void); /* Записывает запрос AN3155 в BKP DR1 и выполняет программный reset. */ +#endif /* Завершает профиль STM32F103C8 для загрузчика и приложения. */ diff --git a/c/protocan-boot/ports/stm32f103/boot_request.c b/c/protocan-boot/ports/stm32f103/boot_request.c new file mode 100644 index 0000000..af6ce33 --- /dev/null +++ b/c/protocan-boot/ports/stm32f103/boot_request.c @@ -0,0 +1,12 @@ +#include "boot_profile.h" /* Использует ту же карту памяти и magic, что общий загрузчик F103. */ +#include "stm32f10x.h" /* Сохраняет совместимость KONOR с CMSIS/StdPeriph без зависимости от HAL. */ +static void request_boot(uint16_t magic) /* Сохраняет одноразовый запрос через программный reset. */ +{ /* BKP DR1 существует в backup-домене STM32F103 и не требует резервирования основной SRAM. */ + RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN; /* Разрешает тактирование PWR и backup-регистров. */ + PWR->CR |= PWR_CR_DBP; /* Разрешает запись в защищённый backup-домен. */ + BKP->DR1 = magic; /* Записывает совместимый код назначения следующего запуска. */ + __DSB(); /* Гарантирует завершение записи до запроса системного сброса. */ + NVIC_SystemReset(); /* Следующий startup потребляет запрос и выбирает загрузчик. */ +} /* Завершает общую аппаратную последовательность входа. */ +void Boot_RequestFirmware(void) { request_boot(BOOT_REQUEST_FIRMWARE_MAGIC); } /* Сохраняет прежний API приложения KONOR для обновления CAN/UART. */ +void Boot_RequestSystemMemory(void) { request_boot(BOOT_REQUEST_SYSTEM_MAGIC); } /* Сохраняет прежний API меню для заводского UART-загрузчика STM32. */ diff --git a/c/protocan-boot/ports/stm32f103/pcan_boot_stm32f103.c b/c/protocan-boot/ports/stm32f103/pcan_boot_stm32f103.c new file mode 100644 index 0000000..0159849 --- /dev/null +++ b/c/protocan-boot/ports/stm32f103/pcan_boot_stm32f103.c @@ -0,0 +1,22 @@ +#include "pcan_boot_stm32f103.h" /* Подключает HAL STM32F1 и публичный профиль KONOR. */ +#include /* Предоставляет инициализацию структур и чтение невыровненных октетов. */ +#define STM32_BOOT_INIT pcan_boot_stm32f103_init /* Экспортирует семейное имя общей процедуры настройки. */ +#define STM32_BOOT_POLL pcan_boot_stm32f103_poll /* Экспортирует семейное имя обслуживания FIFO и таймеров. */ +#define STM32_BOOT_VECTORS pcan_boot_stm32f103_vectors_valid /* Экспортирует проверку векторов именно этого профиля. */ +#define STM32_BOOT_BASE PCAN_BOOT_F103_APP_ADDRESS /* Сохраняет адрес приложения исходной прошивки KONOR. */ +#define STM32_BOOT_END PCAN_BOOT_F103_FLASH_END /* Ограничивает erase и write штатными 64 КиБ Flash. */ +#define STM32_BOOT_RAM_END 0x20005000UL /* STM32F103C8 имеет 20 КиБ SRAM; MSP может указывать сразу за последним байтом. */ +#define STM32_BOOT_UNIT 2U /* Flash STM32F103 программируется полусловами по два байта. */ +#define STM32_BOOT_PROGRAM FLASH_TYPEPROGRAM_HALFWORD /* Выбирает штатный HAL-режим записи полуслова. */ +#define STM32_BOOT_SYNC() ((void)0) /* F103 не имеет Flash data cache, требующего сброса перед readback. */ +static bool erase_region(pcan_boot_stm32_t *port, uint32_t size) /* Стирает только страницы, покрывающие проверенный размер образа. */ +{ /* Вызывается общим кодом после HAL_FLASH_Unlock и проверки границ. */ + FLASH_EraseInitTypeDef erase = {0}; /* Исключает неопределённые поля семейной структуры HAL. */ + uint32_t error = 0U; /* Получает адрес страницы, на которой HAL обнаружил ошибку. */ + (void)port; /* F1 стирает выбранные страницы одной синхронной операцией HAL. */ + erase.TypeErase = FLASH_TYPEERASE_PAGES; /* Не разрешает массовое стирание, затрагивающее загрузчик. */ + erase.PageAddress = STM32_BOOT_BASE; /* Начинает стирание с первой страницы приложения. */ + erase.NbPages = (size + 1023U) / 1024U; /* Округляет вверх к странице 1 КиБ STM32F103C8, как в исходном KONOR. */ + return HAL_FLASHEx_Erase(&erase, &error) == HAL_OK; /* Прерывает обновление при ошибке или тайм-ауте Flash. */ +} /* Завершает аппаратную реализацию стирания F1. */ +#include "../stm32-common/pcan_boot_stm32.inc" /* Собирает общий transport/readback с геометрией и HAL этого семейства. */ diff --git a/c/protocan-boot/ports/stm32f103/pcan_boot_stm32f103.h b/c/protocan-boot/ports/stm32f103/pcan_boot_stm32f103.h new file mode 100644 index 0000000..62027b4 --- /dev/null +++ b/c/protocan-boot/ports/stm32f103/pcan_boot_stm32f103.h @@ -0,0 +1,11 @@ +#ifndef PCAN_BOOT_STM32F103_H /* Исключает повторное объявление порта STM32F103C8. */ +#define PCAN_BOOT_STM32F103_H /* Обозначает активный интерфейс аппаратного профиля. */ +#include "stm32f1xx_hal.h" /* Получает тип CAN_HandleTypeDef и драйверы Flash из STM32CubeF1. */ +#include "boot_profile.h" /* Использует ту же аппаратную карту, что подключённый CMSIS-загрузчик KONOR. */ +#include "../stm32-common/pcan_boot_stm32.h" /* Подключает состояние и API переносимого автомата. */ +#define PCAN_BOOT_F103_APP_ADDRESS BOOT_APP_ADDRESS /* Сохраняет публичное HAL-имя адреса приложения без дублирования числа 0x08003000. */ +#define PCAN_BOOT_F103_FLASH_END BOOT_FLASH_END /* Сохраняет публичное HAL-имя верхней границы 64 КиБ Flash из общего профиля. */ +bool pcan_boot_stm32f103_init(pcan_boot_stm32_t *port, CAN_HandleTypeDef *can, const pcan_boot_config_t *config); /* Назначает single-slot callbacks, фильтры 0/1 в FIFO0 и запускает заранее настроенный CAN1. */ +void pcan_boot_stm32f103_poll(pcan_boot_stm32_t *port); /* Обслуживает до трёх кадров FIFO0 и таймеры ядра из основного цикла. */ +bool pcan_boot_stm32f103_vectors_valid(void); /* Проверяет MSP и Thumb-вектор в пределах профиля; CRC установленного образа не подтверждает. */ +#endif /* Завершает интерфейс профиля STM32F103C8. */ diff --git a/c/protocan-boot/ports/stm32f407/README.md b/c/protocan-boot/ports/stm32f407/README.md new file mode 100644 index 0000000..571a93c --- /dev/null +++ b/c/protocan-boot/ports/stm32f407/README.md @@ -0,0 +1,51 @@ +# STM32F407VE: ProtoCAN Boot v1 + +## Подключённый climate + +`boot_main.c` содержит извлечённый CMSIS-загрузчик, `boot_control_hal.c/.h` — +адресный ENTER_BOOT из рабочего приложения. `boot_profile.h` определяет карту +Flash и SRAM-запрос; идентичность прибора остаётся в `pcan_boot_config.h` проекта. +Исходные `Bootloader/bootloader_f407.c`, `Libraries/ProtoCanBoot/Src/pcan_boot.c` +и `Core/Src/can_boot_control.c` стали include-обёртками общего submodule. +Старый include API также перенаправлен в `templates`. + +BOOT linker исключает последние восемь байт SRAM: запрос хранится в +`0x2001FFFC`, а initial stack не может затереть его до main. Приложение climate +уже использует нижние 112 КиБ SRAM и не перекрывает запрос. Обычный reset +сохраняет десятисекундное окно обновления; TX ACK перед REBOOT проверяется. +Native boot main и reusable HAL `.c` ниже — отдельные варианты сборки. + +## Reusable HAL-порт + +Аппаратный single-slot профиль извлечён из +`climate_control_f407vet6_f4/Bootloader/bootloader_f407.c` и +`Libraries/ProtoCanBoot/Inc/pcan_boot_config.h` проекта climate. +Операции с регистрами адаптированы к современному STM32CubeF4 HAL. + +| Область | Начало | Конец, исключён | Размер | +|---|---|---|---:| +| Загрузчик: секторы 0/1 | `0x08000000` | `0x08008000` | 32 КиБ | +| Приложение: секторы 2..5 | `0x08008000` | `0x08040000` | 224 КиБ | +| EEPROM-кольцо: секторы 6/7 | `0x08040000` | `0x08080000` | 256 КиБ | +| Основная SRAM для MSP | `0x20000000` | `0x20020000` | 128 КиБ | + +Размеры стираемых секторов 2/3/4/5: 16/16/64/128 КиБ. Запись выполняется +словами 32 бита, с `FLASH_VOLTAGE_RANGE_3`; VDD платы должно быть 2,7..3,6 В. +Порт не стирает секторы 0/1/6/7. CCM не используется как область допустимого MSP. + +Подключайте `pcan_boot_stm32f407.c`, общий `src/pcan_boot.c` и сохраните соседний +каталог `stm32-common`. В CMSIS выберите `STM32F407xx`, в HAL включите CAN и +Flash/FlashEx. Проект настраивает CAN1, скорость и GPIO: исходная плата использует +PD0 RX, PD1 TX, AF9, 500 кбит/с, DeviceType=7 / DeviceID=3. + +Вызывайте `pcan_boot_stm32f407_init` после `HAL_CAN_Init`, затем +`pcan_boot_stm32f407_poll` из основного цикла. Адрес прибора, Product/HW/FW, +окно ACK и тайм-аут сессии задаются через `pcan_boot_config_t` по именам полей. +Инициализация принудительно задаёт логический слот A и ёмкость 224 КиБ. + +Linker приложения и VTOR должны указывать на `0x08008000`; загрузчик должен +помещаться в 32 КиБ до этого адреса. Это исходная CAN-разметка climate: +USB SET v2-порт F407 из `set-protocol` использует другую карту памяти, +поэтому его linker и готовые USB-образы нельзя подключать без адаптации. + +[Общая инструкция, пример, ограничения COMMIT и запуска после reset](../stm32-common/README.md). diff --git a/c/protocan-boot/ports/stm32f407/boot_control_hal.c b/c/protocan-boot/ports/stm32f407/boot_control_hal.c new file mode 100644 index 0000000..9c7c6ae --- /dev/null +++ b/c/protocan-boot/ports/stm32f407/boot_control_hal.c @@ -0,0 +1,29 @@ +#include "boot_control_hal.h" /* Подключает совместимый API приложения climate. */ +#include "boot_profile.h" /* Получает общий адрес SRAM-запроса и карту Flash. */ +#include "pcan_boot_config.h" /* Идентичность прибора остаётся настройкой проекта, общей для boot и app. */ +HAL_StatusTypeDef CanBootControl_Start(CAN_HandleTypeDef *can) /* Сохраняет прежнюю настройку выделенного CAN приложения. */ +{ /* Новые приложения с DeviceCan используют только Handle и собственные адресные фильтры. */ + CAN_FilterTypeDef filter = {0}; /* Исключает неопределённые поля аппаратной конфигурации. */ + if (can == NULL) return HAL_ERROR; /* Не обращается к отсутствующему HAL handle. */ + filter.FilterBank = 0U; filter.FilterMode = CAN_FILTERMODE_IDMASK; filter.FilterScale = CAN_FILTERSCALE_32BIT; /* Сохраняет широкую фильтрацию старого выделенного канала; адрес проверяется программно. */ + filter.FilterFIFOAssignment = CAN_RX_FIFO0; filter.FilterActivation = ENABLE; filter.SlaveStartFilterBank = 14U; /* Использует FIFO0 и штатное разделение банков CAN1/CAN2. */ + if (HAL_CAN_ConfigFilter(can, &filter) != HAL_OK) return HAL_ERROR; /* Не запускает CAN с неподтверждённым фильтром. */ + return HAL_CAN_Start(can); /* Возвращает вызывающему приложению фактический результат запуска. */ +} /* Завершает совместимую настройку транспорта приложения. */ +void CanBootControl_Poll(CAN_HandleTypeDef *can) /* Поддерживает старые приложения без отдельного распределителя входящих кадров. */ +{ /* Приём ограничен одним кадром, чтобы не блокировать главный цикл. */ + CAN_RxHeaderTypeDef header; uint8_t data[8]; /* Выделяет полный буфер classic CAN независимо от входящего DLC. */ + if (can != NULL && HAL_CAN_GetRxFifoFillLevel(can, CAN_RX_FIFO0) != 0U && HAL_CAN_GetRxMessage(can, CAN_RX_FIFO0, &header, data) == HAL_OK) (void)CanBootControl_Handle(&header, data); /* Передаёт только успешно принятый кадр общему обработчику. */ +} /* Завершает опрос канала совместимости. */ +uint8_t CanBootControl_Handle(const CAN_RxHeaderTypeDef *header, const uint8_t data[8]) /* Запускает обновление только для собственного адреса и ненулевой сессии. */ +{ /* Ответ ENTER_BOOT отправляет уже загрузчик после повторного запроса клиента. */ + uint32_t id; /* Сохраняет проверенный расширенный CAN ID запроса. */ + (void)data; /* ENTER_BOOT не содержит payload и не должен читать входной буфер. */ + if (header == NULL || header->IDE != CAN_ID_EXT || header->RTR != CAN_RTR_DATA || header->DLC != 0U || header->ExtId > 0x1FFFFFFFUL) return 0U; /* Отвергает стандартные, remote и ошибочно дополненные запросы. */ + id = header->ExtId; /* Извлекает идентификатор только после проверки внешнего заголовка. */ + if (((id >> 27U) & 1U) != 0U || ((id >> 24U) & 7U) != PCAN_BOOT_DEVICE_TYPE || ((id >> 20U) & 15U) != PCAN_BOOT_DEVICE_ID || ((id >> 16U) & 15U) != 9U || (id & 255U) != 2U || ((id >> 8U) & 255U) == 0U) return 0U; /* Сопоставляет Route=0, адрес, BOOT_CONTROL=9, ENTER_BOOT=2 и SessionID != 0. */ + *((volatile uint32_t *)(uintptr_t)PCAN_BOOT_REQUEST_ADDRESS) = PCAN_BOOT_REQUEST_MAGIC; /* Сохраняет одноразовый запрос в слове SRAM, исключённом из linker-стека. */ + __DSB(); /* Дожидается записи SRAM перед системным reset. */ + NVIC_SystemReset(); /* Передаёт управление общему загрузчику без подтверждения из приложения. */ + return 1U; /* Позволяет тестовой модели и старому диспетчеру отметить обработанный запрос. */ +} /* Завершает безопасную проверку входа в загрузчик. */ diff --git a/c/protocan-boot/ports/stm32f407/boot_control_hal.h b/c/protocan-boot/ports/stm32f407/boot_control_hal.h new file mode 100644 index 0000000..4de34f5 --- /dev/null +++ b/c/protocan-boot/ports/stm32f407/boot_control_hal.h @@ -0,0 +1,7 @@ +#ifndef PCAN_BOOT_F407_CONTROL_HAL_H /* Защищает совместимый API входа climate в общий загрузчик. */ +#define PCAN_BOOT_F407_CONTROL_HAL_H /* Обозначает включение адаптера рабочего приложения. */ +#include "stm32f4xx_hal.h" /* Приложение climate передаёт штатные заголовки и handle HAL CAN. */ +HAL_StatusTypeDef CanBootControl_Start(CAN_HandleTypeDef *can); /* Сохраняет прежний API выделенного CAN-канала приложения. */ +void CanBootControl_Poll(CAN_HandleTypeDef *can); /* Проверяет один входящий кадр в старых проектах без общего CAN-диспетчера. */ +uint8_t CanBootControl_Handle(const CAN_RxHeaderTypeDef *header, const uint8_t data[8]); /* Обрабатывает адресный ENTER_BOOT из существующего диспетчера DeviceCan. */ +#endif /* Завершает интерфейс адаптера приложения F407. */ diff --git a/c/protocan-boot/ports/stm32f407/boot_main.c b/c/protocan-boot/ports/stm32f407/boot_main.c new file mode 100644 index 0000000..5fb644b --- /dev/null +++ b/c/protocan-boot/ports/stm32f407/boot_main.c @@ -0,0 +1,68 @@ +#include "boot_profile.h" /* Сохраняет карту Flash climate и зарезервированное SRAM-слово запроса. */ +#include "pcan_boot_config.h" /* Идентичность прибора и окно ACK остаются конфигурацией исходного проекта. */ +#include "../../include/pcan_boot.h" /* Подключает единственную текущую state machine ProtoCAN из templates. */ +#include "stm32f407xx.h" /* Сохраняет лёгкую CMSIS-сборку загрузчика без HAL-драйверов. */ +#include /* Предоставляет безопасное формирование слов из коротких хвостов CAN. */ +#define NATIVE_APP_BASE PCAN_BOOT_APP_ADDRESS /* Приложение climate начинается с физического сектора 2. */ +#define NATIVE_APP_SIZE PCAN_BOOT_APP_SIZE /* Ограничивает прошивку секторами 2..5, сохраняя EEPROM-кольцо. */ +#define NATIVE_RAM_END 0x20020000UL /* Физическая верхняя граница 128 КиБ SRAM сохраняет совместимость векторов ранее установленных приложений. */ +#define NATIVE_PROGRAM_UNIT 4U /* F407 программирует слова x32 при VDD 2,7..3,6 В. */ +#define NATIVE_PPRE1_SHIFT 10U /* STM32F4 размещает делитель APB1 в RCC_CFGR[12:10]. */ +#define NATIVE_FLASH_ERRORS (FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | FLASH_SR_WRPERR) /* Проверяет последовательность, разрядность, выравнивание и аппаратную защиту Flash по RM0090. */ +static pcan_boot_t boot; static volatile uint32_t ticks_ms; /* Хранит единственный автомат CAN и миллисекундные часы загрузчика. */ +static bool native_wait(void) /* Ограничивает аппаратное ожидание Flash без бесконечной блокировки. */ +{ /* Код продолжит исполняться после аппаратного Flash stall на однобанковом F407. */ + uint32_t guard = SystemCoreClock; while ((FLASH->SR & FLASH_SR_BSY) != 0U && guard != 0U) --guard; /* Использует конечный бюджет проверок в единицах итераций текущего CPU. */ + return (FLASH->SR & (FLASH_SR_BSY | NATIVE_FLASH_ERRORS)) == 0U; /* Не подтверждает операцию при BUSY или любой выбранной аппаратной ошибке. */ +} /* Завершает проверку готовности Flash. */ +static bool native_unlock(void) /* Открывает Flash только для текущей операции загрузчика. */ +{ /* Геометрия профиля исключает массовое стирание и запись Option Bytes. */ + if ((FLASH->SR & FLASH_SR_BSY) != 0U) { return false; } FLASH->SR = NATIVE_FLASH_ERRORS; /* Не посылает ключи занятой Flash и очищает предыдущие ошибки W1C. */ + if ((FLASH->CR & FLASH_CR_LOCK) != 0U) { FLASH->KEYR = 0x45670123UL; FLASH->KEYR = 0xCDEF89ABUL; } /* Использует штатную последовательность ключей RM0090. */ + return (FLASH->CR & FLASH_CR_LOCK) == 0U; /* Проверяет фактическое снятие блокировки Flash. */ +} /* Завершает разблокировку контроллера Flash. */ +static void native_lock(void) { FLASH->CR = FLASH_CR_LOCK; } /* Выключает PG/SER и восстанавливает LOCK после успеха и обработанных отказов. */ +static void native_sync_cache(void) /* Убирает устаревшие строки Flash cache перед readback соседнего записанного слова. */ +{ /* Сохраняет исходное включение instruction/data cache и остальные настройки ACR. */ + uint32_t saved = FLASH->ACR; FLASH->ACR = saved & ~(FLASH_ACR_ICEN | FLASH_ACR_DCEN); /* Отключает кэши перед их аппаратным сбросом. */ + FLASH->ACR |= FLASH_ACR_ICRST | FLASH_ACR_DCRST; FLASH->ACR &= ~(FLASH_ACR_ICRST | FLASH_ACR_DCRST); FLASH->ACR = saved; /* Сбрасывает обе cache-памяти и возвращает прежние enable/latency/prefetch настройки. */ + __DSB(); __ISB(); /* Синхронизирует последующие чтения Flash и исполняемый поток после reset кэшей. */ +} /* Завершает синхронизацию Flash cache без HAL. */ +static bool native_program(uint32_t address, uint32_t value) /* Программирует и перечитывает одно слово x32. */ +{ /* Границы и выравнивание проверяет общий writer до вызова. */ + bool ok; FLASH->SR = NATIVE_FLASH_ERRORS; FLASH->CR = FLASH_CR_PG | (2UL << FLASH_CR_PSIZE_Pos); /* Выбирает PSIZE=2, то есть 32-битную запись при VDD 2,7..3,6 В. */ + *(volatile uint32_t *)(uintptr_t)address = value; ok = native_wait(); FLASH->CR &= ~FLASH_CR_PG; native_sync_cache(); /* Дожидается завершения записи и сбрасывает устаревшие строки cache перед чтением. */ + return ok && *(const volatile uint32_t *)(uintptr_t)address == value; /* Проверяет аппаратные флаги и реально прочитанное значение, включая дополнение FF. */ +} /* Завершает одну аппаратную запись F407. */ +static bool native_erase(uint32_t size) /* Стирает только используемые секторы 2..5 приложения climate. */ +{ /* EEPROM-кольцо 6/7 и загрузочные 0/1 не включаются в таблицу разрешённых секторов. */ + static const uint32_t starts[4] = {0x08008000UL, 0x0800C000UL, 0x08010000UL, 0x08020000UL}; /* RM0090: начала секторов 2,3,4,5 объёмом 16,16,64,128 КиБ. */ + uint32_t index; bool ok = true; /* Хранит текущий сектор и результат до восстановления LOCK. */ + if (size < 8U || size > NATIVE_APP_SIZE || !native_unlock()) return false; /* Отвергает неподдерживаемый размер до первого изменения Flash. */ + for (index = 0U; index < 4U && starts[index] < NATIVE_APP_BASE + size; ++index) { /* Не стирает следующий сектор, когда образ заканчивается точно на его границе. */ + (void)pcan_boot_report_busy(&boot, PCAN_BOOT_CMD_ERASE, ticks_ms); FLASH->SR = NATIVE_FLASH_ERRORS; /* Продлевает сессию и сообщает прогресс между длительными стираниями. */ + FLASH->CR = FLASH_CR_SER | (2UL << FLASH_CR_PSIZE_Pos) | ((index + 2U) << FLASH_CR_SNB_Pos); FLASH->CR |= FLASH_CR_STRT; /* Запускает erase конкретного сектора с разрядностью x32. */ + if (!native_wait()) { ok = false; break; } /* Прерывает обновление на первом аппаратном отказе. */ + } /* Завершает обход разрешённых секторов. */ + native_lock(); native_sync_cache(); return ok; /* Восстанавливает LOCK и обновляет cache как после успеха, так и после обработанного отказа. */ +} /* Завершает аппаратное стирание F407. */ +static void native_gpio_init(void) /* Сохраняет исходный CAN1 climate на PD0/PD1 AF9. */ +{ /* Тактирование APB1 определяется общим кодом из фактического RCC_CFGR. */ + RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; /* Разрешает аппаратные такты GPIOD и CAN1. */ + GPIOD->MODER = (GPIOD->MODER & ~15UL) | 10UL; GPIOD->PUPDR = (GPIOD->PUPDR & ~3UL) | 1UL; /* Назначает PD0/PD1 альтернативной функцией и подтягивает RX к рецессивному уровню. */ + GPIOD->OSPEEDR |= 15UL; GPIOD->AFR[0] = (GPIOD->AFR[0] & ~255UL) | 0x99UL; /* Выбирает высокую скорость GPIO и AF9 обоих выводов CAN1 согласно datasheet F407. */ +} /* Завершает настройку физического CAN-порта. */ +static void native_peripheral_stop(void) { RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST; RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN1RST; } /* Сбрасывает CAN1 перед handoff без изменения памяти приложения и EEPROM. */ +#include "../stm32-common/boot_native.inc" /* Подключает общий ProtoCAN transport, CRC, callbacks и безопасную замену MSP. */ +int main(void) /* Самостоятельный загрузчик climate, подключаемый тонкой обёрткой исходного проекта. */ +{ /* Сборка PCAN_BOOTLOADER_BUILD сохраняет VTOR startup в начале Flash. */ + bool requested = *(volatile uint32_t *)(uintptr_t)PCAN_BOOT_REQUEST_ADDRESS == PCAN_BOOT_REQUEST_MAGIC; /* Читает запрос из отдельного слова SRAM, не используемого стеком или ZI. */ + *(volatile uint32_t *)(uintptr_t)PCAN_BOOT_REQUEST_ADDRESS = 0U; /* Потребляет запрос ровно один раз до запуска интерфейсов. */ + SystemCoreClockUpdate(); if (SysTick_Config(SystemCoreClock / 1000U) != 0U || !native_init()) for (;;) {} /* Использует фактический HCLK и создаёт millisecond tick до CAN-тайм-аутов. */ + while (!native_can_init()) { if (!requested && native_vectors_valid(NATIVE_APP_SIZE)) native_jump(NATIVE_APP_BASE); native_peripheral_stop(); } /* При недоступной шине сохраняет обычный запуск установленного приложения, а по запросу остаётся восстанавливаемым. */ + if (!requested && native_vectors_valid(NATIVE_APP_SIZE)) { /* Сохраняет исходное десятисекундное окно входа в обновление после обычного reset. */ + uint32_t started = ticks_ms; while ((uint32_t)(ticks_ms - started) < 10000U) { native_can_poll(); if (boot.state != PCAN_BOOT_STATE_IDLE) { requested = true; break; } } /* Обслуживает discovery и команды без ложного входа по одному IDENTIFY. */ + if (!requested) native_jump(NATIVE_APP_BASE); /* Запускает приложение после окна, используя безопасный naked handoff. */ + } /* Завершает политику обычного запуска. */ + for (;;) native_can_poll(); /* Остаётся в общем ProtoCAN-автомате до подтверждённого COMMIT/REBOOT. */ +} /* Завершает самостоятельный CMSIS-загрузчик F407. */ diff --git a/c/protocan-boot/ports/stm32f407/boot_profile.h b/c/protocan-boot/ports/stm32f407/boot_profile.h new file mode 100644 index 0000000..375e750 --- /dev/null +++ b/c/protocan-boot/ports/stm32f407/boot_profile.h @@ -0,0 +1,8 @@ +#ifndef PCAN_BOOT_F407_PROFILE_H /* Согласует нативный загрузчик climate и приложение с общей аппаратной разметкой. */ +#define PCAN_BOOT_F407_PROFILE_H /* Предотвращает повторное объявление адресов и magic. */ +#define PCAN_BOOT_APP_ADDRESS 0x08008000UL /* climate: секторы 0/1 общей ёмкостью 32 КиБ принадлежат загрузчику. */ +#define PCAN_BOOT_FLASH_END 0x08040000UL /* climate: начало EEPROM-кольца в секторе 6 исключено из приложения. */ +#define PCAN_BOOT_APP_SIZE (PCAN_BOOT_FLASH_END - PCAN_BOOT_APP_ADDRESS) /* Разрешённая ёмкость приложения составляет 224 КиБ в секторах 2..5. */ +#define PCAN_BOOT_REQUEST_MAGIC 0x5043414EUL /* Сохраняет совместимый маркер PCAN одноразового запроса обновления. */ +#define PCAN_BOOT_REQUEST_ADDRESS 0x2001FFFCUL /* Последнее слово основной SRAM F407; linker приложения и загрузчика должен исключать эти четыре байта. */ +#endif /* Завершает общую аппаратную часть конфигурации climate. */ diff --git a/c/protocan-boot/ports/stm32f407/pcan_boot_stm32f407.c b/c/protocan-boot/ports/stm32f407/pcan_boot_stm32f407.c new file mode 100644 index 0000000..748f19b --- /dev/null +++ b/c/protocan-boot/ports/stm32f407/pcan_boot_stm32f407.c @@ -0,0 +1,28 @@ +#include "pcan_boot_stm32f407.h" /* Подключает HAL STM32F4 и публичный профиль climate. */ +#include /* Предоставляет инициализацию структур и чтение невыровненных октетов. */ +#define STM32_BOOT_INIT pcan_boot_stm32f407_init /* Экспортирует семейное имя общей процедуры настройки. */ +#define STM32_BOOT_POLL pcan_boot_stm32f407_poll /* Экспортирует семейное имя обслуживания FIFO и таймеров. */ +#define STM32_BOOT_VECTORS pcan_boot_stm32f407_vectors_valid /* Экспортирует проверку векторов именно этого профиля. */ +#define STM32_BOOT_BASE PCAN_BOOT_F407_APP_ADDRESS /* Сохраняет адрес приложения исходного загрузчика climate. */ +#define STM32_BOOT_END PCAN_BOOT_F407_FLASH_END /* Не разрешает запись в EEPROM-кольцо секторов 6 и 7. */ +#define STM32_BOOT_RAM_END 0x20020000UL /* STM32F407VE: верхняя исключённая граница основной SRAM объёмом 128 КиБ. */ +#define STM32_BOOT_UNIT 4U /* Исходный F407-порт использует запись 32-битных слов при VDD 2,7..3,6 В. */ +#define STM32_BOOT_PROGRAM FLASH_TYPEPROGRAM_WORD /* Согласует разрядность программирования с VOLTAGE_RANGE_3. */ +#define STM32_BOOT_SYNC() FLASH_FlushCaches() /* HAL сохраняет состояние cache enable и сбрасывает устаревшие строки перед readback соседних записанных слов. */ +static bool erase_region(pcan_boot_stm32_t *port, uint32_t size) /* Стирает последовательно только используемые секторы приложения. */ +{ /* Общий код уже проверил размер и разблокировал Flash. */ + static const uint32_t starts[] = {0x08008000UL, 0x0800C000UL, 0x08010000UL, 0x08020000UL}; /* RM0090: начала секторов 2..5 размером 16,16,64,128 КиБ. */ + uint32_t index; /* Индекс сектора в разрешённой области приложения. */ + for (index = 0U; index < 4U && starts[index] < STM32_BOOT_BASE + size; ++index) { /* Не стирает следующий сектор, если образ закончился на его границе. */ + FLASH_EraseInitTypeDef erase = {0}; /* Обнуляет все поля аппаратной команды перед выбором сектора. */ + uint32_t error = 0U; /* Получает номер сектора с ошибкой от HAL. */ + (void)pcan_boot_report_busy(&port->boot, PCAN_BOOT_CMD_ERASE, HAL_GetTick()); /* Уведомляет клиента между длительными синхронными стираниями и продлевает сессию. */ + erase.TypeErase = FLASH_TYPEERASE_SECTORS; /* Исключает массовое стирание загрузчика и EEPROM-кольца. */ + erase.VoltageRange = FLASH_VOLTAGE_RANGE_3; /* Требует VDD 2,7..3,6 В для выбранного программирования x32. */ + erase.Sector = FLASH_SECTOR_2 + index; /* Разрешает только физические секторы 2,3,4,5 STM32F407. */ + erase.NbSectors = 1U; /* Между секторами возвращает управление для ответа BUSY. */ + if (HAL_FLASHEx_Erase(&erase, &error) != HAL_OK) return false; /* Прекращает операцию на первой аппаратной ошибке. */ + } /* Завершает обход секторов, покрывающих фактический образ. */ + return true; /* Все выбранные секторы успешно стёрты. */ +} /* Завершает аппаратную реализацию стирания F4. */ +#include "../stm32-common/pcan_boot_stm32.inc" /* Собирает общий transport/readback с геометрией и HAL этого семейства. */ diff --git a/c/protocan-boot/ports/stm32f407/pcan_boot_stm32f407.h b/c/protocan-boot/ports/stm32f407/pcan_boot_stm32f407.h new file mode 100644 index 0000000..071b9f7 --- /dev/null +++ b/c/protocan-boot/ports/stm32f407/pcan_boot_stm32f407.h @@ -0,0 +1,11 @@ +#ifndef PCAN_BOOT_STM32F407_H /* Исключает повторное объявление порта STM32F407VE. */ +#define PCAN_BOOT_STM32F407_H /* Обозначает активный интерфейс аппаратного профиля. */ +#include "stm32f4xx_hal.h" /* Получает тип CAN_HandleTypeDef и драйверы Flash из STM32CubeF4. */ +#include "boot_profile.h" /* Использует ту же аппаратную карту, что приложение и CMSIS-загрузчик climate. */ +#include "../stm32-common/pcan_boot_stm32.h" /* Подключает состояние и API переносимого автомата. */ +#define PCAN_BOOT_F407_APP_ADDRESS PCAN_BOOT_APP_ADDRESS /* Сохраняет публичное HAL-имя начала приложения без дублирования аппаратного адреса. */ +#define PCAN_BOOT_F407_FLASH_END PCAN_BOOT_FLASH_END /* Сохраняет публичное HAL-имя границы приложения перед EEPROM-кольцом секторов 6/7. */ +bool pcan_boot_stm32f407_init(pcan_boot_stm32_t *port, CAN_HandleTypeDef *can, const pcan_boot_config_t *config); /* Назначает single-slot callbacks, фильтры 0/1 в FIFO0 и запускает заранее настроенный CAN1. */ +void pcan_boot_stm32f407_poll(pcan_boot_stm32_t *port); /* Обслуживает до трёх кадров FIFO0 и таймеры ядра из основного цикла. */ +bool pcan_boot_stm32f407_vectors_valid(void); /* Проверяет MSP и Thumb-вектор в пределах профиля; CRC установленного образа не подтверждает. */ +#endif /* Завершает интерфейс профиля STM32F407VE. */ diff --git a/c/protocan-boot/ports/stm32g474-hope/README.md b/c/protocan-boot/ports/stm32g474-hope/README.md new file mode 100644 index 0000000..2f2b9d9 --- /dev/null +++ b/c/protocan-boot/ports/stm32g474-hope/README.md @@ -0,0 +1,34 @@ +# HOPE G474VET6: готовый BOOT CANdle + +Аппаратный адаптер готового CAN/UART-загрузчика из +`CANdle_stm32` (`https://git.rd12.ru/setcorp/CANdle_stm32.git`). +Основная программа, startup, проверка образа и Flash-порт повторно используются +из `../stm32g474`; протоколы — из общих `protocan-boot` и `rs485-boot`. +Новой загрузочной машины состояний в этом каталоге нет. + +По [заводской схеме HOPE от 14.04.2025](../../../set-protocol/ports/stm32g474-hope/docs/HOPE_G474VE_schematic_20250414.pdf) +CAN1 перенесён с PB8/PB9 исходного CANdle на **PD0 RX / PD1 TX, AF9**. +PB8 на этой плате соединён с BOOT0. USART1 **PA9 TX / PA10 RX, AF7** +соединён с CH340N через JP2 и сохраняет **512000 бод, 8N1**. + +CAN: Classic CAN, 500 кбит/с, extended ID, ProtoCAN Type=7/ID=15. +Тактирование сохранено из CANdle: HSI16/PLL → CPU 144 МГц, +PLLQ 48 МГц → FDCAN. USB CDC в BOOT не реализован; USB-UART работает через CH340N. + +BOOT занимает **0x08000000..0x08007FFF, 32 КиБ**. +Приложение размещается с **0x08008000**, максимум 480 КиБ. +Общая память загрузчика: SRAM 0x20000000..0x20013FF7, +стек 2 КиБ заканчивается на 0x20013FF8; маркер CANB — 0x20013FFC. +DBANK=0/1 поддерживаются готовым Flash-портом; bank swap отвергается. + +При наличии приложения после reset открывается 10-секундное окно обновления. +При отсутствии приложения или маркере CANB загрузчик остаётся ждать UART/CAN. +Перед подтверждением записи проверяются CRC и векторы сохранённого образа. +После независимого reset используется исходная проверка векторов CANdle; +постоянного manifest и A/B-слотов этот профиль не добавляет. + +Интеграция Keil: `stm32f407_emulator/G474/HOPE/Boot/MDK-ARM/HOPE_G474VE_BOOT.uvprojx`. +Все C-файлы проекта подключаются непосредственно из templates; ST HAL/CMSIS +подготавливаются из установленного Keil.STM32G4xx_DFP 1.6.0. +Первичная запись BOOT выполняется через SWD по адресам HEX, затем прошивается +профиль приложения `UMP_Emulator_HOPE_G474VE` с сохранением первых 32 КиБ. diff --git a/c/protocan-boot/ports/stm32g474-hope/device.c b/c/protocan-boot/ports/stm32g474-hope/device.c new file mode 100644 index 0000000..5768359 --- /dev/null +++ b/c/protocan-boot/ports/stm32g474-hope/device.c @@ -0,0 +1,31 @@ +#include "device.h" /* Подключает интерфейс аппаратного слоя готового загрузчика CANdle. */ +static void clock_error(void) { for (;;) {} } /* Останавливает запуск при отказе RCC, чтобы не принимать прошивку с неверной скоростью CAN. */ +void device_sysclock_config(void) /* Повторяет тактирование device_g4.c из CANdle без изменения готового CAN/UART-протокола. */ +{ /* HSI16 оставлен исходным источником boot; приложение самостоятельно переключается на кварц HOPE 8 МГц. */ + RCC_OscInitTypeDef osc = {0}; RCC_ClkInitTypeDef clk = {0}; RCC_PeriphCLKInitTypeDef peripheral = {0}; /* Полностью определяет структуры HAL до запуска PLL и шин. */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); /* Разрешает проверку Flash bank swap и настройку регулятора питания. */ + if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST) != HAL_OK) clock_error(); /* Boost Range1 обеспечивает допустимый режим CPU 144 МГц. */ + osc.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSI48; /* Сохраняет источники оригинального аппаратного профиля CANdle. */ + osc.HSIState = RCC_HSI_ON; osc.HSI48State = RCC_HSI48_ON; osc.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; /* Использует заводскую калибровку HSI16 и включает исходный HSI48. */ + osc.PLL.PLLState = RCC_PLL_ON; osc.PLL.PLLSource = RCC_PLLSOURCE_HSI; osc.PLL.PLLM = RCC_PLLM_DIV4; /* HSI16 / 4 формирует вход PLL 4 МГц, как в готовом CANdle. */ + osc.PLL.PLLN = 72U; osc.PLL.PLLP = RCC_PLLP_DIV2; osc.PLL.PLLQ = RCC_PLLQ_DIV6; osc.PLL.PLLR = RCC_PLLR_DIV2; /* VCO 288 МГц создаёт CPU 144 МГц и FDCAN kernel 48 МГц через PLLQ. */ + if (HAL_RCC_OscConfig(&osc) != HAL_OK) clock_error(); /* Не продолжает загрузку при отказе внутренних генераторов или PLL. */ + clk.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; /* Согласует частоты ядра и обеих периферийных шин. */ + clk.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; clk.AHBCLKDivider = RCC_SYSCLK_DIV1; /* Передаёт CPU и AHB исходные 144 МГц без деления. */ + clk.APB1CLKDivider = RCC_HCLK_DIV1; clk.APB2CLKDivider = RCC_HCLK_DIV1; /* USART1 получает PCLK2 144 МГц для расчёта прежних 512000 бод. */ + if (HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_4) != HAL_OK) clock_error(); /* Сохраняет исходные четыре wait-state Flash и проверяет переключение SYSCLK. */ + peripheral.PeriphClockSelection = RCC_PERIPHCLK_USB | RCC_PERIPHCLK_FDCAN; /* Повторяет независимые источники USB и CAN исходного CANdle. */ + peripheral.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; peripheral.FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL; /* FDCAN использует PLLQ 48 МГц, а не PCLK1 144 МГц. */ + if (HAL_RCCEx_PeriphCLKConfig(&peripheral) != HAL_OK) clock_error(); /* Исключает запуск CAN с неподтверждённым kernel clock. */ + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000U); HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); /* Обеспечивает миллисекундные тайм-ауты готовой загрузочной машины состояний. */ + HAL_NVIC_SetPriority(SysTick_IRQn, 0U, 0U); /* Сохраняет приоритет SysTick оригинального загрузчика CANdle. */ +} /* Завершает аппаратный clock-профиль без изменения Flash Option Bytes. */ +void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *can) /* Привязывает существующий FDCAN-загрузчик к штатному CAN1 платы HOPE. */ +{ /* Единственное изменение маршрута CAN относительно device_g4.c: PD0/PD1 вместо PB8/PB9. */ + GPIO_InitTypeDef gpio = {0}; /* Не оставляет неопределённых параметров скорости и альтернативной функции GPIO. */ + if (can->Instance != FDCAN1) return; /* Не перенастраивает дополнительные CAN2/CAN3 платы. */ + __HAL_RCC_FDCAN_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /* Разрешает общий FDCAN kernel и порт D штатного трансивера U6. */ + gpio.Pin = GPIO_PIN_0 | GPIO_PIN_1; gpio.Mode = GPIO_MODE_AF_PP; gpio.Pull = GPIO_NOPULL; /* PD0 RX и PD1 TX соединены с TJA1051T/3 по схеме HOPE от 14.04.2025. */ + gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; gpio.Alternate = GPIO_AF9_FDCAN1; /* AF9 выбирает FDCAN1 на PD0/PD1 без занятия BOOT0 на PB8. */ + HAL_GPIO_Init(GPIOD, &gpio); /* Подключает готовый CAN-загрузчик к CAN1L/CAN1H разъёма J4. */ +} /* Завершает аппаратный адаптер HOPE; кадры, CRC и запись Flash реализованы готовыми модулями templates. */ diff --git a/c/protocan-boot/ports/stm32g474-hope/device.h b/c/protocan-boot/ports/stm32g474-hope/device.h new file mode 100644 index 0000000..72a37fd --- /dev/null +++ b/c/protocan-boot/ports/stm32g474-hope/device.h @@ -0,0 +1,5 @@ +#ifndef HOPE_BOOT_DEVICE_H /* Защищает аппаратный интерфейс HOPE от повторного включения. */ +#define HOPE_BOOT_DEVICE_H /* Обозначает плату HOPE STM32G474VET6 для готового main CANdle. */ +#include "stm32g4xx_hal.h" /* Предоставляет общему загрузчику HAL FDCAN и системные регистры STM32G4. */ +void device_sysclock_config(void); /* Сохраняет вызов настройки платы, ожидаемый готовым загрузчиком CANdle. */ +#endif /* Завершает интерфейс платы без копирования загрузочного протокола. */ diff --git a/c/protocan-boot/ports/stm32g474-hope/stm32g4xx_hal_conf.template.h b/c/protocan-boot/ports/stm32g474-hope/stm32g4xx_hal_conf.template.h new file mode 100644 index 0000000..2dd3a41 --- /dev/null +++ b/c/protocan-boot/ports/stm32g474-hope/stm32g4xx_hal_conf.template.h @@ -0,0 +1,32 @@ +#ifndef STM32G4xx_HAL_CONF_H /* Защищает минимальную конфигурацию HAL загрузчика от повторного включения. */ +#define STM32G4xx_HAL_CONF_H /* Отделяет BOOT от настроек моделей, дисплея и USB CDC приложения. */ +#define HAL_MODULE_ENABLED /* Разрешает базовый HAL_Init и миллисекундные аппаратные таймеры. */ +#define HAL_CORTEX_MODULE_ENABLED /* Подключает HAL NVIC и SysTick, используемые готовым startup CANdle. */ +#define HAL_RCC_MODULE_ENABLED /* Подключает управление HSI16, PLL и kernel clock FDCAN. */ +#define HAL_GPIO_MODULE_ENABLED /* Подключает UART PA9/PA10 и CAN PD0/PD1. */ +#define HAL_FLASH_MODULE_ENABLED /* Разрешает готовому Flash-порту G474 стирать и записывать только область приложения. */ +#define HAL_PWR_MODULE_ENABLED /* Подключает Boost Range1 для исходных 144 МГц boot. */ +#define HAL_FDCAN_MODULE_ENABLED /* Разрешает Classic CAN 500 кбит/с готового ProtoCAN-загрузчика. */ +#define HSE_VALUE 8000000UL /* Сохраняет номинал внешнего кварца HOPE в герцах, хотя boot использует HSI16. */ +#define HSE_STARTUP_TIMEOUT 100UL /* Ограничивает ожидание внешнего кварца 100 мс при использовании HAL RCC. */ +#define HSI_VALUE 16000000UL /* Внутренний источник исходного CANdle имеет частоту 16 МГц. */ +#define HSI48_VALUE 48000000UL /* Отдельный внутренний генератор USB имеет частоту 48 МГц. */ +#define LSE_VALUE 32768UL /* RTC-кварц HOPE имеет частоту 32768 Гц и не участвует в загрузочной PLL. */ +#define LSE_STARTUP_TIMEOUT 5000UL /* Стандартный HAL допускает до 5 секунд запуска RTC-кварца. */ +#define LSI_VALUE 32000UL /* Определяет номинальную частоту внутреннего низкочастотного RC в герцах. */ +#define EXTERNAL_CLOCK_VALUE 12288000UL /* Сохраняет стандартный номинал неиспользуемого внешнего аудиотактирования HAL. */ +#define VDD_VALUE 3300UL /* Логика платы питается напряжением 3300 мВ через AMS1117-3.3. */ +#define TICK_INT_PRIORITY 0UL /* Повторяет приоритет SysTick готового загрузчика CANdle. */ +#define USE_RTOS 0U /* Загрузчик обслуживает UART/CAN опросом без операционной системы. */ +#define PREFETCH_ENABLE 0U /* Сохраняет стандартный выключенный prefetch HAL G4. */ +#define INSTRUCTION_CACHE_ENABLE 1U /* Разрешает аппаратный кэш инструкций при выполнении boot из Flash. */ +#define DATA_CACHE_ENABLE 1U /* Разрешает стандартный кэш данных HAL G4. */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* Использует статическую HAL_FDCAN_MspInit аппаратного адаптера HOPE. */ +#include "stm32g4xx_hal_rcc.h" /* Предоставляет HAL RCC и расширенные функции выбора источников частоты. */ +#include "stm32g4xx_hal_gpio.h" /* Предоставляет структуры и альтернативные функции GPIO. */ +#include "stm32g4xx_hal_cortex.h" /* Предоставляет HAL NVIC и управление SysTick. */ +#include "stm32g4xx_hal_flash.h" /* Предоставляет операции разблокировки, doubleword-записи и стирания Flash. */ +#include "stm32g4xx_hal_pwr.h" /* Предоставляет управление регулятором и Boost Range1. */ +#include "stm32g4xx_hal_fdcan.h" /* Предоставляет транспортные структуры и функции FDCAN. */ +#define assert_param(expression) ((void)0U) /* Сохраняет штатное отключение отладочных assert HAL в рабочем загрузчике. */ +#endif /* Завершает самостоятельную HAL-конфигурацию шаблона HOPE BOOT. */ diff --git a/c/protocan-boot/ports/stm32g474/LICENSE.source.md b/c/protocan-boot/ports/stm32g474/LICENSE.source.md new file mode 100644 index 0000000..6977229 --- /dev/null +++ b/c/protocan-boot/ports/stm32g474/LICENSE.source.md @@ -0,0 +1,34 @@ +# Licenses + +## candleLight Firmware Sources + +The MIT License (MIT) + +Copyright (c) 2016 Hubert Denkmair + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +## STM32 HAL +The HAL is distributed under a non-restrictive BSD (Berkeley Software +Distribution) license. + +## STM32 USB Library +Code from the STM32 USB library is licensed +under ST STMicroelectronics +[Ultimate Liberty license SLA0044] (www.st.com/SLA0044) diff --git a/c/protocan-boot/ports/stm32g474/README.md b/c/protocan-boot/ports/stm32g474/README.md new file mode 100644 index 0000000..f672869 --- /dev/null +++ b/c/protocan-boot/ports/stm32g474/README.md @@ -0,0 +1,63 @@ +# STM32G474VET6: ProtoCAN Boot v1 / CANdle + +Исходный проект: `https://git.rd12.ru/setcorp/CANdle_stm32.git`, commit +`61a93c5`. Аппаратный код извлечён из `src/boot/g474_can_bootloader.c`, +`src/can_boot_control.c` и `src/boot/g474_boot_startup.c`; локальная CAN state +machine заменена единым `src/pcan_boot.c`. Лицензия исходного проекта сохранена +в [`LICENSE.source.md`](LICENSE.source.md). + +| Область | Начало | Конец, исключён | Размер | +|---|---|---|---:| +| Загрузчик | `0x08000000` | `0x08008000` | 32 КиБ | +| Single-slot приложение | `0x08008000` | `0x08080000` | 480 КиБ | +| RAM проекта | `0x20000000` | `0x20013FF8` | 80 КиБ − 8 байт | +| Одноразовый запрос CANB | `0x20013FFC` | `0x20014000` | 4 байта | + +`boot_profile.h` содержит единые адреса/magic и совместимый API приложения. +Валидатор векторов допускает прежний MSP вплоть до физической границы +`0x20014000`; новые linker/startup исключают последние восемь байт, чтобы +не затереть запрос до чтения в main. RAM-COMMIT не сохраняется после питания. + +## Состав и подключение + +- `pcan_boot_stm32g474.c/.h` — reusable HAL FDCAN/Flash-порт с single-slot, + независимым CRC readback, doubleword записью и проверкой TXBTO перед reset. +- `boot_main.c` — самостоятельный CAN/UART-загрузчик CANdle, без собственной + реализации wire-протокола; использует `pcan_boot` и общий `rs485-boot`. +- `boot_startup.c` — исходная схема Keil/GCC startup с безопасным initial MSP. +- `boot_control.c` — вход из приложения по адресному ENTER_BOOT или UART BEGIN, + совместимый UART PING/ACK и исходный USART1 IRQ. + +В проекте CANdle старые файлы стали include-обёртками из submodule `templates`. +BOOT Keil и CMake компилируют дополнительно `pcan_boot.c` и +`pcan_boot_stm32g474.c`. Приложение использует общий `boot_control.c` без +подключения загрузочной state machine к USB–CAN приложению. + +Board-проект предоставляет `device.h`, `device_sysclock_config`, +`HAL_FDCAN_MspInit`, CMSIS/HAL и linker. Исходная плата использует CPU 144 МГц, +FDCAN kernel 48 МГц, FDCAN1 PB8/PB9 AF9, classic CAN 500 кбит/с, +DeviceType=7 / DeviceID=15. UART — PA9/PA10 AF7, 512000 бод, TTL без DE. +Для reusable API вызовите `HAL_FDCAN_Init` с двумя extended-фильтрами, +затем `pcan_boot_stm32g474_init`, затем регулярно `poll` из main. +FDCAN и его TX FIFO должны принадлежать этому порту, без конкурирующих TX IRQ. + +## Flash и протокол + +Поддерживается реальная плотность 512 КиБ. DBANK=1 использует два банка по +256 КиБ и страницы 2 КиБ; DBANK=0 — один банк 512 КиБ и страницы 4 КиБ. +Номера страниц считаются отдельно для каждого банка, с проверкой всей +округлённой области до erase. BFB2 и SYSCFG FB_MODE bank swap отвергаются; +Option Bytes не изменяются. Другие плотности требуют собственного профиля. + +Flash программируется doubleword по восемь байт. Неполный doubleword +дополняется FF только в конце образа; повторная запись ECC-слова в середине +потока не допускается. UART использует тот же writer, что CAN DATA. +VERIFY перечитывает Flash, COMMIT повторяет проверку, REBOOT возможен только +после COMMIT и физически подтверждённого TX. Кодирование DLC определяется +константами используемой версии HAL; старый сдвиг 16 и новый сдвиг 0 не смешиваются. + +Стирание синхронное. Клиент должен допускать длительное Flash stall; BUSY до +и после erase поддерживает сессию. Постоянного manifest, A/B-rollback, resume +после питания и аутентификации в исходном single-slot профиле нет. + +[Подключённые проекты и проверки Keil/CMake](../../projects/STM32.md). diff --git a/c/protocan-boot/ports/stm32g474/boot_control.c b/c/protocan-boot/ports/stm32g474/boot_control.c new file mode 100644 index 0000000..c7dd270 --- /dev/null +++ b/c/protocan-boot/ports/stm32g474/boot_control.c @@ -0,0 +1,48 @@ +#include "boot_profile.h" /* Получает единственный источник адресов, magic и функций входа CANdle G474. */ +#include "stm32g4xx.h" /* Использует исходный CMSIS-порт USART/SRAM без зависимости приложения от загрузочного main. */ +static volatile bool request; /* IRQ либо CAN-диспетчер отмечает запрос, который основной цикл может безопасно обработать. */ +static uint8_t frame[28], used; /* Кадр BEGIN содержит 8 байт заголовка, 16 байт payload и 4 байта CRC, всего 28 байт. */ +static uint32_t read32(const uint8_t *data) { return (uint32_t)data[0] | ((uint32_t)data[1] << 8U) | ((uint32_t)data[2] << 16U) | ((uint32_t)data[3] << 24U); } /* Извлекает little-endian CRC без невыровненного чтения. */ +static uint32_t crc32(const uint8_t *data, uint8_t length) /* Малый app-only codec сохраняет отсутствие зависимости приложения от boot-автомата. */ +{ /* Формат PING/BEGIN совпадает с SETGUI v1, исходный полином IEEE отражённый. */ + uint32_t crc = 0xFFFFFFFFUL; uint8_t index, bit; /* Начинает IEEE CRC32 с инверсного состояния, как исходное приложение CANdle. */ + for (index = 0U; index < length; ++index) { crc ^= data[index]; for (bit = 0U; bit < 8U; ++bit) crc = (crc >> 1U) ^ ((crc & 1U) != 0U ? 0xEDB88320UL : 0U); } /* Обрабатывает только проверенные октеты и восемь бит каждого байта. */ + return ~crc; /* Выполняет финальный XOR, совместимый с zlib и загрузчиком SETGUI v1. */ +} /* Завершает совместимый малый CRC приложения. */ +void can_boot_observe(uint32_t id, bool extended, uint8_t dlc) /* Не переводит приложение в обновление по чужому либо невалидному кадру. */ +{ /* Переход откладывается до вызова can_boot_enter из существующего main. */ + if (extended && dlc == 0U && id <= 0x1FFFFFFFUL && ((id >> 27U) & 1U) == 0U && ((id >> 24U) & 7U) == CAN_BOOT_DEVICE_TYPE && ((id >> 20U) & 15U) == CAN_BOOT_DEVICE_ID && ((id >> 16U) & 15U) == 9U && (id & 255U) == 2U && ((id >> 8U) & 255U) != 0U) request = true; /* Требует Route=0, собственный адрес, BOOT_CONTROL/ENTER_BOOT и ненулевую сессию. */ +} /* Завершает наблюдение входящего CAN без чтения отсутствующего payload. */ +bool can_boot_requested(void) { return request; } /* Сохраняет прежний API опроса приложения CANdle. */ +void can_boot_enter(void) { *(volatile uint32_t *)(uintptr_t)CAN_BOOT_REQUEST_ADDRESS = CAN_BOOT_REQUEST_MAGIC; __DSB(); NVIC_SystemReset(); } /* Записывает CANB в зарезервированное SRAM-слово до системного сброса. */ +static void process_frame(void) /* Принимает только проверенные короткие PING и BEGIN приложения. */ +{ /* Полный firmware flow после BEGIN обслуживает уже общий загрузчик из templates. */ + uint8_t payload = frame[7]; uint32_t checksum; /* Размер payload предварительно ограничен шестнадцатью байтами. */ + if (frame[2] != 1U || read32(frame + 8U + payload) != crc32(frame + 2U, (uint8_t)(6U + payload))) { return; } /* Не выполняет reset по кадру другой версии либо повреждённому CRC. */ + if (frame[3] == 0x0BU && payload == 16U) { can_boot_enter(); return; } /* Сохраняет существующий SETGUI FIRMWARE_BEGIN как запрос входа в загрузчик. */ + if (frame[3] == 1U && payload == 0U) { /* PING подтверждает наличие UART приложения без входа в обновление. */ + uint8_t reply[15] = {0xA5U, 0x5AU, 1U, 0x81U, frame[4], frame[5], 0U, 3U, 0U, 0U, 1U}; uint8_t index; /* Формирует прежний ACK PING с номером входящего запроса и трёхбайтовым результатом. */ + checksum = crc32(reply + 2U, 9U); for (index = 0U; index < 4U; ++index) reply[11U + index] = (uint8_t)(checksum >> (index * 8U)); /* Добавляет CRC32 LE после девяти защищаемых байтов ver/header/payload. */ + for (index = 0U; index < sizeof(reply); ++index) { while ((USART1->ISR & USART_ISR_TXE_TXFNF) == 0U) {} USART1->TDR = reply[index]; } /* Отправляет полный совместимый ответ USART1. */ + while ((USART1->ISR & USART_ISR_TC) == 0U) {} USART1->ICR = USART_ICR_TCCF; /* Дожидается последнего стоп-бита и очищает флаг завершения передачи. */ + } /* Остальные сообщения приложения не относятся к входу в boot и игнорируются. */ +} /* Завершает обработку валидного короткого кадра приложения. */ +void can_boot_uart_init(void) /* Сохраняет исходную разводку и IRQ-приём UART CANdle G474. */ +{ /* Этот код компилируется только в работающем приложении с CONFIG_CAN_BOOT_APP. */ + RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN; /* Включает GPIOA и USART1 в соответствующих clock-доменах G474. */ + GPIOA->MODER = (GPIOA->MODER & ~((3UL << 18U) | (3UL << 20U))) | (2UL << 18U) | (2UL << 20U); /* Переводит PA9 и PA10 в режим альтернативной функции. */ + GPIOA->AFR[1] = (GPIOA->AFR[1] & ~((15UL << 4U) | (15UL << 8U))) | (7UL << 4U) | (7UL << 8U); /* Назначает AF7 USART1 TX/RX согласно исходной плате CANdle. */ + USART1->BRR = (SystemCoreClock + 256000UL) / 512000UL; USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | USART_CR1_UE; /* Сохраняет 512000 бод при исходном APB2=HCLK и приём по RXNE IRQ. */ + NVIC_SetPriority(USART1_IRQn, 2U); NVIC_EnableIRQ(USART1_IRQn); used = 0U; /* Сохраняет приоритет 2 исходного UART и очищает parser перед приёмом. */ +} /* Завершает настройку входа приложения через UART. */ +void can_boot_uart_poll(void) /* Принимает один октет, проверяет длину и синхронизацию до записи в малый буфер. */ +{ /* Длина 28 байт покрывает только PING и BEGIN; больших команд здесь нет. */ + uint32_t status = USART1->ISR; uint8_t byte, total; /* Сохраняет флаги USART до чтения RDR. */ + if ((status & (USART_ISR_ORE | USART_ISR_FE | USART_ISR_NE)) != 0U) { USART1->ICR = USART_ICR_ORECF | USART_ICR_FECF | USART_ICR_NECF; used = 0U; return; } /* Сбрасывает parser после аппаратной потери либо повреждения байта. */ + if ((status & USART_ISR_RXNE_RXFNE) == 0U) { return; } byte = (uint8_t)USART1->RDR; /* Не читает RDR без доступного октета. */ + if (used == 0U && byte != 0xA5U) { return; } if (used == 1U && byte != 0x5AU) { used = byte == 0xA5U ? 1U : 0U; return; } /* Ищет двухбайтовую сигнатуру A5 5A с сохранением возможного начала следующего кадра. */ + frame[used++] = byte; if (used < 8U) { return; } /* Накапливает только ограниченный буфер и ждёт полного восьмибайтового заголовка. */ + if (frame[6] != 0U || frame[7] > 16U) { used = 0U; return; } /* Запрещает длину больше шестнадцати байтов до дальнейшего накопления. */ + total = (uint8_t)(12U + frame[7]); if (used < total) { return; } process_frame(); used = 0U; /* Передаёт полный header/payload/CRC обработчику и начинает следующий короткий кадр. */ +} /* Завершает безопасный parser приложения. */ +void USART1_IRQHandler(void) { can_boot_uart_poll(); } /* Сохраняет прежний экспорт IRQ, используемый startup приложения CANdle. */ diff --git a/c/protocan-boot/ports/stm32g474/boot_main.c b/c/protocan-boot/ports/stm32g474/boot_main.c new file mode 100644 index 0000000..2f8e508 --- /dev/null +++ b/c/protocan-boot/ports/stm32g474/boot_main.c @@ -0,0 +1,66 @@ +#include "pcan_boot_stm32g474.h" /* Подключает FDCAN/Flash порт и единственную ProtoCAN state machine templates. */ +#include "../../../rs485-boot/include/rs485_boot.h" /* Повторно использует общий SETGUI v1 UART updater. */ +#include "device.h" /* Тактирование и GPIO FDCAN остаются аппаратной привязкой исходного board-проекта. */ +#include /* Копирует проверенные диапазоны Flash для повторов UART-блоков. */ +static FDCAN_HandleTypeDef can; static pcan_boot_stm32_t updater; static rs485_boot_t uart_boot; static bool can_started; /* Сохраняет состояния двух транспортов и факт успешного аппаратного запуска FDCAN. */ +static __attribute__((naked, noreturn)) void enter_app(uint32_t sp __attribute__((unused)), uint32_t pc __attribute__((unused))) /* Не обращается к старому C-стеку после замены MSP. */ +{ /* AAPCS передаёт исходный MSP приложения в r0 и Thumb entry в r1. */ + __asm volatile("msr msp, r0\n" "movs r2, #0\n" "msr control, r2\n" "dsb\n" "isb\n" "cpsie i\n" "bx r1\n"); /* Согласует привилегированный режим и конвейер до безвозвратного перехода по новому вектору. */ +} /* Завершает naked handoff без эпилога C. */ +static void jump_app(void) /* Отключает загрузочные интерфейсы перед запуском установленного приложения. */ +{ /* Структурная проверка векторов выполнена вызывающим main. */ + const uint32_t *vectors = (const uint32_t *)(uintptr_t)CAN_BOOT_APP_ADDRESS; uint32_t sp = vectors[0], pc = vectors[1], index; /* Сохраняет новые значения до отключения прерываний и смены стека. */ + __disable_irq(); SysTick->CTRL = 0U; USART1->CR1 = 0U; if (can_started) (void)HAL_FDCAN_Stop(&can); /* Не допускает работы загрузочного UART/CAN и SysTick после handoff. */ + for (index = 0U; index < 8U; ++index) { NVIC->ICER[index] = 0xFFFFFFFFUL; NVIC->ICPR[index] = 0xFFFFFFFFUL; } /* Снимает внешние enable/pending IRQ записью W1C. */ + SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk | SCB_ICSR_PENDSVCLR_Msk; SCB->VTOR = CAN_BOOT_APP_ADDRESS; /* Очищает системные pending IRQ и согласует VTOR с linker приложения. */ + enter_app(sp, pc); /* Передаёт управление без обращения к старому C-стеку. */ +} /* Завершает аппаратную подготовку запуска приложения. */ +static bool uart_transmit(void *user, const uint8_t *data, uint16_t length) /* Передаёт совместимые ответы SETGUI v1 через USART1. */ +{ /* Транспорт TTL не управляет DE внешнего RS-485 трансивера. */ + uint16_t index; (void)user; for (index = 0U; index < length; ++index) { while ((USART1->ISR & USART_ISR_TXE_TXFNF) == 0U) {} USART1->TDR = data[index]; } /* Передаёт полный сформированный кадр без чтения за его длиной. */ + while ((USART1->ISR & USART_ISR_TC) == 0U) {} USART1->ICR = USART_ICR_TCCF; return true; /* Дожидается последнего стоп-бита до возможного reset после END. */ +} /* Завершает синхронную UART передачу. */ +static bool uart_erase(void *user, uint32_t size) { (void)user; return updater.boot.state == PCAN_BOOT_STATE_IDLE && pcan_boot_stm32g474_erase(size); } /* Не позволяет UART стереть Flash при открытой CAN-сессии. */ +static bool uart_write(void *user, uint32_t offset, const uint8_t *data, uint16_t length) { (void)user; return pcan_boot_stm32g474_write(uart_boot.image_size, offset, data, length); } /* Использует тот же doubleword writer, что CAN DATA. */ +static bool uart_read(void *user, uint32_t offset, uint8_t *data, uint16_t length) /* Подтверждает повторы UART-блоков чтением сохранённых данных. */ +{ /* Проверяет размеры вычитанием, чтобы не переполнить адресное сложение. */ + (void)user; if (data == NULL || offset > CAN_BOOT_APP_SIZE || length > CAN_BOOT_APP_SIZE - offset) { return false; } /* Не допускает чтение за пределами 480-КиБ области. */ + (void)memcpy(data, (const void *)(uintptr_t)(CAN_BOOT_APP_ADDRESS + offset), length); return true; /* Возвращает только проверенный диапазон Flash. */ +} /* Завершает readback повторного UART-запроса. */ +static bool uart_valid(void *user, uint32_t size, uint32_t crc) { (void)user; return pcan_boot_stm32g474_image_valid(size, crc); } /* Перед END проверяет векторы и настоящий CRC Flash общим портом. */ +static void uart_reboot(void *user) { (void)user; NVIC_SystemReset(); } /* UART callback вызывается после физически завершённого ответа END. */ +static void uart_init(void) /* Сохраняет исходные PA9/PA10 AF7, 512000 бод и общий SETGUI v1 updater. */ +{ /* Аппаратные частоты уже настроены board-функцией device_sysclock_config. */ + GPIO_InitTypeDef gpio = {0}; rs485_boot_config_t config = {CAN_BOOT_APP_ADDRESS, CAN_BOOT_APP_SIZE, RS485_BOOT_MAX_BLOCK}; rs485_boot_port_t callbacks = {0}; /* Полностью определяет структуры текущих HAL и UART API. */ + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_USART1_CLK_ENABLE(); gpio.Pin = GPIO_PIN_9 | GPIO_PIN_10; gpio.Mode = GPIO_MODE_AF_PP; gpio.Pull = GPIO_NOPULL; gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; gpio.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &gpio); /* Назначает исходные TX/RX выводы без изменения CAN PB8/PB9. */ + USART1->BRR = (HAL_RCC_GetPCLK2Freq() + 256000UL) / 512000UL; USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_FIFOEN | USART_CR1_UE; /* Рассчитывает скорость от фактического PCLK2 и включает polling UART с FIFO. */ + callbacks.transmit = uart_transmit; callbacks.erase = uart_erase; callbacks.write = uart_write; callbacks.read = uart_read; callbacks.image_valid = uart_valid; callbacks.reboot = uart_reboot; /* Подключает общий Flash writer и проверку образа вместо локальной реализации UART flow. */ + (void)rs485_boot_init(&uart_boot, &config, &callbacks, NULL); /* Создаёт отдельную RAM-сессию UART с прежним wire-протоколом. */ +} /* Завершает настройку UART восстановления. */ +static bool fdcan_init(void) /* Сохраняет исходные 48 МГц kernel clock и скорость classic CAN 500 кбит/с. */ +{ /* GPIO FDCAN PB8/PB9 AF9 включает board-функция HAL_FDCAN_MspInit. */ + pcan_boot_config_t config = {0}; can.Instance = FDCAN1; can.Init.ClockDivider = FDCAN_CLOCK_DIV1; can.Init.FrameFormat = FDCAN_FRAME_CLASSIC; can.Init.Mode = FDCAN_MODE_NORMAL; can.Init.AutoRetransmission = ENABLE; /* Выбирает единственный выделенный FDCAN1 без CAN FD/BRS и с автоматическим повтором TX. */ + can.Init.NominalPrescaler = 6U; can.Init.NominalSyncJumpWidth = 2U; can.Init.NominalTimeSeg1 = 13U; can.Init.NominalTimeSeg2 = 2U; /* 48 МГц / 6 / (1+13+2) дают ровно 500000 бит/с. */ + can.Init.DataPrescaler = 6U; can.Init.DataSyncJumpWidth = 2U; can.Init.DataTimeSeg1 = 13U; can.Init.DataTimeSeg2 = 2U; /* Полностью инициализирует data timing, хотя в classic режиме он не используется. */ + can.Init.StdFiltersNbr = 0U; can.Init.ExtFiltersNbr = 2U; can.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* Выделяет адресный и broadcast-discovery фильтры общему порту. */ + if (HAL_FDCAN_Init(&can) != HAL_OK) { return false; } config.device_type = CAN_BOOT_DEVICE_TYPE; config.device_id = CAN_BOOT_DEVICE_ID; config.ack_window = 16U; config.session_timeout_ms = 30000UL; /* Сохраняет исходный адрес 7:15 и окно ACK, добавляя тайм-аут RAM-сессии 30 секунд. */ + return pcan_boot_stm32g474_init(&updater, &can, &config); /* Инициализирует единую state machine ProtoCAN и проверяет геометрию Flash. */ +} /* Завершает настройку FDCAN без локальной копии CAN-протокола. */ +static void service_interfaces(void) /* Обслуживает оба транспорта без одновременной записи одной Flash-области. */ +{ /* Каждый вызов ограничивает обработку UART шестьюдесятью четырьмя октетами. */ + uint32_t count; for (count = 0U; count < 64U; ++count) { /* Не позволяет постоянному UART-потоку захватить главный цикл целиком. */ + uint32_t status = USART1->ISR; uint8_t byte; if ((status & (USART_ISR_ORE | USART_ISR_FE | USART_ISR_NE)) != 0U) USART1->ICR = USART_ICR_ORECF | USART_ICR_FECF | USART_ICR_NECF; /* Снимает аппаратные ошибки USART перед дальнейшим приёмом. */ + if ((status & USART_ISR_RXNE_RXFNE) == 0U) { break; } byte = (uint8_t)USART1->RDR; rs485_boot_feed(&uart_boot, &byte, 1U); /* Передаёт доступный октет общему UART parser. */ + } /* Завершает ограниченный пакет UART. */ + if (can_started && uart_boot.state != RS485_BOOT_RECEIVING) pcan_boot_stm32g474_poll(&updater); /* Во время записи UART запрещает второй транспорт, в остальных состояниях обслуживает CAN и discovery. */ +} /* Завершает мультиплексирование загрузочных интерфейсов. */ +int main(void) /* Подключает исходный board startup CANdle к общим загрузочным библиотекам templates. */ +{ /* Linker и initial MSP должны исключать последние восемь байт SRAM со словом запроса. */ + bool requested = *(volatile uint32_t *)(uintptr_t)CAN_BOOT_REQUEST_ADDRESS == CAN_BOOT_REQUEST_MAGIC; *(volatile uint32_t *)(uintptr_t)CAN_BOOT_REQUEST_ADDRESS = 0U; /* Потребляет сохранённый запрос CANB до настройки периферии. */ + HAL_Init(); device_sysclock_config(); uart_init(); can_started = fdcan_init(); /* Сохраняет исходную последовательность clock/GPIO/UART/FDCAN и доступность UART при отказе CAN. */ + if (!requested && pcan_boot_stm32g474_vectors_valid(CAN_BOOT_APP_SIZE)) { /* Сохраняет исходное десятисекундное окно входа в обновление. */ + uint32_t started = HAL_GetTick(); while ((uint32_t)(HAL_GetTick() - started) < 10000U) { service_interfaces(); if (updater.boot.state != PCAN_BOOT_STATE_IDLE || uart_boot.state != RS485_BOOT_IDLE) { requested = true; break; } } /* Обслуживает UART/CAN с учётом переполнения tick, без входа в обновление по одному discovery. */ + if (!requested) jump_app(); /* Передаёт управление установленному приложению после окна ожидания. */ + } /* Завершает обычную политику запуска без постоянного manifest. */ + for (;;) service_interfaces(); /* Остаётся доступным для адресного обновления и восстановления через UART. */ +} /* Завершает общий boot main STM32G474VET6. */ diff --git a/c/protocan-boot/ports/stm32g474/boot_profile.h b/c/protocan-boot/ports/stm32g474/boot_profile.h new file mode 100644 index 0000000..319f7cf --- /dev/null +++ b/c/protocan-boot/ports/stm32g474/boot_profile.h @@ -0,0 +1,17 @@ +#ifndef PCAN_BOOT_G474_PROFILE_H /* Согласует приложение CANdle и самостоятельный CAN/UART-загрузчик. */ +#define PCAN_BOOT_G474_PROFILE_H /* Исключает повторное определение общей аппаратной конфигурации. */ +#include /* Объявляет булевы признаки расширенного кадра и запроса обновления. */ +#include /* Объявляет wire-типы CAN ID и DLC публичного приложения. */ +#define CAN_BOOT_APP_ADDRESS 0x08008000UL /* Исходный CANdle G474 резервирует 32 КиБ Flash под загрузчик. */ +#define CAN_BOOT_FLASH_END 0x08080000UL /* Верхняя исключённая граница 512 КиБ Flash STM32G474VET6. */ +#define CAN_BOOT_APP_SIZE (CAN_BOOT_FLASH_END - CAN_BOOT_APP_ADDRESS) /* Единственный слот приложения содержит 480 КиБ. */ +#define CAN_BOOT_REQUEST_ADDRESS 0x20013FFCUL /* Исходный запрос CANB хранится в последнем слове используемых 80 КиБ SRAM; linker исключает последние восемь байт. */ +#define CAN_BOOT_REQUEST_MAGIC 0x43414E42UL /* Сохраняет совместимый маркер CANB для входа из работающего приложения. */ +#define CAN_BOOT_DEVICE_TYPE 7U /* Сохраняет исходный тип устройства CANdle G474 в ProtoCAN. */ +#define CAN_BOOT_DEVICE_ID 15U /* Сохраняет исходный адрес устройства CANdle G474. */ +void can_boot_observe(uint32_t can_id, bool extended, uint8_t dlc); /* Отмечает адресный ENTER_BOOT из общего CAN-диспетчера приложения. */ +bool can_boot_requested(void); /* Возвращает отложенный запрос, чтобы main приложения выполнил reset из безопасного контекста. */ +void can_boot_enter(void); /* Сохраняет одноразовый запрос в SRAM и вызывает системный reset. */ +void can_boot_uart_init(void); /* Настраивает исходный USART1 PA9/PA10, 512000 бод, и приём через IRQ. */ +void can_boot_uart_poll(void); /* Разбирает один байт PING/BEGIN SETGUI v1 в работающем приложении. */ +#endif /* Завершает профиль и совместимый API входа CANdle G474. */ diff --git a/c/protocan-boot/ports/stm32g474/boot_startup.c b/c/protocan-boot/ports/stm32g474/boot_startup.c new file mode 100644 index 0000000..7204d9b --- /dev/null +++ b/c/protocan-boot/ports/stm32g474/boot_startup.c @@ -0,0 +1,30 @@ +#include "boot_profile.h" /* Использует общий адресный профиль CANdle G474 и исключённое слово SRAM-запроса. */ +#include "stm32g4xx.h" /* Получает CMSIS регистры и SystemInit выбранного STM32G474. */ +#include "stm32g4xx_hal.h" /* Связывает SysTick самостоятельного загрузчика с HAL_GetTick. */ +extern uint32_t __StackTop, __data_start, __data_end, __data_source, __bss_start, __bss_end; /* GNU linker задаёт границы runtime-инициализации и вершину отдельного стека. */ +extern int main(void); /* Передаёт управление общему boot main после инициализации C runtime. */ +void SysTick_Handler(void); /* Объявляет публичное имя обработчика до определения, как требует standalone startup. */ +__attribute__((noreturn)) void Reset_Handler(void); /* Объявляет безвозвратную аппаратную точку входа GNU/Keil. */ +static __attribute__((noreturn)) void fault(void) { for (;;) {} } /* Не выполняет произвольный переход при необработанном IRQ либо исключении загрузчика. */ +void SysTick_Handler(void) { HAL_IncTick(); } /* Обеспечивает реальные миллисекундные тайм-ауты UART/FDCAN/HAL. */ +__attribute__((noreturn)) void Reset_Handler(void) /* Сохраняет совместимость исходного startup с Arm Compiler 6 и GNU toolchain. */ +{ /* На Arm Compiler runtime и scatter-loading предоставляет библиотечная функция __main. */ +#if defined(__ARMCC_VERSION) /* Выбирает штатный C runtime Keil, не дублируя ZI/RW инициализацию. */ + extern void __main(void); SystemInit(); __main(); /* Настраивает базовый MCU и запускает runtime перед main. */ +#else /* GNU-вариант использует символы исходного linker script CANdle. */ + uint32_t *source = &__data_source, *destination = &__data_start; /* Сохраняет Flash-источник и SRAM-назначение инициализированных данных. */ + while (destination < &__data_end) *destination++ = *source++; /* Копирует только объявленную секцию data, не затрагивая исключённый SRAM-маркер. */ + for (destination = &__bss_start; destination < &__bss_end; ++destination) *destination = 0U; /* Обнуляет ZI только внутри RAM-региона, согласованного с linker. */ + SystemInit(); (void)main(); /* Запускает базовую конфигурацию MCU и общую загрузочную программу. */ +#endif /* Завершает выбор C runtime для двух поддерживаемых toolchain. */ + for (;;) {} /* Не допускает возврат из main в несуществующий вызывающий код reset. */ +} /* Завершает Reset_Handler самостоятельного загрузчика. */ +typedef void (*vector_t)(void); /* Описывает Thumb-обработчик аппаратного исключения Cortex-M4. */ +static __attribute__((used, section(".vectors"))) const vector_t vectors[118] = { /* Сохраняет таблицу из 118 записей в начале 32-КиБ загрузочной Flash без ненужного внешнего символа. */ +#if defined(__ARMCC_VERSION) /* Keil получает fixed MSP, совпадающий с ARM_LIB_STACK в общем scatter script. */ + (vector_t)0x20013FF8UL, Reset_Handler, fault, fault, /* Резервирует последние восемь байт SRAM, чтобы пролог main не уничтожил маркер CANB до чтения. */ +#else /* GNU linker вычисляет вершину стека по RAM_SIZE, также уменьшенному на восемь байт. */ + (vector_t)&__StackTop, Reset_Handler, fault, fault, /* Использует linker-определение без жёсткого адреса для GNU сборки. */ +#endif /* Завершает выбор совместимого initial MSP. */ + [4 ... 14] = fault, [15] = SysTick_Handler, [16 ... 117] = fault /* Разрешает только SysTick; загрузочные UART/FDCAN обслуживаются опросом. */ +}; /* Завершает извлечённую таблицу векторов CANdle G474. */ diff --git a/c/protocan-boot/ports/stm32g474/pcan_boot_stm32g474.c b/c/protocan-boot/ports/stm32g474/pcan_boot_stm32g474.c new file mode 100644 index 0000000..6c61357 --- /dev/null +++ b/c/protocan-boot/ports/stm32g474/pcan_boot_stm32g474.c @@ -0,0 +1,104 @@ +#include "pcan_boot_stm32g474.h" /* Подключает семейные HAL API, карту памяти и состояние общего автомата. */ +#include /* Предоставляет безопасную упаковку doubleword и коротких CAN-ответов. */ +static const uint32_t dlc_values[9] = {FDCAN_DLC_BYTES_0, FDCAN_DLC_BYTES_1, FDCAN_DLC_BYTES_2, FDCAN_DLC_BYTES_3, FDCAN_DLC_BYTES_4, FDCAN_DLC_BYTES_5, FDCAN_DLC_BYTES_6, FDCAN_DLC_BYTES_7, FDCAN_DLC_BYTES_8}; /* Изолирует различное кодирование DLC в старых и новых версиях HAL, не предполагая сдвиг 0 либо 16. */ +static bool geometry(uint32_t *page_size, uint32_t *bank_size) /* Не позволяет неподдерживаемой геометрии изменить загрузочную область. */ +{ /* Профиль предназначен только для STM32G474VET6 с 512 КиБ Flash. */ + bool dual = (FLASH->OPTR & FLASH_OPTR_DBANK) != 0U; /* DBANK выбирает две страницы по 2 КиБ либо один банк со страницами по 4 КиБ. */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); /* Гарантирует доступность MEMRMP перед проверкой bank swap даже вне board-функции CANdle. */ + if (*(const uint16_t *)(uintptr_t)FLASHSIZE_BASE != 512U || (FLASH->OPTR & FLASH_OPTR_BFB2) != 0U || (SYSCFG->MEMRMP & SYSCFG_MEMRMP_FB_MODE) != 0U) { return false; } /* Требует известную физическую ёмкость и прямое соответствие логических адресов физическим банкам. */ + *page_size = dual ? 2048U : 4096U; *bank_size = dual ? 262144UL : 524288UL; /* RM0440: страницы 2/4 КиБ и банки 256/512 КиБ соответственно режиму DBANK. */ + return true; /* Обе исходные конфигурации DBANK поддерживаются без изменения Option Bytes. */ +} /* Завершает проверку геометрии перед erase и program. */ +bool pcan_boot_stm32g474_vectors_valid(uint32_t size) /* Проверяет только допустимость таблицы векторов. */ +{ /* Используемая SRAM 80 КиБ соответствует исходному linker CANdle G474. */ + const uint32_t *vectors = (const uint32_t *)(uintptr_t)CAN_BOOT_APP_ADDRESS; uint32_t sp, pc; /* Два первых слова содержат MSP и Thumb reset handler. */ + if (size < 8U || size > CAN_BOOT_APP_SIZE) { return false; } sp = vectors[0]; pc = vectors[1]; /* Проверяет размер до чтения аппаратно отображённой Flash. */ + return sp > 0x20000000UL && sp <= 0x20014000UL && (sp & 7U) == 0U && (pc & 1U) != 0U && (pc & ~1UL) >= CAN_BOOT_APP_ADDRESS && (pc & ~1UL) < CAN_BOOT_APP_ADDRESS + size; /* Не принимает стек вне SRAM, невыровненный MSP или reset vector за полезным образом. */ +} /* Завершает структурную проверку без чтения остальной Flash. */ +bool pcan_boot_stm32g474_image_valid(uint32_t size, uint32_t crc) /* Подтверждает реальную Flash перед VERIFY, COMMIT или UART END. */ +{ /* Полезная длина не включает дополнение FF последнего doubleword. */ + return pcan_boot_stm32g474_vectors_valid(size) && pcan_boot_crc32_update(0U, (const uint8_t *)(uintptr_t)CAN_BOOT_APP_ADDRESS, size) == crc; /* Использует общий полином ProtoCAN вместо локальной копии CAN-CRC. */ +} /* Завершает независимую проверку сохранённого образа. */ +bool pcan_boot_stm32g474_erase(uint32_t size) /* Стирает страницы 480-КиБ single-slot области без затрагивания загрузчика. */ +{ /* Bank swap отвергается, а настройки Option Bytes остаются владельцу устройства. */ + uint32_t page_size, bank_size, address, end; bool ok = true; /* Сохраняет аппаратную геометрию и результат до восстановления LOCK. */ + if (size < 8U || size > CAN_BOOT_APP_SIZE || !geometry(&page_size, &bank_size)) { return false; } /* Проверяет полезную длину и физическую карту до разблокировки Flash. */ + end = CAN_BOOT_APP_ADDRESS + ((size + page_size - 1U) & ~(page_size - 1U)); /* Округляет конец вверх к странице текущего DBANK-режима. */ + if (end > CAN_BOOT_FLASH_END || HAL_FLASH_Unlock() != HAL_OK) { return false; } /* Не стирает Flash за физической ёмкостью профиля. */ + for (address = CAN_BOOT_APP_ADDRESS; address < end; address += page_size) { /* Обходит только страницы, покрывающие полезный образ. */ + FLASH_EraseInitTypeDef erase = {0}; uint32_t error = 0U, offset = address - FLASH_BASE; /* Определяет физическое положение страницы относительно начала Flash. */ + erase.TypeErase = FLASH_TYPEERASE_PAGES; erase.Banks = offset >= bank_size ? FLASH_BANK_2 : FLASH_BANK_1; /* Разрешает адресовать второй банк только в поддерживаемой dual-bank карте. */ + erase.Page = (offset % bank_size) / page_size; erase.NbPages = 1U; /* Номер страницы считается отдельно внутри физического банка. */ + if (HAL_FLASHEx_Erase(&erase, &error) != HAL_OK) { ok = false; break; } /* Прерывает стирание при тайм-ауте, защите либо аппаратной ошибке страницы. */ + } /* Завершает ограниченный обход страниц. */ + if (HAL_FLASH_Lock() != HAL_OK) { ok = false; } return ok; /* Обязательно восстанавливает блокировку и не подтверждает отказ LOCK. */ +} /* Завершает стирание с поддержкой single/dual bank STM32G474VE. */ +bool pcan_boot_stm32g474_write(uint32_t image_size, uint32_t offset, const uint8_t *data, uint16_t length) /* Записывает выровненные doubleword без повторного программирования ECC-слова. */ +{ /* Один writer используется обоими загрузочными транспортами. */ + uint32_t page_size, bank_size, done = 0U; bool ok = true; /* Хранит проверенную геометрию и фактическое смещение полезных байтов. */ + if (image_size < 8U || image_size > CAN_BOOT_APP_SIZE || data == NULL || length == 0U || offset > image_size || length > image_size - offset || (offset & 7U) != 0U || !geometry(&page_size, &bank_size)) { return false; } /* Проверяет адреса вычитанием, исключая переполнение и неизвестную физическую геометрию. */ + if ((length & 7U) != 0U && offset + length != image_size) { return false; } /* Неполное 64-битное слово допускается только в конце полезного образа. */ + if (HAL_FLASH_Unlock() != HAL_OK) { return false; } /* Не начинает запись при отказе аппаратной разблокировки. */ + while (done < length) { /* Разбивает UART/CAN payload на аппаратные doubleword по восемь байт. */ + uint64_t value = UINT64_MAX; uint32_t count = length - done, address = CAN_BOOT_APP_ADDRESS + offset + done; /* Значение FF сохраняет незаданные хвостовые октеты стёртыми. */ + if (count > 8U) { count = 8U; } (void)memcpy(&value, data + done, count); /* Не читает за полезной длиной неполного последнего блока. */ + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, value) != HAL_OK || memcmp((const void *)(uintptr_t)address, &value, 8U) != 0) { ok = false; break; } /* HAL G4 синхронизирует Flash cache, а порт проверяет аппаратную запись и весь doubleword readback. */ + done += count; /* Продвигается только на число полезных октетов, не включая FF в CRC. */ + } /* Завершает запись ограниченного payload. */ + if (HAL_FLASH_Lock() != HAL_OK) { ok = false; } return ok; /* Восстанавливает аппаратную блокировку после успеха и отказов записи. */ +} /* Завершает защищённое программирование G474. */ +static bool send_frame(void *user, uint32_t id, const pcan_boot_byte_t *data, pcan_boot_byte_t length) /* Подтверждает физическую передачу FDCAN, включая ответ перед reset. */ +{ /* Порт владеет выделенным FDCAN1 без конкурирующих отправителей или TX IRQ. */ + pcan_boot_stm32_t *port = user; FDCAN_HandleTypeDef *can = port->can; FDCAN_TxHeaderTypeDef header = {0}; /* Получает handle и обнуляет все поля аппаратного заголовка. */ + uint8_t bytes[8] = {0}; uint32_t started = HAL_GetTick(), buffer; /* Не позволяет HAL читать за коротким служебным payload. */ + if (length > 8U || id > 0x1FFFFFFFUL || (length != 0U && data == NULL)) { return false; } if (length != 0U) (void)memcpy(bytes, data, length); /* Проверяет внешний размер до копирования в полный classic CAN-буфер. */ + while (HAL_FDCAN_GetTxFifoFreeLevel(can) == 0U) if ((uint32_t)(HAL_GetTick() - started) >= 100U) { return false; } /* Ограничивает ожидание места в TX FIFO ста миллисекундами. */ + header.Identifier = id; header.IdType = FDCAN_EXTENDED_ID; header.TxFrameType = FDCAN_DATA_FRAME; header.DataLength = dlc_values[length]; /* Формирует расширенный адресный кадр с совместимым кодированием DLC текущего HAL. */ + header.ErrorStateIndicator = FDCAN_ESI_ACTIVE; header.BitRateSwitch = FDCAN_BRS_OFF; header.FDFormat = FDCAN_CLASSIC_CAN; header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; /* ProtoCAN Boot использует classic CAN без BRS и не требует отдельного TX Event FIFO. */ + if (HAL_FDCAN_AddMessageToTxFifoQ(can, &header, bytes) != HAL_OK) { return false; } buffer = HAL_FDCAN_GetLatestTxFifoQRequestBuffer(can); /* Запоминает bitmask именно поставленного в очередь TX-буфера. */ + while (HAL_FDCAN_IsTxBufferMessagePending(can, buffer) != 0U) if ((uint32_t)(HAL_GetTick() - started) >= 100U) { (void)HAL_FDCAN_AbortTxRequest(can, buffer); return false; } /* Отменяет неподтверждённый TX вместо перезапуска MCU при отсутствии ACK шины. */ + return buffer != 0U && (can->Instance->TXBTO & buffer) != 0U; /* Отличает завершённую передачу от abort по аппаратному флагу transmission occurred. */ +} /* Завершает надёжную отправку ответа FDCAN. */ +static bool erase_slot(void *user, pcan_boot_byte_t slot) /* Подключает страницу Flash к единственному логическому слоту A. */ +{ /* Разрешение reset сбрасывается до изменения Flash. */ + pcan_boot_stm32_t *port = user; bool ok; if (slot != 0U) { return false; } port->ready = false; port->written = 0U; /* Не допускает A/B-адресацию и прежний COMMIT после начала новой записи. */ + (void)pcan_boot_report_busy(&port->boot, PCAN_BOOT_CMD_ERASE, HAL_GetTick()); ok = pcan_boot_stm32g474_erase(port->boot.manifest.image_size); /* Предупреждает клиента перед синхронным стиранием выбранных страниц. */ + if (ok) { (void)pcan_boot_report_busy(&port->boot, PCAN_BOOT_CMD_ERASE, HAL_GetTick()); } return ok; /* Продлевает сессию после завершения длительной Flash-операции. */ +} /* Завершает callback стирания G474. */ +static bool write_slot(void *user, pcan_boot_byte_t slot, uint32_t offset, const pcan_boot_byte_t *data, pcan_boot_byte_t length) /* Подключает защищённый writer к общему CAN-автомату. */ +{ /* Общий автомат проверяет номера восьмибайтовых блоков, порт повторно проверяет фактическое смещение. */ + pcan_boot_stm32_t *port = user; if (slot != 0U || offset != port->written || length > 8U || !pcan_boot_stm32g474_write(port->boot.manifest.image_size, offset, data, length)) { return false; } /* Не подтверждает неправильный слот, порядок или отказ Flash. */ + port->written += length; return true; /* Считает только полностью записанные полезные октеты. */ +} /* Завершает callback записи G474. */ +static pcan_boot_status_t verify(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *manifest) /* Отличает неверный образ от ошибки readback CRC. */ +{ /* Сохраняет точные статусы текущего общего API. */ + pcan_boot_stm32_t *port = user; if (slot != 0U || manifest == NULL || port->written != manifest->image_size || !pcan_boot_stm32g474_vectors_valid(manifest->image_size)) return PCAN_BOOT_STATUS_INVALID_SIZE; /* Не принимает неполную запись или reset handler вне полезного образа. */ + return pcan_boot_stm32g474_image_valid(manifest->image_size, manifest->image_crc32) ? PCAN_BOOT_STATUS_OK : PCAN_BOOT_STATUS_CRC_ERROR; /* Перечитывает реальную Flash вместо доверия CRC потока. */ +} /* Завершает VERIFY G474. */ +static bool commit(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *manifest) { pcan_boot_stm32_t *port = user; port->ready = verify(user, slot, manifest) == PCAN_BOOT_STATUS_OK; return port->ready; } /* Активирует проверенный образ только в RAM, без имитации постоянных A/B-метаданных. */ +static bool can_reboot(void *user) { pcan_boot_stm32_t *port = user; return port->ready && port->boot.state == PCAN_BOOT_STATE_COMMITTED; } /* Разрешает протокольный reset только после VERIFY и COMMIT. */ +static void reboot(void *user) { if (can_reboot(user)) NVIC_SystemReset(); } /* Общий автомат вызывает reset только после подтверждённого TX ответа. */ +bool pcan_boot_stm32g474_init(pcan_boot_stm32_t *port, FDCAN_HandleTypeDef *can, const pcan_boot_config_t *config) /* Настраивает current ProtoCAN Boot v1 поверх подготовленного FDCAN1. */ +{ /* GPIO, kernel clock 48 МГц и HAL_FDCAN_Init остаются в board-проекте. */ + pcan_boot_config_t single; pcan_boot_port_t callbacks = {0}; FDCAN_FilterTypeDef filter = {0}; uint32_t page_size, bank_size; /* Подготавливает полностью определённые структуры текущего API и HAL. */ + if (port == NULL || can == NULL || config == NULL || can->Instance != FDCAN1 || can->Init.ExtFiltersNbr < 2U || !geometry(&page_size, &bank_size)) { return false; } /* Не запускает порт без двух выделенных extended-фильтров или поддерживаемой Flash-геометрии. */ + single = *config; single.active_slot = 0U; single.slot_count = 1U; single.max_image_size = CAN_BOOT_APP_SIZE; /* Принудительно сохраняет исходный single-slot профиль 480 КиБ. */ + callbacks.send = send_frame; callbacks.erase_slot = erase_slot; callbacks.write_slot = write_slot; callbacks.verify_status = verify; callbacks.set_pending_slot = commit; callbacks.can_reboot = can_reboot; callbacks.reboot = reboot; /* Подключает Flash, readback и согласованную политику reset к единственному общему автомату. */ + (void)memset(port, 0, sizeof(*port)); port->can = can; if (!pcan_boot_init(&port->boot, &single, &callbacks, port)) { port->can = NULL; return false; } /* Делает неуспешно настроенный порт безопасным для последующего poll. */ + filter.IdType = FDCAN_EXTENDED_ID; filter.FilterIndex = 0U; filter.FilterType = FDCAN_FILTER_MASK; filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; /* Первый аппаратный фильтр обслуживает все сообщения собственного адреса. */ + filter.FilterID1 = pcan_boot_make_id(0U, 0U, single.device_type, single.device_id, 0U, 0U); filter.FilterID2 = 0x0FF00000UL; /* Не маскирует приоритет; проверяет только Route/Type/ID. */ + if (HAL_FDCAN_ConfigFilter(can, &filter) != HAL_OK) { port->can = NULL; return false; } /* Не использует CAN с неподтверждённым адресным фильтром. */ + filter.FilterIndex = 1U; filter.FilterID1 = pcan_boot_make_id(0U, 0U, 7U, 15U, PCAN_BOOT_MSG_DISCOVERY, 0U); filter.FilterID2 = 0x0FFFFFFFUL; /* Второй фильтр допускает только штатный broadcast discovery, исключая broadcast-запись. */ + if (HAL_FDCAN_ConfigFilter(can, &filter) != HAL_OK || HAL_FDCAN_ConfigGlobalFilter(can, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE) != HAL_OK || HAL_FDCAN_Start(can) != HAL_OK) { port->can = NULL; return false; } /* Отвергает прочие standard/extended/remote кадры и проверяет аппаратный запуск. */ + return true; /* Flash-профиль, оба фильтра и FDCAN готовы к общему автомату. */ +} /* Завершает инициализацию reusable G474-порта. */ +void pcan_boot_stm32g474_poll(pcan_boot_stm32_t *port) /* Обслуживает транспорт и таймеры ядра из основного цикла. */ +{ /* Не вызывается из IRQ из-за синхронных операций Flash. */ + FDCAN_HandleTypeDef *can; uint32_t count; if (port == NULL || port->can == NULL) { return; } can = port->can; pcan_boot_poll(&port->boot, HAL_GetTick()); /* Проверяет состояние до доступа к handle и обновляет часы без входящего кадра. */ + for (count = 0U; count < 3U && HAL_FDCAN_GetRxFifoFillLevel(can, FDCAN_RX_FIFO0) != 0U; ++count) { /* Ограничивает время обработки нагруженного CAN на одну итерацию main. */ + FDCAN_RxHeaderTypeDef header; uint8_t data[64], length; /* Защищает память даже при ошибочно принятом CAN FD payload до 64 байт. */ + if (HAL_FDCAN_GetRxMessage(can, FDCAN_RX_FIFO0, &header, data) != HAL_OK) break; /* Не декодирует неуспешно принятый аппаратный кадр. */ + for (length = 0U; length <= 8U && header.DataLength != dlc_values[length]; ++length) {} /* Декодирует только classic DLC через значения текущего HAL. */ + if (length <= 8U && header.IdType == FDCAN_EXTENDED_ID && header.RxFrameType == FDCAN_DATA_FRAME && header.FDFormat == FDCAN_CLASSIC_CAN && header.Identifier <= 0x1FFFFFFFUL) { pcan_boot_poll(&port->boot, HAL_GetTick()); (void)pcan_boot_process(&port->boot, header.Identifier, data, length); } /* Проверяет внешний формат и передаёт полный актуальный ProtoCAN flow единому ядру. */ + } /* Завершает ограниченный пакет RX-кадров. */ +} /* Завершает обслуживание reusable G474-порта. */ diff --git a/c/protocan-boot/ports/stm32g474/pcan_boot_stm32g474.h b/c/protocan-boot/ports/stm32g474/pcan_boot_stm32g474.h new file mode 100644 index 0000000..0824862 --- /dev/null +++ b/c/protocan-boot/ports/stm32g474/pcan_boot_stm32g474.h @@ -0,0 +1,12 @@ +#ifndef PCAN_BOOT_STM32G474_H /* Защищает HAL FDCAN-порт от повторного включения. */ +#define PCAN_BOOT_STM32G474_H /* Обозначает активный интерфейс профиля STM32G474VET6. */ +#include "stm32g4xx_hal.h" /* Подключает реальные типы FDCAN/Flash STM32CubeG4. */ +#include "boot_profile.h" /* Получает аппаратные границы и адрес CAN исходного CANdle G474. */ +#include "../stm32-common/pcan_boot_stm32.h" /* Использует общее состояние single-slot порта и актуальный API ядра. */ +bool pcan_boot_stm32g474_init(pcan_boot_stm32_t *port, FDCAN_HandleTypeDef *can, const pcan_boot_config_t *config); /* Подключает готовый FDCAN1 с двумя extended-фильтрами, запускает адресный ProtoCAN Boot v1. */ +void pcan_boot_stm32g474_poll(pcan_boot_stm32_t *port); /* Обслуживает ограниченный пакет кадров и таймеры ядра из основного цикла. */ +bool pcan_boot_stm32g474_erase(uint32_t size); /* Стирает страницы приложения при поддерживаемой геометрии 512 КиБ и отключённой перестановке банков. */ +bool pcan_boot_stm32g474_write(uint32_t image_size, uint32_t offset, const uint8_t *data, uint16_t length); /* Позволяет CAN и UART использовать один doubleword writer с проверкой полезной длины. */ +bool pcan_boot_stm32g474_image_valid(uint32_t size, uint32_t crc); /* Проверяет readback CRC, MSP и reset vector внутри фактической длины образа. */ +bool pcan_boot_stm32g474_vectors_valid(uint32_t size); /* Проверяет только векторы; не доказывает целостность после внешнего reset. */ +#endif /* Завершает интерфейс G474 single-slot порта. */ diff --git a/c/protocan-boot/ports/tms320f2812/README.md b/c/protocan-boot/ports/tms320f2812/README.md new file mode 100644 index 0000000..5f59dc9 --- /dev/null +++ b/c/protocan-boot/ports/tms320f2812/README.md @@ -0,0 +1,15 @@ +# F2812 / AM29LV800BT + +Самостоятельный проект, карта NOR, параметры CAN, установка и ограничения +описаны в [общей инструкции CCS](../../projects/README.md). + +- `boot2812.h` — физические CPU word-адреса и отдельная совместимость F2812; +- `nor_flash.c` — x16 AMD driver с ID, ограниченными program/sector erase, + DQ7/DQ5 polling, readback и BUSY; +- `boot_store.c` — упаковка октетов, проверка всей SCI8-таблицы, CRC32, + публикация manifest последними magic-словами, проверенная загрузка RAM; +- `projects/ccs/f2812/board.c` — подтверждённые линии CPLD и XINTF ПМ67; +- `projects/ccs/f2812/main.c` — независимые eCAN/IRQ/очередь/main F2812. + +Протокол и CRC повторно используются из `src/pcan_boot.c`. EEPROM отсутствует; +код F28335 и его A/B-журнал не подключаются к этому проекту. diff --git a/c/protocan-boot/ports/tms320f2812/boot2812.h b/c/protocan-boot/ports/tms320f2812/boot2812.h new file mode 100644 index 0000000..5025d04 --- /dev/null +++ b/c/protocan-boot/ports/tms320f2812/boot2812.h @@ -0,0 +1,24 @@ +#ifndef BOOT2812_H /* Исключает повторное объявление профиля NOR-загрузчика F2812. */ +#define BOOT2812_H /* Отделяет основной контроллер ПМ67 от периферийного F28335. */ +#include "../../include/pcan_boot.h" /* Использует существующий ProtoCAN codec и представление октетов C28x. */ +#define BOOT2812_NOR_BASE 0x100000UL /* CPU word-адрес AM29LV800BT взят из START_ADR_FLASH действующего flash_tools.h платы. */ +#define BOOT2812_IMAGE_WORD 0x160000UL /* Новый CAN-образ занимает три полных верхних обычных сектора, выше старого образа и данных FPGA. */ +#define BOOT2812_IMAGE_BYTES 0x30000UL /* Три сектора по 0x8000 слов дают 196608 октетов полезного SCI8. */ +#define BOOT2812_META_WORD 0x17E000UL /* Последний top-boot сектор начинается после областей 16K/4K/4K слов и содержит 8192 слова. */ +#define BOOT2812_PRODUCT 0x2812U /* Отдельный Product Type запрещает запись образа F28335 в основной контроллер F2812. */ +#define BOOT2812_DEVICE_TYPE 3U /* Тип загрузчика остаётся в том же адресном классе ProtoCAN, что F28335. */ +#define BOOT2812_DEVICE_ID 6U /* Отдельный ID 6 исключает совпадение с существующим F28335 на адресе 3/7. */ +#define BOOT2812_RECOVERY_MS 3000UL /* После reset загрузчик три секунды принимает ENTER_BOOT до автоматического запуска сохранённого образа. */ +unsigned long Boot2812_Now(void); /* Возвращает монотонные миллисекунды Timer1 для CAN и ограниченных ожиданий NOR. */ +void Boot2812_Busy(void); /* Во время долгого стирания сообщает BUSY через общий codec и обслуживает аппаратный TX ACK. */ +void Boot2812_BoardInit(void); /* Настраивает действующие линии CPLD и XINTF платы ПМ67. */ +bool Boot2812_NorIdentify(void); /* До первого erase требует AMD manufacturer 0001 и top-boot device 22DA. */ +unsigned int Boot2812_NorRead(unsigned long word); /* Читает одно 16-битное слово по CPU-адресу внешней NOR. */ +bool Boot2812_NorProgram(unsigned long word, unsigned int value); /* Программирует только зарезервированные CAN-области и проверяет прочитанный результат. */ +bool Boot2812_NorErase(unsigned long word); /* Принимает только начала трёх секторов образа и одного сектора метаданных. */ +bool Boot2812_Erase(void *user, pcan_boot_byte_t slot); /* Удаляет публикацию до стирания единственного CAN-слота. */ +bool Boot2812_Write(void *user, pcan_boot_byte_t slot, uint32_t offset, const pcan_boot_byte_t *data, pcan_boot_byte_t length); /* Сохраняет октеты ProtoCAN в x16 NOR младшим байтом вперёд. */ +pcan_boot_status_t Boot2812_Verify(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *image); /* Проверяет CRC прочитанной NOR и все CPU-адреса SCI8 до COMMIT. */ +bool Boot2812_Commit(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *image); /* Публикует manifest только после повторной проверки всей внешней Flash. */ +bool Boot2812_Load(uint32_t *entry); /* Читает действующий manifest, проверяет образ и переносит только разрешённую RAM. */ +#endif /* Завершает интерфейс самостоятельного NOR-порта F2812. */ diff --git a/c/protocan-boot/ports/tms320f2812/boot_store.c b/c/protocan-boot/ports/tms320f2812/boot_store.c new file mode 100644 index 0000000..8d9f701 --- /dev/null +++ b/c/protocan-boot/ports/tms320f2812/boot_store.c @@ -0,0 +1,105 @@ +#include "boot2812.h" /* Использует отдельные адреса и совместимость внешней NOR F2812. */ +static unsigned int octet(uint32_t offset) /* Читает октет файла SCI8 из x16 NOR, где младший октет хранится первым. */ +{ /* Поток CAN остаётся независимым от sizeof(char) на C28x. */ + unsigned int word = Boot2812_NorRead(BOOT2812_IMAGE_WORD + offset / 2UL); /* Преобразует смещение в октетах в CPU word-адрес слота. */ + return (offset & 1UL) ? word >> 8 : word & 255U; /* Передаёт младшие восемь бит октета без знакового расширения. */ +} /* Все дальнейшие поля таблицы собираются из того же порядка октетов. */ +static unsigned int u16(uint32_t offset) /* Восстанавливает слово TI boot table в little endian. */ +{ /* Вызывается только после проверки достаточной длины соответствующего поля. */ + return octet(offset) | (octet(offset + 1UL) << 8); /* Два октета соответствуют одному слову C28x. */ +} /* Завершает чтение длины секции или данных программы. */ +static uint32_t address_at(uint32_t offset) /* Адрес TI SCI8 содержит старшее 16-битное слово перед младшим. */ +{ /* Этот порядок отличается от обычного u32 little endian метаданных ProtoCAN. */ + return ((uint32_t)u16(offset) << 16) | u16(offset + 2UL); /* Внутри каждого слова по-прежнему сохраняется little endian. */ +} /* Возвращает CPU-адрес, измеряемый в словах. */ +static bool allowed(uint32_t first, uint32_t end) /* Разрешает только реальную RAM приложения и исключает RAM работающего загрузчика. */ +{ /* Новое приложение не должно загружать инициализированные секции в L1 или RAM InitFlash до перехода в runtime. */ + return end > first && ((first >= 0x8000UL && end <= 0x8F00UL) || (first >= 0x3F8000UL && end <= 0x3FA000UL) || (first >= 0x80000UL && end <= 0x100000UL)); /* L0 до ramfuncs, полный H0 и внешняя SRAM зоны 2; периферия, NOR, стек и внутренние Flash запрещены. */ +} /* Проверки входа и всех секций выполняются до первой записи приложения в RAM. */ +static bool table(uint32_t size, bool copy, uint32_t *entry) /* Проверяет целиком SCI8 и при повторном проходе переносит данные в RAM. */ +{ /* Устойчивость загрузчика не зависит от адресов, заявленных принимаемым файлом. */ + uint32_t starts[64], ends[64], offset = 22UL, address, end; /* Лимит 64 секции ограничивает стек и число сравнений перекрытий. */ + unsigned int sections = 0U, count, i; bool entry_loaded = false; /* Требует, чтобы точка входа реально находилась среди загружаемых слов. */ + if (size < 24UL || (size & 1UL) || u16(0UL) != 0x08AAU) return false; /* Ключ SCI8 AA08, чётный размер и терминатор обязательны. */ + *entry = address_at(18UL); /* После ключа и восьми резервных слов находится CPU word-адрес C runtime. */ + while (offset + 2UL <= size) { /* Поле count читается только при наличии обоих октетов. */ + count = u16(offset); offset += 2UL; /* Размер секции выражен в 16-битных словах, а не октетах файла. */ + if (!count) return offset == size && entry_loaded; /* Запрещает хвост, незавершённую таблицу и entry вне payload. */ + if (sections == 64U || size - offset < 4UL) return false; /* Не допускает переполнения ограниченных массивов или усечённого адреса. */ + address = address_at(offset); offset += 4UL; end = address + count; /* Восстанавливает исключающую верхнюю границу CPU-диапазона секции. */ + if (!allowed(address, end) || (uint32_t)count * 2UL > size - offset) return false; /* Проверяет адреса и полный payload до обращения к RAM назначения. */ + for (i = 0; i < sections; ++i) if (address < ends[i] && starts[i] < end) return false; /* Даже правильно переданная CRC не разрешает две секции поверх одного слова. */ + starts[sections] = address; ends[sections++] = end; /* Сохраняет уже проверенный диапазон для следующих секций. */ + if (*entry >= address && *entry < end) entry_loaded = true; /* Подтверждает наличие исполняемого слова по адресу входа. */ + if (copy) { /* Этот проход выполняется только после полной read-only проверки всего образа. */ + for (i = 0; i < count; ++i) { /* Переносит ровно заявленные и предварительно проверенные слова секции. */ +#if defined(BOOT2812_HOST) /* Аппаратная модель проверяет тот же диапазон без записи по адресам процесса ПК. */ + extern void NorModel_LoadWord(uint32_t target, unsigned int value); /* Модель сохраняет каждое слово переноса для независимой проверки. */ + NorModel_LoadWord(address + i, u16(offset + (uint32_t)i * 2UL)); /* Подменяет только шину RAM назначения. */ +#else /* На F2812 CPU-адреса уже выражены в 16-битных словах. */ + *(volatile unsigned int *)(address + i) = u16(offset + (uint32_t)i * 2UL); /* Записывает секцию только в разрешённую RAM приложения. */ +#endif /* Завершает аппаратную запись либо её host-модель. */ + } /* Завершает перенос текущей секции. */ + } /* После проверочного прохода RAM остаётся нетронутой. */ + offset += (uint32_t)count * 2UL; /* Пропускает полезные октеты до следующего count. */ + } /* Исчерпание файла без терминатора означает неполный образ. */ + return false; /* Не запускает незавершённую таблицу. */ +} /* Образ с ошибкой не публикуется как запускаемый. */ +bool Boot2812_Erase(void *user, pcan_boot_byte_t slot) /* Реализует single-slot подготовку внешней NOR. */ +{ /* Существующие legacy-образы и FPGA ниже 160000 не входят в новый CAN-раздел. */ + unsigned long sector; (void)user; /* Перебирает только три полных обычных сектора нового образа. */ + if (slot || !Boot2812_NorIdentify() || !Boot2812_NorErase(BOOT2812_META_WORD)) return false; /* Сначала удаляет marker старого CAN-образа; при обрыве стирания сохраняется recovery. */ + for (sector = BOOT2812_IMAGE_WORD; sector < BOOT2812_IMAGE_WORD + BOOT2812_IMAGE_BYTES / 2UL; sector += 0x8000UL) if (!Boot2812_NorErase(sector)) return false; /* Геометрия x16 допускает erase только по границам обычных секторов 32K слов. */ + return true; /* Ядро ProtoCAN разрешает DATA только после полного успешного стирания слота. */ +} /* EEPROM-операции и несуществующий второй слот отсутствуют. */ +bool Boot2812_Write(void *user, pcan_boot_byte_t slot, uint32_t offset, const pcan_boot_byte_t *data, pcan_boot_byte_t length) /* Упаковывает поступившие октеты в x16 слова NOR. */ +{ /* В одном вызове записывается не более одного classic CAN кадра. */ + unsigned int i, word; (void)user; /* Счётчик относится к октетам кадра, адрес NOR отдельно делится на два. */ + if (slot || !length || length > 8U || (offset & 1UL) || offset > BOOT2812_IMAGE_BYTES || length > BOOT2812_IMAGE_BYTES - offset) return false; /* Не допускает выхода из слота либо продолжения слова с неверного октета. */ + for (i = 0; i < length; i += 2U) { /* Последовательные 8-октетные блоки начинаются на границе x16 слова. */ + word = (data[i] & 255U) | ((i + 1U < length ? data[i + 1U] & 255U : 255U) << 8); /* Неполное последнее слово сохраняет FF в незанятом старшем октете. */ + if (!Boot2812_NorProgram(BOOT2812_IMAGE_WORD + (offset + i) / 2UL, word)) return false; /* Аппаратный драйвер проверяет и допустимый адрес, и результат записи каждого слова. */ + } /* Завершает сохранение текущего CAN-блока. */ + return true; /* ACK означает проверенную запись, а не только получение кадра. */ +} /* CRC ядра продвигается только после успешного возврата этого callback. */ +pcan_boot_status_t Boot2812_Verify(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *image) /* Перепроверяет CRC непосредственно из сохранённой NOR. */ +{ /* Потоковая CRC при приёме не заменяет аппаратный readback полного файла. */ + uint32_t offset, crc = 0UL, entry; pcan_boot_byte_t bytes[32]; unsigned int count, i; (void)user; /* Небольшой буфер не требует размещать весь образ во внутренней RAM F2812. */ + if (slot || image->image_size < 24UL || image->image_size > BOOT2812_IMAGE_BYTES || (image->image_size & 1UL)) return PCAN_BOOT_STATUS_INVALID_SIZE; /* SCI8 должен целиком помещаться в выделенных трёх секторах и содержать целые слова. */ + if (image->product_type != BOOT2812_PRODUCT || image->hardware_revision_min > 1U || image->hardware_revision_max < 1U) return PCAN_BOOT_STATUS_WRONG_DEVICE; /* Образ F28335 или несовместимого изделия не становится загрузочным. */ + for (offset = 0; offset < image->image_size; offset += count) { /* Проверяет каждый фактически сохранённый октет ровно один раз. */ + count = image->image_size - offset < 32UL ? (unsigned int)(image->image_size - offset) : 32U; /* Последний буфер ограничен реальной длиной без FF-дополнения CAN. */ + for (i = 0; i < count; ++i) bytes[i] = octet(offset + i); /* Читает данные из NOR, а не из приёмной очереди CAN. */ + crc = pcan_boot_crc32_update(crc, bytes, count); /* Использует общий CRC32 ProtoCAN без дублирования полинома в аппаратном порту. */ + Boot2812_Busy(); /* Большой файл сохраняет ответы клиента при длинной проверке на реальном CPU. */ + } /* Завершает вычисление CRC readback. */ + if (crc != image->image_crc32) return PCAN_BOOT_STATUS_CRC_ERROR; /* Различает повреждение памяти и ошибку структуры SCI8. */ + return table(image->image_size, false, &entry) ? PCAN_BOOT_STATUS_OK : PCAN_BOOT_STATUS_INVALID_STATE; /* Все адреса, перекрытия, терминатор и entry проверяются до COMMIT. */ +} /* До успеха verifier никакие слова приложения не переносятся в RAM. */ +bool Boot2812_Commit(void *user, pcan_boot_byte_t slot, const pcan_boot_manifest_t *image) /* Публикует загрузочный manifest последней операцией после readback. */ +{ /* Формат из 12 слов фиксирован и не зависит от sizeof C-структуры. */ + unsigned int words[12], i; /* Два magic-слова, версия формата, размер, CRC, версия FW и контроль manifest. */ + pcan_boot_byte_t bytes[20]; uint32_t crc; /* CRC первых десяти слов защищает размер и контрольную сумму самого образа. */ + if (Boot2812_Verify(user, slot, image) != PCAN_BOOT_STATUS_OK) return false; /* Не публикует файл, испорченный после предыдущего VERIFY. */ + words[0] = 0x2812U; words[1] = 0xCA7EU; words[2] = 1U; words[3] = 0U; /* Magic 2812/CA7E и версия 1 отличают новый CAN manifest от прежних данных платы. */ + words[4] = (unsigned int)(image->image_size & 0xFFFFUL); words[5] = (unsigned int)(image->image_size >> 16); /* Длина выражена октетами и хранится младшим словом первой. */ + words[6] = (unsigned int)(image->image_crc32 & 0xFFFFUL); words[7] = (unsigned int)(image->image_crc32 >> 16); /* Сохраняет точную CRC всего полученного файла. */ + words[8] = (unsigned int)(image->firmware_version & 0xFFFFUL); words[9] = (unsigned int)(image->firmware_version >> 16); /* Версия кандидата не подменяется версией постоянного загрузчика. */ + for (i = 0; i < 10U; ++i) { bytes[2U * i] = words[i] & 255U; bytes[2U * i + 1U] = words[i] >> 8; } /* Wire-представление manifest использует октеты независимо от ширины C28x char. */ + crc = pcan_boot_crc32_update(0UL, bytes, 20U); words[10] = (unsigned int)(crc & 0xFFFFUL); words[11] = (unsigned int)(crc >> 16); /* CRC manifest не позволяет принять частично записанные поля размера и CRC образа. */ + for (i = 2U; i < 12U; ++i) if (!Boot2812_NorProgram(BOOT2812_META_WORD + i, words[i])) return false; /* Сначала записывает все поля, пока оба magic-слова ещё равны FF. */ + if (!Boot2812_NorProgram(BOOT2812_META_WORD + 1UL, words[1])) return false; /* Второе magic-слово фиксируется после полного тела manifest. */ + return Boot2812_NorProgram(BOOT2812_META_WORD, words[0]); /* Первое magic записывается последним: потеря питания раньше оставляет recovery. */ +} /* Повтор COMMIT обрабатывает идемпотентный автомат общего ядра. */ +bool Boot2812_Load(uint32_t *entry) /* Проверяет опубликованный образ после reset перед переносом в RAM приложения. */ +{ /* Пустой или повреждённый manifest оставляет прибор в постоянном CAN recovery. */ + unsigned int words[12], i; pcan_boot_byte_t bytes[20]; uint32_t crc; pcan_boot_manifest_t image; /* Сериализованные поля читаются явно, без memcpy по ABI структуры. */ + for (i = 0; i < 12U; ++i) words[i] = Boot2812_NorRead(BOOT2812_META_WORD + i); /* Читает только фиксированные 24 октета manifest. */ + if (words[0] != 0x2812U || words[1] != 0xCA7EU || words[2] != 1U || words[3]) return false; /* Не интерпретирует старые данные Flash либо неполный commit как запускаемый файл. */ + for (i = 0; i < 10U; ++i) { bytes[2U * i] = words[i] & 255U; bytes[2U * i + 1U] = words[i] >> 8; } /* Восстанавливает то же октетное представление, что защищалось при COMMIT. */ + crc = pcan_boot_crc32_update(0UL, bytes, 20U); /* Проверяет метаданные до использования объявленной ими длины. */ + if (crc != ((uint32_t)words[10] | ((uint32_t)words[11] << 16))) return false; /* Повреждённый размер не может вывести чтение за пределы CAN-слота. */ + image.image_size = (uint32_t)words[4] | ((uint32_t)words[5] << 16); image.image_crc32 = (uint32_t)words[6] | ((uint32_t)words[7] << 16); /* Размер и CRC файла восстанавливаются только после успешной CRC manifest. */ + image.firmware_version = (uint32_t)words[8] | ((uint32_t)words[9] << 16); image.product_type = BOOT2812_PRODUCT; image.hardware_revision_min = image.hardware_revision_max = 1U; /* Профиль образа был проверен до публикации manifest. */ + return Boot2812_Verify(0, 0U, &image) == PCAN_BOOT_STATUS_OK && table(image.image_size, true, entry); /* Сначала полный read-only проход, затем перенос и только после успеха разрешение вызова entry. */ +} /* Не загружает старые flat BIN автоматически: новый проект использует проверяемую SCI8-таблицу. */ diff --git a/c/protocan-boot/ports/tms320f2812/nor_flash.c b/c/protocan-boot/ports/tms320f2812/nor_flash.c new file mode 100644 index 0000000..0b5ff51 --- /dev/null +++ b/c/protocan-boot/ports/tms320f2812/nor_flash.c @@ -0,0 +1,69 @@ +#include "boot2812.h" /* Ограничивает аппаратный драйвер разделами обновления конкретного профиля ПМ67. */ +#if defined(BOOT2812_HOST) /* Host-модель воспроизводит команды NOR без обращения к физическим CPU-адресам. */ +extern unsigned int NorModel_Read(unsigned long word); /* Модель отдаёт данные, ID и аппаратные биты готовности чипа. */ +extern void NorModel_Write(unsigned long word, unsigned int value); /* Модель принимает настоящую последовательность unlock/program/erase драйвера. */ +#define NOR_READ(word) NorModel_Read(word) /* Подменяет только чтение шины, сохраняя алгоритм драйвера. */ +#define NOR_WRITE(word, value) NorModel_Write(word, value) /* Подменяет физическую запись при проверке границ и отказов. */ +#else /* Production использует 16-битную параллельную XINTF-шину. */ +#define NOR_READ(word) (*(volatile unsigned int *)(word)) /* Один CPU-адрес C28x соответствует одному x16 слову AM29LV800BT. */ +#define NOR_WRITE(word, value) (*(volatile unsigned int *)(word) = (value)) /* Volatile сохраняет каждый командный цикл AMD в исходном порядке. */ +#endif /* Завершает выбор физической шины либо модели. */ +static void reset_read(void) /* Выводит чип из autoselect либо неудачной операции в обычный режим чтения. */ +{ /* Reset не стирает слова памяти и допустим по любому адресу чипа. */ + NOR_WRITE(BOOT2812_NOR_BASE, 0x00F0U); /* F0 — Read/Reset из таблицы команд AMD Am29LV800B. */ +} /* Все ошибки возвращают NOR в состояние, пригодное для следующей recovery-сессии. */ +static void unlock(unsigned int command) /* Выполняет общий префикс x16-команд согласно datasheet AMD. */ +{ /* Адреса ниже являются смещениями в словах, а не октетными AAA/555 режима x8. */ + NOR_WRITE(BOOT2812_NOR_BASE + 0x555UL, 0x00AAU); /* Первый unlock-цикл AA по смещению 555h в режиме x16. */ + NOR_WRITE(BOOT2812_NOR_BASE + 0x2AAUL, 0x0055U); /* Второй unlock-цикл 55 по смещению 2AAh. */ + NOR_WRITE(BOOT2812_NOR_BASE + 0x555UL, command); /* Третий цикл выбирает autoselect, программирование либо начало стирания. */ +} /* Последующий цикл данных или адрес сектора выполняет вызывающая операция. */ +unsigned int Boot2812_NorRead(unsigned long word) /* Читает только физический диапазон установленной NOR ёмкостью 1 МиБ. */ +{ /* Верхняя исключающая граница равна BASE + 512K слов. */ + return word >= BOOT2812_NOR_BASE && word < BOOT2812_NOR_BASE + 0x80000UL ? NOR_READ(word) : 0xFFFFU; /* Вне чипа не создаёт шинного чтения по неизвестному адресу. */ +} /* Возвращает полное x16 слово без перестановки октетов. */ +bool Boot2812_NorIdentify(void) /* Идентификация обязательна перед разрешением изменяющих операций. */ +{ /* Не подменяет top-boot геометрию похожим bottom-boot или NAND-чипом. */ + unsigned int maker, device; /* Хранит два слова autoselect, прежде чем вернуть чип к чтению. */ + reset_read(); unlock(0x0090U); /* 90h включает чтение manufacturer/device ID после обычного unlock. */ + maker = NOR_READ(BOOT2812_NOR_BASE); device = NOR_READ(BOOT2812_NOR_BASE + 1UL); /* AMD: offset 0 содержит 0001, offset 1 — 22DA для Am29LV800BT x16. */ + reset_read(); /* Обычные чтения образа после проверки не должны видеть таблицу autoselect. */ + return maker == 0x0001U && device == 0x22DAU; /* Отличающийся чип получает отказ до первого sector erase. */ +} /* Не выполняет разрушительных пробных записей для определения типа памяти. */ +static bool wait_word(unsigned long word, unsigned int expected, unsigned long timeout) /* Ограничивает DQ7/DQ5 polling временем и числом проходов. */ +{ /* DQ7 отражает готовность программируемого старшего бита; DQ5 требует завершающего повторного чтения. */ + unsigned long started = Boot2812_Now(), budget = 50000000UL; /* Итерационный предел обеспечивает выход даже при остановленном Timer1. */ + unsigned int value; /* Снимок status считывается один раз на основной проход. */ + do { /* Не вызывает никаких функций из программируемой внешней NOR: код загрузчика находится во внутренней Flash. */ + value = NOR_READ(word); /* Читает именно адрес программирования либо начало стираемого сектора. */ + if ((value & 0x0080U) == (expected & 0x0080U)) return NOR_READ(word) == expected; /* После совпадения DQ7 подтверждает все 16 бит результата. */ + if (value & 0x0020U) { /* DQ5 сообщает превышение внутреннего времени алгоритма AMD. */ + if ((NOR_READ(word) & 0x0080U) == (expected & 0x0080U)) return NOR_READ(word) == expected; /* Повтор исключает нормальное завершение операции одновременно с чтением DQ5. */ + break; /* После подтверждённой ошибки больше не ждёт неопределённое время. */ + } /* Завершает трактовку аппаратного статуса текущего прохода. */ + Boot2812_Busy(); /* Долгое стирание продолжает давать клиенту живой ответ и не блокирует CAN ISR. */ + } while (--budget && Boot2812_Now() - started < timeout); /* Беззнаковое вычитание сохраняет корректность при переполнении миллисекунд. */ + reset_read(); /* Отказ возвращает чип в режим чтения перед следующей recovery-попыткой. */ + return false; /* Не сообщает успех по одному окончанию тайм-аута. */ +} /* Завершает ограниченное ожидание аппаратной операции. */ +bool Boot2812_NorProgram(unsigned long word, unsigned int value) /* Программирует только выделенный CAN-образ либо manifest. */ +{ /* Старые данные приложения, FPGA и остальные сектора чипа не входят в разрешённые диапазоны. */ + unsigned int before; /* Предварительное чтение исключает попытку перевода NOR-бита из нуля в единицу. */ + if (!((word >= BOOT2812_IMAGE_WORD && word < BOOT2812_IMAGE_WORD + BOOT2812_IMAGE_BYTES / 2UL) || (word >= BOOT2812_META_WORD && word < BOOT2812_META_WORD + 0x2000UL))) return false; /* Проверяет word-адрес до любого unlock или командного цикла. */ + before = NOR_READ(word); /* Проверяет текущее содержимое перед началом операции. */ + if (before == value) return true; /* Повтор одинакового блока не выполняет лишнее программирование. */ + if ((before & value) != value) return false; /* Бит 0→1 требует отдельного sector erase и не должен маскироваться чтением старого слова. */ + unlock(0x00A0U); NOR_WRITE(word, value); /* A0 запускает word program; следующий цикл содержит адрес и полные 16 бит данных. */ + return wait_word(word, value, 100UL); /* Сто миллисекунд дают ограниченный запас для программирования одного слова. */ +} /* Каждый успех означает фактическое совпадение прочитанного слова. */ +bool Boot2812_NorErase(unsigned long word) /* Не принимает произвольный адрес или команду полного стирания чипа. */ +{ /* Обновление ограничено секторами 12/13/14 и последним top-boot сектором 18. */ + unsigned long i, count = word == BOOT2812_META_WORD ? 0x2000UL : 0x8000UL; /* AM29LV800BT: обычный сектор 32K слов, последний boot-сектор 8K слов. */ + if (!(word == BOOT2812_IMAGE_WORD || word == BOOT2812_IMAGE_WORD + 0x8000UL || word == BOOT2812_IMAGE_WORD + 0x10000UL || word == BOOT2812_META_WORD)) return false; /* Только точные разрешённые начала секторов исключают округление в соседнюю область. */ + unlock(0x0080U); /* 80h начинает шеститактовую последовательность Sector Erase AMD. */ + NOR_WRITE(BOOT2812_NOR_BASE + 0x555UL, 0x00AAU); NOR_WRITE(BOOT2812_NOR_BASE + 0x2AAUL, 0x0055U); /* Повторяет вторую unlock-пару перед выбором сектора. */ + NOR_WRITE(word, 0x0030U); /* 30h по sector address выбирает один сектор; команда Chip Erase 10h отсутствует. */ + if (!wait_word(word, 0xFFFFU, 20000UL)) return false; /* Ограничивает ожидание двадцатью секундами с периодическими BUSY-ответами. */ + for (i = 0; i < count; ++i) if (NOR_READ(word + i) != 0xFFFFU) return false; /* Проверяет всю стёртую область, а не только её первое слово. */ + return true; /* Разрешает запись лишь после полного аппаратного readback сектора. */ +} /* При сбое сохранённый manifest уже недействителен, загрузчик остаётся в recovery. */ diff --git a/c/protocan-boot/ports/tms320f28335/README.md b/c/protocan-boot/ports/tms320f28335/README.md index c3c0a5d..337d2ec 100644 --- a/c/protocan-boot/ports/tms320f28335/README.md +++ b/c/protocan-boot/ports/tms320f28335/README.md @@ -1,18 +1,54 @@ # F28335 + M95M02: CAN, отдельный загрузчик и A/B -Реализация состоит из Flash-загрузчика `periph_167/Bootloader`, переносимого +Реализация состоит из Flash-загрузчика `projects/ccs/f28335`, переносимого `f28335_boot_store.c`, аппаратного `f28335_boot_hw.c` и адаптера -`f28335_can_boot.c`. Приложение подключает их через `Source/Internal/can_boot.c`. +`f28335_can_boot.c`. Приложение подключает общий `f28335_can_application.c` +прямой ссылкой linked resource из templates в CCS Debug/Release. В сборке `EEPROM_M95M02=0` CAN Boot отключён. Для установленной M95M02 — значение 1. ## Адрес и формат -Device Type **3**, Device ID **7**, имя **F28335-M95M02**, Product **0x2833**, HW **1**. +Адрес определяется физическим номером **PERIPH 0–31** по новой Excel-таблице: +Type = 1 + PERIPH / 16 (целая часть), Device ID = PERIPH mod 16. +**УМП1 — 1/5, УМП2 — 1/6, задатчик — 1/8**. Product **0x2833**, HW **1** +описывают существующую аппаратную совместимость F28335 и не являются CAN-адресом. +Имена паспорта для назначенных плат — `UMP1`, `UMP2`, `Zadatchik`. +Приложение передаёт Mode в `F28335CanBoot_Init(Mode)`. Загрузчик независимо +читает те же активные низким уровнем GPIO21/20/22/51 с весами 1/2/4/8 и базой 1. +Поэтому существующие перемычки ПМ35 задают номера 1–16; номера 0 и 17–31 +поддерживаются адресным контрактом, но требуют другого источника физического номера. +Общий адрес 3/7 больше не принимается. Чужие адреса отбрасываются аппаратным +mailbox, ISR и ядром до записи EEPROM, включая данные A/B и управляющие команды. В приложении FW берётся из `firmware_version.h`, формат `major<<24 | minor<<16 | patch`; для версии 1.1.2 это `0x01010002`. Загрузчик сообщает версию подтверждённого образа из журнала, при отсутствии такого образа — 0. Версия кандидата передаётся в BEGIN_COMPAT. CAN **250000 бит/с**, Extended ID, окно **16 блоков по 8 октетов**. -ENTER_BOOT для session=1: `0x13790102`, STATUS: `0x1B7C0102`. +Для задатчика и session=1: ENTER_BOOT `0x11890102`, STATUS `0x198C0102`. + +## Общий запуск Flash и резервной EEPROM + +Сектор A и аппаратный boot `0x33FFF6` принадлежат постоянному загрузчику. +Flash-приложение использует `[0x300000,0x338000)`: первые 16 слов — описание +FAB1, остальные — собственные LOAD-секции. `f28335_flash_app.c` проверяет +magic/version, entry, границы, инверсию entry, маркеры и CRC32 IEEE всего +диапазона после заголовка, включая промежутки, заполненные `0xFFFF`. +Python-контракт `python/protocan/f28335_flash.py` заполняет зарезервированные +32 октета COFF по смещению, подтверждённому TI OFD, после линковки. + +Загрузчик даёт трёхсекундное окно CAN, затем запускает исправную внутреннюю +Flash в приоритете. Отсутствующая/повреждённая Flash ведёт к прежнему выбору +EEPROM A/B с trial/CONFIRM/rollback. ENTER_BOOT удерживает CAN recovery. +Handoff running=`0xFE` обозначает проверенную внутреннюю Flash; 0/1 — EEPROM +A/B, `0xFF` — отсутствие запущенного приложения. Flash-приложение обслуживает +PING и ENTER_BOOT, но не подменяет подтверждение EEPROM-кандидата. +Обновление EEPROM по CAN не меняет приоритет исправной Flash после reset. + +RS Flash должен стирать только B–H, публиковать FAB1 после проверки остальных +данных и запрещать любые адреса сектора A. В SETGUI соответствующие JTAG +маски задаются явными TI `FlashSectorA..H`: A для установки boot, B–H для +приложения. Полное стирание чипа внешним программатором не ограничивается linker. +Старая самостоятельная Flash-сборка с codestart `0x33FFF6` несовместима с этим +размещением и не должна передаваться как обновление приложения. Образ — SCI8 BIN (`AA 08`), чётная длина от 24 до **130560 байт** включительно. Числа в протоколе little endian. Адреса внутри SCI8: сначала старшее 16-битное @@ -106,7 +142,7 @@ Python API: `protocan.can_boot.CanBootServices` — запросы и разбо ## Аппаратная интеграция MBOX3 — адресные входящие Boot; MBOX4 — ответы; MBOX6 — точный broadcast discovery. -MBOX0..2 сохраняют legacy/UMP, MBOX5 остаётся heartbeat. ISR помещает сообщения +MBOX0..2 сохраняют legacy/UMP, MBOX5 загрузчик не использует. ISR помещает сообщения в очередь на 31 кадр. Чужие адреса, RTR и неподходящие типы отбрасываются до очереди. При переполнении/потере mailbox сессия отменяется; повторная запись начинается заново. SPI-драйвер загрузчика имеет ограничение ожидания байта и WIP, 24-битный адрес, @@ -126,10 +162,13 @@ NOINIT handoff в обоих проектах. CAN не содержит опе Старые BIN/OUT автоматически не заменены. Приложение должно содержать интеграцию READY/CONFIRM, иначе на следующем reset оно останется неподтверждённым кандидатом. 2. Собрать отдельный загрузчик TI C2000 COFF compiler: - `Bootloader/build.ps1 -CompilerRoot <путь-к-ti-cgt-c2000>`. - Результат — `Bootloader/build/F28335_CAN_AB.out` и MAP. -3. Один раз установить этот OUT через JTAG и выбрать аппаратный Flash boot - согласно схеме платы. Не загружать поверх него старый application OUT с + `python c/protocan-boot/projects/build.py --device f28335 --compiler <путь-к-ti-cgt-c2000>`. + Результат — `projects/ccs/f28335/Debug/F28335_CAN_AB.out` и MAP. +3. Установить обновлённый OUT через JTAG и выбрать аппаратный Flash boot + согласно схеме платы. При переходе с общего адреса 3/7 обновить и приложение, + и загрузчик: старый загрузчик не перейдёт на новый адрес после reset сам. + В SETCAN выбрать «Прошивка → CAN / ProtoCAN Boot → Устройство PERIPH» + и нужное назначение. Не загружать поверх загрузчика старый application OUT с секцией codestart во Flash. 4. После reset пустая EEPROM или старая разметка автоматически ведут в CAN recovery. Передать новое приложение через ProtoCAN Boot, дождаться пробного запуска и @@ -145,8 +184,10 @@ NOINIT handoff в обоих проектах. CAN не содержит опе ядро, приложение/загрузчик, wide-octet режим, журнал, обрыв публикации на каждом из 69 возможных положений, пробный запуск, CONFIRM, откат, SCI8 и границы памяти. Python-тесты проверяют клиентские запросы, паспорт, фильтрацию ответов и лимит A/B. -Проверка синтаксиса использует настоящие DSP2833x headers. Сборка TI/CCS, -раскладка итогового MAP и физические CAN/SPI/reset на плате ещё не подтверждены. +Проверка синтаксиса использует настоящие DSP2833x headers. Импорт и сборка TI/CCS, +раскладка MAP и реальные COFF LOAD-адреса проверены; физические CAN/SPI/reset +на плате требуют стендовой проверки. Отдельные проекты и команды сборки описаны +в [инструкции CCS](../../projects/README.md). CRC32 защищает от повреждения, криптографической подписи и anti-rollback по версии в этом порту нет. Удалённый CONFIRM подтверждает готовность приложения, @@ -155,6 +196,12 @@ CRC32 защищает от повреждения, криптографичес Аппаратный формат SPI boot описан в [TI Boot ROM Reference Guide](https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/171/2742.Boot-ROM.pdf). В A/B-схеме ROM выбирает Flash, а разбор EEPROM выполняет этот загрузчик. -Общий порт и ядро подключены из `newProject/templates/c/protocan-boot`. -Приложение и отдельный загрузчик используют один checkout; зависимость CAN Boot -от копии templates внутри SETGUI устранена. Startup, linker script и Quiesce остаются в проекте платы. +Проект предоставляет `f28335_can_application_config.h` в include paths. +Он задаёт `F28335_CAN_BOOT_APPLICATION_ENABLED` (0/1) и при включённом модуле +`F28335_CAN_BOOT_FIRMWARE_VERSION` из версии приложения. В 167 это ручной +`firmware_version.h`; профиль включён только при M95M02 без `FLASH_BOOT`. +Локальный `Source/Internal/can_boot.c` содержит только `F28335Boot_Quiesce` +со штатной остановкой нагрузки. Общие `.c` повторно включать в него не нужно: +они компилируются единственным linked resource общей библиотеки. +Постоянный Flash-загрузчик по-прежнему собирается отдельным проектом +`projects/ccs/f28335` и не линкуется в RAM-приложение. diff --git a/c/protocan-boot/ports/tms320f28335/f28335_boot_platform.h b/c/protocan-boot/ports/tms320f28335/f28335_boot_platform.h index facd3b3..e0d7bc9 100644 --- a/c/protocan-boot/ports/tms320f28335/f28335_boot_platform.h +++ b/c/protocan-boot/ports/tms320f28335/f28335_boot_platform.h @@ -1,6 +1,7 @@ #ifndef F28335_BOOT_PLATFORM_H #define F28335_BOOT_PLATFORM_H #include "f28335_boot_store.h" +#include "f28335_flash_app.h" /* Общий handoff различает EEPROM A/B, защищённое Flash-приложение и неизвестный запуск. */ #ifndef F28335_BOOT_LOADER #define F28335_BOOT_LOADER 0 #endif diff --git a/c/protocan-boot/ports/tms320f28335/f28335_can_application.c b/c/protocan-boot/ports/tms320f28335/f28335_can_application.c new file mode 100644 index 0000000..f7fe30b --- /dev/null +++ b/c/protocan-boot/ports/tms320f28335/f28335_can_application.c @@ -0,0 +1,10 @@ +#include "f28335_can_application_config.h" /* Получает от проекта разрешение CAN A/B и версию приложения; этот конфигурационный заголовок должен находиться в include paths CCS. */ +#ifndef F28335_CAN_BOOT_APPLICATION_ENABLED /* Отсутствующее аппаратное решение нельзя трактовать как разрешение записи служебных областей EEPROM. */ +#error "Define F28335_CAN_BOOT_APPLICATION_ENABLED in f28335_can_application_config.h" /* Останавливает сборку до появления приложения с неполной интеграцией загрузчика. */ +#endif /* Завершает проверку обязательного конфигурационного признака проекта. */ +#if F28335_CAN_BOOT_APPLICATION_ENABLED /* Самостоятельный Flash-образ и платы без M95M02 исключают весь CAN A/B-код на этапе компиляции. */ +#include "../../src/pcan_boot.c" /* Компилирует единственный автомат команд ProtoCAN Boot с его штатными сессиями, CRC32 и проверкой последовательности пакетов. */ +#include "f28335_boot_store.c" /* Подключает общий A/B-журнал, readback, проверку SCI8 и выбор подтверждённого слота той же версии templates. */ +#include "f28335_boot_hw.c" /* Предоставляет SPI EEPROM, watchdog и согласованный handoff между приложением и постоянным Flash-загрузчиком. */ +#include "f28335_can_boot.c" /* В режиме приложения обслуживает вход в boot и READY/CONFIRM, сохраняя служебные mailbox 3/4/6 отдельно от технологического CAN. */ +#endif /* Постоянный загрузчик собирается отдельным CCS-проектом templates с F28335_BOOT_LOADER=1, а не этим прикладным модулем. */ diff --git a/c/protocan-boot/ports/tms320f28335/f28335_can_boot.c b/c/protocan-boot/ports/tms320f28335/f28335_can_boot.c index 5cbd7a4..f02354b 100644 --- a/c/protocan-boot/ports/tms320f28335/f28335_can_boot.c +++ b/c/protocan-boot/ports/tms320f28335/f28335_can_boot.c @@ -19,6 +19,7 @@ static struct { uint32_t id; unsigned int dlc; pcan_boot_byte_t data[8]; } queue static unsigned int reset_requested,reset_session,ready,healthy,confirmed; static uint32_t sent_at,ready_at; static unsigned int main_passes; +static unsigned int addressed; /* Разрешает обслуживание только после проверки номера PERIPH и установки согласованных фильтров CAN. */ static int tx_busy,tx_canceling; /* Один исходящий mailbox исключает перезапись ещё передаваемого ответа. * MDL содержит первые четыре октета, MDH — следующие четыре, младшим вперёд. @@ -84,7 +85,7 @@ static unsigned int enter(void *u,pcan_boot_byte_t session) if(!healthy) return 2; if(F28335_BOOT_LOADER) return 0; /* No destructive fallback on boards still starting through the SPI ROM. */ - if(F28335Boot_RunningSlot()>1 || !confirmed) return 2; + if((F28335Boot_RunningSlot()>1 && F28335Boot_RunningSlot()!=F28335_BOOT_FLASH_SLOT) || !confirmed) return 2; /* Только handoff общего загрузчика разрешает переход из EEPROM либо защищённой внутренней Flash; старый SPI-ROM старт остаётся запрещён. */ reset_session=session; reset_requested=1; return 1; } static void info32(pcan_boot_byte_t *p,uint32_t v) @@ -95,18 +96,18 @@ static void info32(pcan_boot_byte_t *p,uint32_t v) * 2 — active/pending/attempted/healthy/тайм-аут, 3 — область параметров. */ static bool info(void *u,pcan_boot_byte_t command,pcan_boot_byte_t page,pcan_boot_byte_t *out) { - static const char name[]=F28335_CAN_BOOT_DEVICE_NAME; - unsigned int i,index; (void)u; + const char *name=boot.config.device_type==1U && boot.config.device_id==8U?"Zadatchik":boot.config.device_type==1U && boot.config.device_id==5U?"UMP1":boot.config.device_type==1U && boot.config.device_id==6U?"UMP2":F28335_CAN_BOOT_DEVICE_NAME; /* Паспорт различает три назначенных Excel устройства; резервные номера сохраняют аппаратное имя. */ + unsigned int i,index,name_size=(unsigned int)strlen(name)+1U; (void)u; /* Длина включает завершающий NUL, чтобы последняя страница имени однозначно завершала чтение. */ if(command==PCAN_BOOT_CMD_CAPABILITIES && page==0) { /* bits: ping, discovery, identity, name, memory, A/B, confirm, rollback, * separate loader, session timeout, readback, SCI8 validation. */ - info32(out,(F28335_BOOT_LOADER || F28335Boot_RunningSlot()<2)?0xFFFUL:0x1FUL); + info32(out,(F28335_BOOT_LOADER || F28335Boot_RunningSlot()<2 || F28335Boot_RunningSlot()==F28335_BOOT_FLASH_SLOT)?0xFFFUL:0x1FUL); /* Flash-приложение с достоверным handoff поддерживает вход в постоянный CAN Boot так же, как подтверждённый EEPROM-образ. */ info32(out+4,F28335_AB_SLOT_BYTES); return true; } if(command==PCAN_BOOT_CMD_DEVICE_NAME) { - if((unsigned int)page*8U>=sizeof(name)) return false; + if((unsigned int)page*8U>=name_size) return false; /* Страница после конца выбранного имени не является допустимой частью паспорта. */ for(i=0;i<8;++i) { index=(unsigned int)page*8U+i; - out[i]=index=F28335_CAN_BOOT_PERIPH_COUNT) return; /* Номер вне Excel-диапазона 0–31 не подменяется общим адресом и не открывает запись другой платы. */ memset(&cfg,0,sizeof(cfg)); memset(&port,0,sizeof(port)); io.read=F28335Boot_Read; io.write=F28335Boot_Write; io.user=0; healthy=f28335_boot_open(&store,&io); - cfg.device_type=F28335_CAN_BOOT_DEVICE_TYPE; cfg.device_id=F28335_CAN_BOOT_DEVICE_ID; + cfg.device_type=1U+periph_id/16U; cfg.device_id=periph_id%16U; /* Excel: PERIPH 0–15 → Type 1, 16–31 → Type 2; младшие четыре бита задают Device ID. */ cfg.product_type=F28335_CAN_BOOT_PRODUCT; cfg.hardware_revision=1; #if F28335_BOOT_LOADER cfg.firmware_version=store.active<2?store.image[store.active].firmware_version:0; @@ -139,7 +142,7 @@ void F28335CanBoot_Init(void) cfg.firmware_version=F28335_CAN_BOOT_FIRMWARE_VERSION; #endif head=tail=overflow=reset_requested=reset_session=ready=main_passes=0; tx_busy=tx_canceling=0; - confirmed=healthy && running<2 && store.active==running && store.pending==F28335_AB_NONE; + confirmed=running==F28335_BOOT_FLASH_SLOT || (healthy && running<2 && store.active==running && store.pending==F28335_AB_NONE); /* Flash уже проверена CRC постоянным boot; пробное подтверждение требуется только EEPROM-кандидату. */ cfg.active_slot=store.active; cfg.slot_count=2; cfg.max_image_size=F28335_AB_SLOT_BYTES; cfg.ack_window=16; cfg.session_timeout_ms=30000UL; @@ -148,6 +151,7 @@ void F28335CanBoot_Init(void) port.confirm_running_slot=confirm; port.enter_boot=enter; port.can_reboot=can_reboot; port.service_info=info; if(!pcan_boot_init(&boot,&cfg,&port,0)) return; + addressed=1U; /* Дальнейшие ISR, основной цикл и handoff используют только успешно созданную адресную конфигурацию. */ EALLOW; /* Меняем только MBOX3/4/6: маска 88=8+16+64. MBOX0..2 — старый обмен, * MBOX5 — heartbeat. Приём broadcast выделен в отдельный точный mailbox, @@ -181,8 +185,8 @@ static void receive_box(volatile struct MBOX *box,uint32_t mask) type=pcan_boot_id_msg_type(id); if(!(box->MSGID.all&0x80000000UL) || pcan_boot_id_route(id)!=0 || (type!=9 && type!=10 && type!=11 && type!=13) || - !((pcan_boot_id_device_type(id)==F28335_CAN_BOOT_DEVICE_TYPE && - pcan_boot_id_device_id(id)==F28335_CAN_BOOT_DEVICE_ID) || + !((pcan_boot_id_device_type(id)==boot.config.device_type && /* Сравнивает тип именно этой платы, а не прежнюю общую константу 3. */ + pcan_boot_id_device_id(id)==boot.config.device_id) || /* Отбрасывает команды соседних PERIPH ещё до очереди и любых операций EEPROM. */ (type==13 && pcan_boot_id_device_type(id)==7 && pcan_boot_id_device_id(id)==15 && pcan_boot_id_msg_body(id)==0))) { ECanaRegs.CANRMP.all=mask; return; } if(next==tail) overflow=1; @@ -199,6 +203,7 @@ static void receive_box(volatile struct MBOX *box,uint32_t mask) void F28335CanBoot_RxISR(void) { + if(!addressed) return; /* Неверный или ещё не настроенный номер PERIPH не должен принимать даже оставшиеся флаги RX. */ receive_box(&ECanaMboxes.MBOX3,8UL); receive_box(&ECanaMboxes.MBOX6,64UL); } @@ -214,9 +219,11 @@ unsigned int F28335CanBoot_WatchdogAllowed(void) /* Неблокирующий диспетчер относительно ожидания CAN: вызывать в каждом проходе main. * Сами callbacks проверки/записи EEPROM синхронные. Порядок здесь важен: * проба приложения -> завершение TX -> reset -> poll -> ошибки RX -> один кадр. */ +unsigned int F28335CanBoot_Active(void) { return addressed && (boot.state!=PCAN_BOOT_STATE_IDLE || reset_requested); } /* Открытый ENTER_BOOT удерживает recovery; диагностический PING не меняет приоритет Flash и EEPROM. */ void F28335CanBoot_Service(void) { uint32_t now=F28335Boot_Now(); + if(!addressed) return; /* Не обслуживает старую RAM-сессию после отказа повторной инициализации адреса. */ if(!F28335_BOOT_LOADER && ready && !confirmed && healthy && F28335Boot_RunningSlot()<2) { /* A trial must keep executing main, not merely a timer ISR. */ /* После 100 проходов main и 5 секунд пробуем сохранить CONFIRM. @@ -261,15 +268,16 @@ void F28335CanBoot_Service(void) * или CRC незавершённой передачи: данные сессии через reset не сохраняются. */ void F28335CanBoot_Resume(unsigned int session) { - if(F28335_BOOT_LOADER && session && session<256) - (void)pcan_boot_process(&boot,pcan_boot_make_id(1,0, - F28335_CAN_BOOT_DEVICE_TYPE,F28335_CAN_BOOT_DEVICE_ID,9,(session<<8)|2),0,0); + if(addressed && F28335_BOOT_LOADER && session && session<256) /* Восстанавливает только допустимую сессию адресованного загрузчика после reset. */ + (void)pcan_boot_process(&boot,pcan_boot_make_id(1,0, /* ACK относится к тому же физическому PERIPH, который принимал ENTER_BOOT в приложении. */ + boot.config.device_type,boot.config.device_id,9,(session<<8)|2),0,0); /* MsgType 9, команда 2 и исходный SessionID сохраняют протокол handoff. */ } #else void F28335CanBoot_EarlyInit(void) {} -void F28335CanBoot_Init(void) {} +void F28335CanBoot_Init(unsigned int periph_id) { (void)periph_id; } /* Сборка без M95M02 не занимает CAN-адрес и не открывает сервис записи. */ void F28335CanBoot_RxISR(void) {} void F28335CanBoot_Service(void) {} +unsigned int F28335CanBoot_Active(void) { return 0U; } /* Профиль без M95M02 не создаёт CAN-сеанс и не удерживает старт общего загрузчика. */ void F28335CanBoot_Ready(void) {} unsigned int F28335CanBoot_WatchdogAllowed(void) { return 1; } void F28335CanBoot_Resume(unsigned int session) { (void)session; } diff --git a/c/protocan-boot/ports/tms320f28335/f28335_can_boot.h b/c/protocan-boot/ports/tms320f28335/f28335_can_boot.h index 17b44db..59476e8 100644 --- a/c/protocan-boot/ports/tms320f28335/f28335_can_boot.h +++ b/c/protocan-boot/ports/tms320f28335/f28335_can_boot.h @@ -9,8 +9,7 @@ #endif /* Адрес ProtoCAN состоит из Device Type (3 бита) и Device ID (4 бита). * ProductType — отдельный код совместимости прошивки; это не CAN ID и не RS-адрес. */ -#define F28335_CAN_BOOT_DEVICE_TYPE 3U -#define F28335_CAN_BOOT_DEVICE_ID 7U +#define F28335_CAN_BOOT_PERIPH_COUNT 32U /* Лист «Интерфейс протокола», строки 45–76: PERIPH 0–31 занимают два типа по 16 экземпляров. */ #define F28335_CAN_BOOT_PRODUCT 0x2833U #define F28335_CAN_BOOT_DEVICE_NAME "F28335-M95M02" /* Порядок интеграции приложения: @@ -18,10 +17,11 @@ * таймера и EEPROM; Ready после старта прикладных подсистем; Service в main. * RxISR вызывается из CAN ISR, WatchdogAllowed проверяется перед кормлением * watchdog таймерным ISR. Resume применяется только отдельным загрузчиком. */ -void F28335CanBoot_Init(void); +void F28335CanBoot_Init(unsigned int periph_id); /* Принимает физический номер PERIPH: 5 — УМП1, 6 — УМП2, 8 — задатчик; общий адрес для всех плат исключён. */ void F28335CanBoot_EarlyInit(void); void F28335CanBoot_RxISR(void); void F28335CanBoot_Service(void); +unsigned int F28335CanBoot_Active(void); /* Удерживает загрузчик в CAN recovery после ENTER_BOOT, не запуская приложение по окончании стартового окна. */ void F28335CanBoot_Ready(void); void F28335CanBoot_Resume(unsigned int session); unsigned int F28335CanBoot_WatchdogAllowed(void); diff --git a/c/protocan-boot/ports/tms320f28335/f28335_flash_app.c b/c/protocan-boot/ports/tms320f28335/f28335_flash_app.c new file mode 100644 index 0000000..ac5dbd5 --- /dev/null +++ b/c/protocan-boot/ports/tms320f28335/f28335_flash_app.c @@ -0,0 +1,26 @@ +#include "f28335_flash_app.h" /* Использует ту же границу сектора A и формат описания, что сборщик и RS-программатор. */ +bool f28335_flash_app_validate(f28335_flash_read_word_t read_word, void *user, uint32_t *entry) /* Не обращается к EEPROM и подходит для постоянного загрузчика и проверки staging RAM. */ +{ /* Никакие адреса из непроверенного заголовка не используются для чтения до проверки границ. */ + uint16_t header[F28335_FLASH_APP_HEADER_WORDS], word, octet, bit, i; /* Малый локальный буфер хранит 16 слов описания FAB1. */ + uint32_t address, start, end, expected, crc = 0xFFFFFFFFUL, target, inverse; /* CRC32 IEEE начинается со всех единиц и инвертируется после последнего октета. */ + if (!read_word || !entry) return false; /* Отсутствующий источник или выходной указатель не должен вызывать обращение к памяти. */ + for (i = 0; i < F28335_FLASH_APP_HEADER_WORDS; ++i) header[i] = read_word(user, F28335_FLASH_APP_START + i); /* Читает только фиксированное описание в секторе H. */ + if (header[0] != 0x4146U || header[1] != 0x3142U || header[2] != 1U || header[3] != F28335_FLASH_APP_HEADER_WORDS || header[14] != 0x5AA5U || header[15] != 0xA55AU) return false; /* Физические октеты ASCII FAB1, версия 1, размер и два маркера отличают завершённый образ от стёртого либо старого Flash. */ + target = (uint32_t)header[4] | ((uint32_t)header[5] << 16); /* Точка входа хранится младшим 16-битным словом вперёд внутри описания. */ + start = (uint32_t)header[6] | ((uint32_t)header[7] << 16); /* Нижняя граница защищённого CRC диапазона должна начинаться сразу после описания. */ + end = (uint32_t)header[8] | ((uint32_t)header[9] << 16); /* Верхняя граница является исключённым адресом слова, а не длиной в байтах. */ + expected = (uint32_t)header[10] | ((uint32_t)header[11] << 16); /* Сохранённая CRC32 рассчитана по физическим октетам всех слов диапазона. */ + inverse = (uint32_t)header[12] | ((uint32_t)header[13] << 16); /* Инверсия адреса выявляет частичную публикацию управляющих полей. */ + if (start != F28335_FLASH_APP_DATA || end <= start || end > F28335_FLASH_APP_STOP || target < start || target >= end || inverse != ~target) return false; /* Запрещает RAM, сектор загрузчика, пустой код и случайные адреса из повреждённого описания. */ + for (address = start; address < end; ++address) { /* Проверяет также стёртые промежутки между LOAD-секциями, чтобы JTAG и RS давали одинаковое содержимое. */ + word = read_word(user, address); /* Получает одно 16-битное слово из Flash либо из модели staging SCI8. */ + for (i = 0; i < 2U; ++i) { /* Каждый адрес C28x содержит два физических октета: сначала младший, затем старший. */ + octet = (word >> (8U * i)) & 255U; /* Маска отделяет октет независимо от 16-битного char TI. */ + crc ^= octet; /* Добавляет очередной октет в отражённое состояние CRC32 IEEE. */ + for (bit = 0; bit < 8U; ++bit) crc = (crc & 1UL) ? ((crc >> 1) ^ 0xEDB88320UL) : (crc >> 1); /* 0xEDB88320 — отражённый полином IEEE 802.3, совпадающий с zlib.crc32. */ + } /* Завершает обработку обоих октетов текущего слова. */ + } /* Завершает чтение только внутри области приложения ниже сектора A. */ + if ((crc ^ 0xFFFFFFFFUL) != expected) return false; /* Повреждённое или частично записанное приложение остаётся недоступным для запуска. */ + *entry = target; /* Публикует точку старта только после подтверждения всех адресов и данных. */ + return true; /* Разрешает загрузчику запустить именно проверенную Flash-программу. */ +} /* Ошибка никогда не меняет EEPROM, Flash или сохранённый выходной адрес. */ diff --git a/c/protocan-boot/ports/tms320f28335/f28335_flash_app.h b/c/protocan-boot/ports/tms320f28335/f28335_flash_app.h new file mode 100644 index 0000000..94741e3 --- /dev/null +++ b/c/protocan-boot/ports/tms320f28335/f28335_flash_app.h @@ -0,0 +1,11 @@ +#ifndef F28335_FLASH_APP_H /* Защищает общий контракт Flash-приложения от повторного объявления. */ +#define F28335_FLASH_APP_H /* Один заголовок используется загрузчиком, RS-проверкой и host-тестами. */ +#include "../../include/pcan_boot.h" /* Получает переносимые 16- и 32-битные типы и bool для C28x и ПК. */ +#define F28335_FLASH_APP_START 0x300000UL /* Первые 16 слов сектора H содержат описание FAB1, а не аппаратный boot. */ +#define F28335_FLASH_APP_HEADER_WORDS 16U /* Размер описания равен 32 октетам при 16-битном адресуемом слове C28x. */ +#define F28335_FLASH_APP_DATA 0x300010UL /* Код и Flash LOAD-секции следуют после служебного описания. */ +#define F28335_FLASH_APP_STOP 0x338000UL /* Начало сектора A является исключённой границей приложения. */ +#define F28335_BOOT_FLASH_SLOT 0xFEU /* Отдельный handoff отличает внутреннюю Flash от EEPROM A/B и неизвестного SPI-ROM запуска. */ +typedef uint16_t (*f28335_flash_read_word_t)(void *user, uint32_t address); /* Callback читает одно физическое слово без предположения о памяти host-тестов. */ +bool f28335_flash_app_validate(f28335_flash_read_word_t read_word, void *user, uint32_t *entry); /* Проверяет описание, границы и CRC32 до передачи управления приложению. */ +#endif /* Завершает единый контракт защищённой области Flash-приложения. */ diff --git a/c/protocan-boot/projects/.gitignore b/c/protocan-boot/projects/.gitignore new file mode 100644 index 0000000..70afdaf --- /dev/null +++ b/c/protocan-boot/projects/.gitignore @@ -0,0 +1,4 @@ +# Служебные и выходные файлы CCS остаются локальными; исходники проектов хранятся выше этих каталогов. +ccs/*/Debug/ +# Release использует собственные объекты, метаданные и архивы, чтобы не смешивать конфигурации. +ccs/*/Release/ diff --git a/c/protocan-boot/projects/README.md b/c/protocan-boot/projects/README.md new file mode 100644 index 0000000..97e6184 --- /dev/null +++ b/c/protocan-boot/projects/README.md @@ -0,0 +1,207 @@ +# Отдельные проекты CCS: F28335 и F2812 + +Весь комплект находится внутри `templates/c/protocan-boot`: проекты CCS, +исходники загрузчиков, аппаратные порты, linker command files, необходимая +поддержка TI, CLI-сборка, тесты и документация. Зависимости от исходников +`28335_periph` и `BALZAM_167` при сборке отсутствуют. Требуется установленный +TI C2000 compiler с поддержкой **COFF ABI**; проверена версия **22.6.0.LTS**. + +| Проект CCS | Контроллер | Обновляемая память | Схема | +| --- | --- | --- | --- | +| `ccs/f28335` — `F28335_CAN_AB` | TMS320F28335 | M95M02, 256 КиБ | A/B, trial, CONFIRM, rollback | +| `ccs/f2812` — `F2812_CAN_NOR` | TMS320F2812 / ПМ67 | AM29LV800BT-70EI, 1 МиБ, x16 | Один выделенный NOR-слот, проверяемый manifest, CAN recovery | + +F2812 не использует EEPROM. Его карта, GPIO, частота CAN, допустимые адреса +приложения и состояние протокола отделены от F28335. + +## Открытие в Code Composer Studio + +1. **Project → Import CCS Projects**, каталог поиска — `c/protocan-boot/projects/ccs`. +2. Выбрать `F28335_CAN_AB` и `F2812_CAN_NOR`. Оставить проекты в исходном + расположении: **не включать Copy projects into workspace**, поскольку + переносимые ссылки `PCAN_ROOT` ведут к общей библиотеке выше проектов. +3. Выбрать **Debug** либо **Release**, затем **Build Project**. Оба проекта + содержат собственные `.project`, `.cproject`, `.ccsproject`. +4. OUT/MAP появятся в `ccs/<контроллер>//`. + +В `targetConfigs` сохранены существующие конфигурации Sauris SAU510: +F28335 — Iso Plus v.2, F2812 — Iso Plus. Для другого адаптера выбрать свой +Connection в Target Configuration. Компиляция и импорт не подключаются к JTAG +и не программируют плату. + +Для отдельных workspace с ограниченными правами CCS допускает переменную +`TI_APPDATA_DIR` с доступным для записи каталогом. Это служебный cache IDE, +он не относится к исходникам загрузчиков. + +## Сборка без запуска IDE + +Из корня **templates**: + +```powershell +python c/protocan-boot/projects/build.py --device f28335 +python c/protocan-boot/projects/build.py --device f2812 +python c/protocan-boot/projects/build.py --device f28335 --configuration Release +python c/protocan-boot/projects/build.py --device f2812 --configuration Release +``` + +Можно передать `--compiler <каталог-ti-cgt-c2000>` и `--output <каталог>`. +Скрипт читает состав исходников и настройки из этих же CCS-проектов, полностью +пересобирает их и проверяет реальные COFF LOAD-адреса официальным `ofd2000`. +Проверка отклоняет загружаемый RAM-код без Flash LOAD, пересечения, отсутствующие +boot branch/C entry, запись CSM/OTP и посторонних внутренних секторов. +Рядом с OUT сохраняются MAP, `build.log` и manifest с SHA-256. + +Результаты: + +- `ccs/f28335/Debug/F28335_CAN_AB.out`; +- `ccs/f2812/Debug/F2812_CAN_NOR.out`. + +OUT — постоянный загрузчик для первоначальной установки через JTAG во +**внутреннюю Flash** соответствующего TMS. Образ самого приложения передаётся +по CAN в его внешнюю память. Для автоматического запуска должен быть выбран +внутренний Flash boot; у ПМ67 необходимо также учитывать штатную логику CPLD +выбора источника reset/boot из `big_dsp_module` платы. + +## Prebuild/postbuild и копирование в SETGUI + +В `.cproject` обоих проектов настроены **Debug и Release**. Prebuild вызывает +`projects/build.py --step prepare`: сохраняет UTC, Git-ревизию templates, +контроллер, конфигурацию и SHA-256 исходников в +`${BuildDirectory}/generated/canboot_build.json`. Это внешний паспорт сборки +загрузчика; номер версии приложения 167 не изменяется. + +Postbuild вызывает тот же скрипт с `--step postbuild`. Он требует подготовку +той же конфигурации и неизменные исходники, проверяет фактические COFF LOAD-адреса, +C entry и аппаратный boot-переход через TI `ofd2000`, затем сохраняет OUT/MAP, +`.out.manifest.json`, `.out.sha256` и `firmware_identity.json` в локальном архиве +`${BuildDirectory}/firmware/HASH_дата_UTC+3`. Manifest содержит контроллер, +Debug/Release, назначение `canboot`, адреса проверки и SHA-256 точного OUT. +`firmware/latest_build.json` указывает текущие локальную и экспортированную папки. + +Проверенный архив автоматически копируется в SETGUI по следующей схеме: + +```text +SETGUI/..periph_28335/firmware/periph28335/balzam167/canboot/ + 28335/HASH_дата_UTC+3/F28335_CAN_AB.out + 2812/HASH_дата_UTC+3/F2812_CAN_NOR.out +``` + +MAP, manifest, SHA-256 и метаданные лежат рядом с соответствующим OUT. +`..periph_28335` — буквальное имя существующего каталога SETGUI с двумя точками +в начале. Время имени папки берётся из prebuild; `+` после HASH означает изменения +в templates. Debug и Release имеют отдельные BuildDirectory и свои метаданные. + +В **Project Properties → Build → Steps** команды уже заполнены для обеих +конфигураций. Пример для F28335 Debug, каждая команда вводится одной строкой: + +```bat +python "${PROJECT_LOC}/../../build.py" --device f28335 --configuration Debug --compiler "${CG_TOOL_ROOT}" --output "${BuildDirectory}" --step prepare +python "${PROJECT_LOC}/../../build.py" --device f28335 --configuration Debug --compiler "${CG_TOOL_ROOT}" --output "${BuildDirectory}" --step postbuild --export "${PROJECT_LOC}/../../../../../../SETGUI/..periph_28335/firmware/periph28335/balzam167/canboot/28335" +``` + +Для F2812 используются `--device f2812` и конечная папка `2812`; для Release — +`--configuration Release`. При другом расположении SETGUI измените `--export` +в postbuild обеих конфигураций. Все пути с пробелами должны оставаться в кавычках. +CLI-сборка из раздела выше выполняет те же prepare/postbuild и копирует в эти же +каталоги; аргумент `--export <каталог>` переопределяет место копирования. +При ошибке компиляции, проверки OUT, отсутствии MAP или изменении исходников +после prebuild новый комплект в SETGUI не копируется. После изменения исходников +выполните **Rebuild Project**, чтобы обновить и OUT, и подготовку. + +В диалоге SETGUI **Flash JTAG (OUT)** для установки постоянного загрузчика F28335 +выбирайте `canboot/28335/HASH_дата_UTC+3/F28335_CAN_AB.out`. +`F2812_CAN_NOR.out` предназначен для JTAG соответствующего F2812. +Копирование файлов не запускает программирование платы и сетевую публикацию. + +## F28335 / M95M02 + +Проект использует существующий порт и формат журнала без изменения адресов: +**PERIPH 0–31: Type = 1 + PERIPH / 16, Device ID = PERIPH mod 16**. +УМП1 — **1/5**, УМП2 — **1/6**, задатчик — **1/8**. +Product **0x2833**, HW **1**, CAN **250000 бит/с**. Приложение и загрузчик +используют один аппаратный номер платы; прежний общий адрес **3/7** отменён. +Код загрузчика — внутренний сектор A `0x338000..0x33FF7F`, boot — `0x33FFF6`. +Слоты M95M02 имеют по **130560 октетов**, параметры — прежние 258 октетов +по адресу `0x3FEFC`. Приложение загружается в RAM ниже CPU word-адреса `0xE000`. + +После установки постоянного загрузчика новое приложение 167 передаётся +существующим клиентом SETGUI **CAN / ProtoCAN Boot**. Оно обязано содержать +hooks READY/CONFIRM и watchdog: пример интеграции реализован в ветке 167. +Без CONFIRM следующий reset возвращает подтверждённый active. +Полная последовательность — [документация порта F28335](../ports/tms320f28335/README.md). + +## F2812 / AM29LV800BT + +Профиль: **Device Type 3, Device ID 6, Product 0x2812, HW 1, +CAN 250000 бит/с, SYSCLKOUT 150 МГц**. CAN находится на **GPIOF6 TX / GPIOF7 RX**. +F2812 использует программную арифметику `rts2800_ml.lib`; F28335 — FPU32 +и `rts2800_fpu32.lib`. + +Внутренний сектор A загрузчика: `0x3F6000..0x3F7F7F`, boot — `0x3F7FF6`. +Внешняя NOR подключена по **CPU word-адресу `0x100000`**. Новый CAN-раздел +задан явно в `ports/tms320f2812/boot2812.h`: + +| Область | CPU word-адреса включительно | Размер | +| --- | --- | ---: | +| Существующая нижняя область: прежние образы/параметры/FPGA | `0x100000..0x15FFFF` | 768 КиБ | +| Новый SCI8 CAN-образ: обычные сектора 12/13/14 | `0x160000..0x177FFF` | **192 КиБ** | +| Неизменяемые этим загрузчиком top-boot сектора 15/16/17 | `0x178000..0x17DFFF` | 48 КиБ | +| Новый manifest: последний top-boot сектор 18 | `0x17E000..0x17FFFF` | 16 КиБ | + +Это **новое явное размещение CAN-образа**, а не автоматическое определение +свободного места в уже заполненном чипе. Перед первоначальной установкой +согласовать эти два выделенных участка с фактической картой NOR конкретной +платы. В известном исходнике FPGA начинается с `0x130000`, а новый CAN-слот +находится выше; драйвер не изменяет ничего ниже `0x160000` и в секторах 15–17. + +После reset доступно **3 секунды** для ENTER_BOOT. Открытая сессия удерживает +загрузчик; пустой/повреждённый manifest оставляет CAN recovery постоянно. +Для обновления уже работающего приложения нужно войти в это окно после reset; +приложение F2812 само по себе пока не получает обработчик ENTER_BOOT от добавления +отдельного проекта загрузчика. + +Перед записью требуется AMD manufacturer **`0x0001`**, device **`0x22DA`**. +Сначала стирается сектор manifest, затем три сектора образа. Запись проверяет +каждое слово. VERIFY повторно читает NOR, проверяет CRC32, SCI8, entry, +перекрытия и запрещённые назначения. COMMIT повторяет проверку, сохраняет +manifest с собственной CRC, два magic-слова публикуются последними. +Стирание сообщает BUSY каждые 250 мс, продлевая живую сессию. + +Это single-slot схема: при обрыве обновления последнего CAN-образа остаётся +recovery, автоматический A/B rollback для F2812 не заявляется. Полное стирание +NOR, запись внутренней Flash по CAN и программирование FPGA отсутствуют. + +Образ приложения — **TI SCI8 `AA 08`**, максимум **196608 октетов**. Старый +flat BIN основного контроллера автоматически не мигрируется. Допустимый payload: + +- L0 `0x8000..0x8EFF`; +- H0 `0x3F8000..0x3F9FFF`; +- внешняя SRAM zone2 `0x80000..0xFFFFF`. + +Стек M1, L1 `0x9000..0x9FFF`, RAM InitFlash `0x8F00..0x8FFF`, периферия, +внутренняя Flash и NOR не допускаются как назначения SCI8. `.ebss` приложения +может занять L1 после перехода в его C runtime; инициализированный payload +работающую RAM загрузчика перезаписывать не должен. Настройка приложения +F2812/его linker — отдельная от импорта загрузчика операция. + +Геометрия x16, ID и команды AA/55/A0/80/30/F0 взяты из +[оригинального datasheet AMD Am29LV800B](https://cms.nacsemi.com/content/AuthDatasheets/FASLS02690-1.pdf). +Аппаратные GPIO/CPLD и XINTF-тайминги перенесены из действующих +`big_dsp_module.c` / `flash_tools.c` ПМ67, без зависимости от этих файлов при сборке. + +## Проверки + +```powershell +$env:CC = 'C:/msys64/ucrt64/bin/gcc.exe' +python c/protocan-boot/tests/run_tests.py +``` + +Проверяются протокол, CRC, сессии/BUSY, A/B F28335 с trial/rollback/CONFIRM, +NOR F2812 с настоящими AMD command cycles, ID, readback, запрещёнными секторами, +обрывами COMMIT, повреждением CRC/SCI8 и тайм-аутом DQ7. +Вариант с CMake/CTest также поддерживается. + +Подтверждены реальные import/build обоих проектов в CCS 12.3, CLI-сборки +Debug/Release TI 22.6 COFF и проверки секций OUT. Физические JTAG/CAN/XINTF, +режим boot и поведение конкретной платы при отключении питания требуют стенда; +физическое программирование этим комплектом автоматически не выполнялось. diff --git a/c/protocan-boot/projects/STM32.md b/c/protocan-boot/projects/STM32.md new file mode 100644 index 0000000..ba4af27 --- /dev/null +++ b/c/protocan-boot/projects/STM32.md @@ -0,0 +1,69 @@ +# STM32: подключение исходных проектов к templates + +Канонические загрузочные реализации находятся в `c/protocan-boot/ports`. +В проектах сохранены прежние пути файлов, содержащие только include общего +исходника из их submodule. Это сохраняет внешний API и настройки Keil, +не оставляя локальных копий state machine, Flash writer или boot-control. + +| Проект | Submodule | Подключённый порт | Сборки | +|---|---|---|---| +| `KONOR_ds18b20` | `lib` | `stm32f103` CMSIS, BKP request, CAN/UART | Keil app и BOOT | +| `home/climate` | `third_party/templates` | `stm32f407` CMSIS boot, HAL app control | Keil app и BOOT | +| `CANdle_stm32` | `templates` | `stm32g474` HAL FDCAN/Flash, CAN/UART, startup/control | Keil app/BOOT, CMake app/BOOT | + +## Что перенесено + +- Общие `pcan_boot.c/.h` используются через submodule; устаревшая копия + `Libraries/ProtoCanBoot` climate заменена совместимыми include-обёртками. +- F103/F407 CMSIS transport, Flash, CRC readback, безопасный naked handoff, + single-slot callbacks и таймеры используют общий `boot_native.inc`. +- F103 UART firmware flow теперь использует имеющийся общий `rs485-boot`; + приложение KONOR продолжает использовать свой прикладной parser `proto.c`. +- G474 локальная CAN state machine полностью заменена текущим `pcan_boot`. + Единый Flash writer используется CAN/UART; вход из приложения и startup + также принадлежат `templates`. +- Конфигурации ядра заполняются по именам полей. Сохранены исходные Device ID, + скорости CAN/UART, границы Flash и режим одного логического слота A. +- В F407 BOOT и G474 app/BOOT linker исключает последние восемь байт используемой + SRAM, где хранится запрос обновления. Initial MSP G474 согласован с этим. +- В GCC-таблице IRQ G474 размер выведен из самого старшего назначенного IRQ: + прежний предел по USB_LP не вмещал USART1 и ломал CMake app-сборку. + +Clock tree, USB–CAN приложение, трансивер, GPIO board-support, настройки +программирования ST-Link и application linker остаются в исходных проектах. +Нативные `boot_main.c` не нужно компилировать вместе с альтернативным HAL boot +main в одном target. Изменения не прошивают подключённые устройства. + +## Зависимости и публикация + +CANdle получен из `https://git.rd12.ru/setcorp/CANdle_stm32.git`, исходный HEAD +`61a93c5`. Записанный там gitlink `templates` указывает на отсутствующий на +сервере объект `520788491c803e07ba1889e1fa60ed1550afb848`. Для локальной +интеграции submodule переключён на доступный локальный HEAD `templates`, +после чего текущие общие исходники синхронизированы в рабочее дерево. +Рабочие копии submodule KONOR/climate также содержат соответствующие текущие файлы. + +Подключение проверено локально. Для воспроизводимого нового клонирования +потребуется зафиксировать и опубликовать изменения `templates`, затем обновить +gitlinks в исходных проектах на этот доступный commit. Коммиты и push не являются +частью этой локальной интеграции; чужие незавершённые изменения не включались в commit. + +## Проверка + +21 октября 2026 года проверены настоящие Keil/Arm Compiler 6.22 сборки +BOOT и приложения каждого из трёх проектов. Все загрузчики помещаются в +исходные лимиты 12/32/32 КиБ. G474 дополнительно проверен ARM GCC/CMake +для `STM32G474VE_CAN_bootloader` и `STM32G474VE_DevBoard_fw`. + +Включённые в G474 BOOT строгие диагностики Arm Compiler выдают предупреждения +о layout структур, GNU-расширениях и обычном C-доступе к буферам в HAL/общих +модулях; компиляция и линковка завершаются без ошибок. GNU/newlib конфигурация +также сообщает о заглушках syscall при отключённом semihosting. Эти сообщения +не подавлялись общими флагами проекта. + +Host CMake/CTest: 10 тестов, включая три production HAL-порта. G474 проверяется +в DBANK=0 и DBANK=1: весь слот, переход между банками, отказ swap/неверной +плотности, все хвосты DATA, CRC readback, тайм-аут и TX ACK до reset. +Проверки интеграции climate подтверждают реальную цепочку include/Keil и границы +Flash/SRAM. Аппаратное обновление, питание и восстановление после обрыва на +физических платах в эту проверку не входят. diff --git a/c/protocan-boot/projects/build.py b/c/protocan-boot/projects/build.py new file mode 100644 index 0000000..7e24224 --- /dev/null +++ b/c/protocan-boot/projects/build.py @@ -0,0 +1,132 @@ +"""Сборка отдельных CCS-проектов ProtoCAN для F28335/M95M02 и F2812/AM29LV800BT.""" # Требует только Python и установленный TI C2000 COFF compiler. +import argparse # Разбирает выбранный контроллер, конфигурацию и пути toolchain. +import base64 # Читает настоящие программируемые данные COFF из официального OFD XML. +from datetime import datetime, timezone # Фиксирует момент prebuild в UTC; имя архива общий модуль переводит в UTC+3. +import hashlib # Связывает собранный OUT с контрольной суммой в локальном build manifest. +import importlib.util # Подключает общий экспорт firmware-info без копирования его алгоритма архивирования. +import json # Сохраняет точные команды, происхождение исходников и результаты проверки. +from pathlib import Path # Разрешает все зависимости внутри templates относительно расположения проекта. +import subprocess # Вызывает установленный TI compiler без shell-интерполяции аргументов. +import xml.etree.ElementTree as ET # Использует действующие .project/.cproject как источник состава и опций сборки. + +ROOT = Path(__file__).resolve().parents[1] # Корень protocan-boot содержит codec, порты, проекты и vendored TI support. +DEFAULT_COMPILER = Path("C:/ti/ccs1230/ccs/tools/compiler/ti-cgt-c2000_22.6.0.LTS") # Сохраняет проверенную версию установленного C2000 COFF compiler. + + +def settings(device, configuration, compiler): # Читает те же исходники и пути, которые получает импортированный проект CCS. + project = ROOT / "projects/ccs" / device # Каждое семейство контроллера имеет собственный Eclipse projectDescription. + config = next(item for item in ET.parse(project / ".cproject").findall(".//configuration") if item.get("name") == configuration) # Не подменяет Debug настройками Release или другого устройства. + options = {item.get("superClass", "").rsplit(".", 1)[-1]: item for item in config.findall("folderInfo/toolChain/tool/option")} # Собирает только параметры общего folderInfo без переопределений отдельных файлов. + macros = {"${PROJECT_ROOT}": str(project), "${PROJECT_LOC}": str(project), "${CG_TOOL_ROOT}": str(compiler)} # Разрешает только известные пути, не выполняя shell-подстановки. + def values(name): # Возвращает listOptionValue после подстановки локальных макросов CCS. + result = [] # Порядок include paths и библиотек остаётся тем же, что в проекте. + for item in options[name].findall("listOptionValue"): # Обрабатывает каждое явное значение текущей конфигурации. + value = item.get("value", "") # Отсутствующее значение не превращается в имя неизвестного каталога. + for macro, replacement in macros.items(): value = value.replace(macro, replacement) # Ограничивает подстановки определёнными выше путями. + if "${" in value: raise ValueError("Unresolved CCS macro: " + value) # Останавливает сборку вместо поиска случайной зависимости на машине. + result.append(value) # Добавляет параметр в исходном порядке конфигурации CCS. + return result # Возвращает обычные аргументы без скрытых изменений окружения. + sources = sorted(project.glob("*.c")) + sorted(project.glob("*.asm")) # Локальные production-исходники проекта компилируются вместе с аппаратным портом. + commands = sorted(project.glob("*.cmd")) # Каждый проект имеет собственную разметку памяти соответствующего F28xx. + for link in ET.parse(project / ".project").findall(".//linkedResources/link"): # Добавляет только explicit linkedResources из templates. + uri = link.findtext("locationURI", "") # Все общие исходники привязаны к переменной PCAN_ROOT. + if not uri.startswith("PCAN_ROOT/"): raise ValueError("Unsupported linked resource: " + uri) # Не допускает зависимость от старого firmware checkout или абсолютного чужого пути. + path = ROOT / uri.removeprefix("PCAN_ROOT/") # Разрешает vendor и общие исходники внутри переносимого protocan-boot. + if path.suffix.lower() in (".c", ".asm"): sources.append(path) # Заголовки не компилируются самостоятельными единицами трансляции. + elif path.suffix.lower() == ".cmd": commands.append(path) # Подключает оригинальное TI размещение регистров выбранного контроллера. + flags = ["-v28", "-ml", "-mt", "--abi=coffabi", "-O" + options["OPT_LEVEL"].get("value").rsplit(".", 1)[-1], "--opt_for_speed=" + options["OPT_FOR_SPEED"].get("value").rsplit(".", 1)[-1], "--gen_func_subsections=on"] # Повторяет архитектуру COFF, большие адреса, оптимизацию и сборку отдельных функций проекта CCS. + if device == "f28335": flags.append("--float_support=fpu32") # Только F28335 имеет используемый аппаратный FPU32. + flags += ["--include_path=" + value for value in values("INCLUDE_PATH")] + ["--define=" + value for value in values("DEFINE")] # Передаёт конкретные аппаратные заголовки и profile defines без потери различий между контроллерами. + if configuration == "Debug": flags.append("-g") # Debug OUT сохраняет символы для пошагового JTAG-анализа загрузчика. + return project, config.get("artifactName"), flags, sources, commands, values("LIBRARY"), values("SEARCH_PATH") # Возвращает полный воспроизводимый набор исходников и linker inputs. + + +def verify(device, image, compiler): # Проверяет реальные секции OUT после линковки, а не только текст соседнего MAP. + xml = ET.fromstring(subprocess.check_output([str(compiler / "bin/ofd2000.exe"), "-x", str(image)])) # Официальный декодер TI читает COFF текущей завершившейся сборки. + coff = xml.find(".//ti_coff") # Загружать через JTAG разрешено именно executable C2000 COFF. + if coff is None or coff.findtext("file_header/exec") != "true" or coff.findtext("file_header/target_id") != "0x9d": raise ValueError("Expected executable C2000 COFF") # Не подписывает чужой объект, ELF либо незалинкованный файл. + first, end, boot = (0x338000, 0x33FF80, 0x33FFF6) if device == "f28335" else (0x3F6000, 0x3F7F80, 0x3F7FF6) # Адреса внутренних секторов A и аппаратных boot-переходов различаются между F28335/F2812. + loaded = set() # Повторная загрузка одного физического слова из двух секций запрещена. + for section in coff.findall("section"): # Рассматривает только реальные данные секций после линковки. + address = int(section.findtext("virtual_addr", "0"), 0); raw = section.findtext("raw_data") # COFF virtual_addr обозначает LOAD, physical_addr — RUN копируемых ramfuncs. + if raw is None or section.findtext("copy") == "true" or section.findtext("name") == ".adc_cal": continue # Исключает только явные COPY/отладочные секции, BSS без raw_data и заводскую ADC-калибровку; загружаемый RAM-код обязан иметь Flash LOAD. + data = base64.b64decode(raw) # Читает точные октеты программируемого содержимого из COFF, а не считает по объявленному размеру. + if len(data) % 2 or not (first <= address < address + len(data) // 2 <= end or address == boot and len(data) == 4): raise ValueError("Loaded section outside bootloader Flash: " + str(section.findtext("name"))) # Защищает OTP, CSM, внешнюю NOR/EEPROM и остальные внутренние секторы. + for word in range(address, address + len(data) // 2): # Контролирует физические 16-битные слова всех программируемых секций. + if word in loaded: raise ValueError("Overlapping load sections") # Даже совпадающие данные не разрешают неоднозначную разметку OUT. + loaded.add(word) # Фиксирует фактически загружаемый диапазон текущего результата. + entry = int(coff.findtext("optional_file_header/entry_point", "0"), 0) # Извлекает реальную точку входа C runtime из заголовка файла. + if entry not in loaded or boot not in loaded or boot + 1 not in loaded: raise ValueError("Missing loaded C entry or codestart") # JTAG OUT обязан одновременно содержать C startup и аппаратный Flash boot переход. + return {"entry_word": entry, "boot_word": boot, "loaded_words": len(loaded)} # Эти проверенные значения входят в build manifest рядом с SHA-256. + + +def identity_tools(): # CCS и CLI используют общий формат имени папки, manifest и SHA-256 из templates. + spec = importlib.util.spec_from_file_location("canboot_identity", ROOT.parent / "firmware-info/tools/identity.py") # firmware-info расположен рядом с protocan-boot внутри каталога c. + module = importlib.util.module_from_spec(spec) # Загрузка не резервирует версию и не создаёт артефакты приложения 167. + spec.loader.exec_module(module) # Выполняет только объявления общего модуля подготовки и локального экспорта. + return module # Вызывающий получает единую реализацию архивирования без сетевой публикации. + + +def source_hashes(device): # Связывает prebuild и postbuild с исходниками выбранного загрузчика, включая включаемые C-файлы и заголовки. + folders = [ROOT / "include", ROOT / "src", ROOT / "ports" / ("tms320" + device), ROOT / "vendor/ti" / device, ROOT / "projects/ccs" / device] # Общий автомат разделяется, аппаратные файлы второго контроллера в паспорт не попадают. + files = {ROOT / "projects/build.py"} # Изменение самого процесса между подготовкой и копированием требует нового prebuild. + for folder in folders: # Проверяет production-файлы библиотеки, порта, TI support и текущего CCS-проекта. + files.update(path for path in folder.rglob("*") if path.is_file() and path.suffix.lower() in (".c", ".h", ".asm", ".cmd", ".inc") and not {"Debug", "Release", "generated", "firmware"}.intersection(path.relative_to(folder).parts[:-1])) # Исключает результаты сборки; адреса памяти и аппаратные defines входят через CMD/H. + files.update(ROOT / "projects/ccs" / device / name for name in (".project", ".cproject", ".ccsproject")) # Настройки ABI, include paths и список linkedResources тоже должны оставаться неизменными. + return {path.relative_to(ROOT).as_posix(): hashlib.sha256(path.read_bytes()).hexdigest() for path in sorted(files)} # SHA-256 относится к точным байтам каждого исходного файла до компиляции. + + +def prepare(device, configuration, compiler, output): # Prebuild фиксирует происхождение именно той конфигурации, которую затем линкует CCS либо CLI. + project, name, *_ = settings(device, configuration, compiler) # Проверяет наличие выбранного проекта и узнаёт штатное имя OUT. + identity = identity_tools(); source = identity.git_state(ROOT.parents[1]) # Корень templates содержит Git-ревизию самостоятельных CAN boot проектов. + metadata = {"schema": 1, "product": name, "target": "TMS320" + device.upper(), "device": device, "configuration": configuration, "execution": "FLASH", "image_format": "COFF", "purpose": "canboot", "built_at_utc": datetime.now(timezone.utc).replace(microsecond=0).isoformat(), "source": source, "sources": source_hashes(device)} # Внешний паспорт описывает постоянный загрузчик; версию и встроенный паспорт приложения не имитирует. + identity.write_atomic(output / "generated/canboot_build.json", json.dumps(metadata, ensure_ascii=False, indent=2) + "\n") # Отдельный BuildDirectory не позволяет Debug и Release перезаписать подготовку друг друга. + return metadata # Позволяет проверить подготовку без запуска компилятора или доступа к плате. + + +def postbuild(device, configuration, compiler, output, export=None): # Проверяет готовый OUT и копирует только текущий комплект в папку соответствующего контроллера SETGUI. + output = output.resolve(); project, name, *_ = settings(device, configuration, compiler) # Имена OUT/MAP берутся из активной конфигурации CCS, а не из поиска старых сборок. + metadata = json.loads((output / "generated/canboot_build.json").read_text(encoding="utf-8")) # Без успешного prebuild выпуск останавливается до изменения каталога GUI. + if metadata.get("device") != device or metadata.get("configuration") != configuration or metadata.get("sources") != source_hashes(device): # Не допускает паспорт другой конфигурации или изменения исходников после подготовки. + raise ValueError("CAN boot sources/configuration changed: run prebuild and rebuild") # Требует согласованную пересборку вместо копирования неподтверждённого результата. + image = output / (name + ".out"); map_path = image.with_suffix(".map") # Оба файла принадлежат одному штатному результату линковки. + if not map_path.is_file(): raise ValueError("Missing CAN boot MAP: " + str(map_path)) # Неполный комплект не попадает в папку установки через JTAG. + metadata.update(verify(device, image, compiler)) # Повторно проверяет COFF LOAD-адреса, C entry и boot branch перед каждым экспортом из CCS или CLI. + identity = identity_tools(); metadata_path = output / "canboot_build.json" # Сохраняет проверенный внешний паспорт отдельно от исходной записи prebuild. + identity.write_atomic(metadata_path, json.dumps(metadata, ensure_ascii=False, indent=2) + "\n") # Диапазоны Flash и SHA исходников доступны рядом с локальным результатом. + identity.seal(image, metadata_path) # Manifest и SHA-256 рядом с OUT подписывают точные байты файла для JTAG. + destination = export if export is not None else ROOT.parents[2] / "SETGUI/..periph_28335/firmware/periph28335/balzam167/canboot" / device.removeprefix("f") # Сохраняет ожидаемую структуру 167/canboot/28335 и 167/canboot/2812 относительно соседнего SETGUI. + result = identity.archive_build(image, metadata_path, output / "firmware", extra_files=[map_path], export=destination) # Общий архиватор переносит только OUT, MAP, manifest, SHA-256 и метаданные текущего выпуска. + identity.write_atomic(output / "firmware/latest_build.json", json.dumps(result, ensure_ascii=False, indent=2) + "\n") # Указывает точные локальную и скопированную папки последнего успешного выпуска. + return image # Совместимый CLI по-прежнему возвращает путь проверенного OUT для первоначальной установки через JTAG. + + +def build(device, configuration, compiler, output=None, export=None): # Полностью собирает выбранный проект и экспортирует проверенный загрузчик без установки на плату. + compiler = compiler.resolve(); project, name, flags, sources, commands, libraries, searches = settings(device, configuration, compiler) # Использует абсолютный toolchain и актуальную конфигурацию CCS. + output = (output or project / configuration).resolve(); output.mkdir(parents=True, exist_ok=True) # Генерирует результаты только в каталоге выбранной сборки. + prepare(device, configuration, compiler, output) # CLI выполняет тот же prebuild, который настроен в управляемом проекте CCS. + objects = [] # В линковку входят только успешно пересобранные исходники текущего вызова. + with (output / "build.log").open("w", encoding="utf-8") as log: # Журнал содержит полный набор команд и диагностику TI. + def run(command): # Не продолжает сборку после ошибки компилятора или linker. + log.write(json.dumps([str(arg) for arg in command], ensure_ascii=False) + "\n"); log.flush() # Сохраняет команду до запуска процесса без исполнения как shell-кода. + subprocess.run([str(arg) for arg in command], cwd=project, stdout=log, stderr=subprocess.STDOUT, check=True) # Ненулевой статус исключает публикацию ложного успешного результата. + for source in sources: # Все локальные и linked TI-файлы пересобираются для выбранного контроллера. + obj = output / (source.stem + ".obj"); run([compiler / "bin/cl2000.exe", *flags, "-c", "--output_file=" + str(obj), source]); objects.append(obj) # Объекты F2812 soft-float и F28335 FPU32 не смешиваются. + image = output / (name + ".out") # Имя результата совпадает с artifactName импортированного CCS-проекта. + link = [compiler / "bin/cl2000.exe", "-v28", "--abi=coffabi"] + (["--float_support=fpu32"] if device == "f28335" else []) # Linker ABI и FPU точно соответствуют скомпилированным объектам. + run([*link, "-z", "--rom_model", "--entry_point=_c_int00", "--stack_size=0x3f0", "--warn_sections", "--reread_libs", "-m" + str(image.with_suffix(".map")), "-o", image, *["--search_path=" + value for value in searches], *commands, *objects, *["-l" + value for value in libraries]]) # Подключает только собственный linker и оригинальные peripheral sections выбранного MCU. + return postbuild(device, configuration, compiler, output, export) # CCS и CLI проверяют и копируют готовый комплект единственной общей функцией. + + +if __name__ == "__main__": # Импорт для проверки проектов не запускает compiler автоматически. + parser = argparse.ArgumentParser(description=__doc__) # Описывает два самостоятельных проекта и отсутствие программирования платы. + parser.add_argument("--device", choices=("f2812", "f28335"), required=True) # Не допускает случайной сборки для другого контроллера. + parser.add_argument("--configuration", choices=("Debug", "Release"), default="Debug") # Повторяет имена управляемых конфигураций CCS. + parser.add_argument("--compiler", type=Path, default=DEFAULT_COMPILER) # Поддерживает другую установленную версию TI с COFF ABI. + parser.add_argument("--output", type=Path) # Разрешает изолированную проверочную сборку без загрязнения импортированного CCS-проекта. + parser.add_argument("--step", choices=("build", "prepare", "postbuild"), default="build") # CCS запускает подготовку до компиляции и экспорт после своей линковки; CLI по умолчанию выполняет весь цикл. + parser.add_argument("--export", type=Path) # Переопределяет корень архивов 28335 либо 2812 при другом расположении SETGUI. + args = parser.parse_args(); output = (args.output or ROOT / "projects/ccs" / args.device / args.configuration).resolve() # Явный BuildDirectory CCS и CLI используют одинаковый формат результата. + if args.step == "prepare": prepare(args.device, args.configuration, args.compiler, output); print(output / "generated/canboot_build.json") # Фиксирует подготовку и выводит короткий путь к её паспорту без длинного списка SHA исходников. + elif args.step == "postbuild": print(postbuild(args.device, args.configuration, args.compiler, output, args.export)) # Проверяет OUT/MAP активного BuildDirectory и экспортирует один комплект. + else: print(build(args.device, args.configuration, args.compiler, output, args.export)) # Полный CLI-цикл включает те же подготовку и копирование, что CCS. diff --git a/c/protocan-boot/projects/ccs/f2812/.ccsproject b/c/protocan-boot/projects/ccs/f2812/.ccsproject new file mode 100644 index 0000000..335c4fd --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/.ccsproject @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/c/protocan-boot/projects/ccs/f2812/.cproject b/c/protocan-boot/projects/ccs/f2812/.cproject new file mode 100644 index 0000000..b83628a --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/.cproject @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/c/protocan-boot/projects/ccs/f2812/.project b/c/protocan-boot/projects/ccs/f2812/.project new file mode 100644 index 0000000..49210b8 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/.project @@ -0,0 +1,106 @@ + + + + F2812_CAN_NOR + + Отдельный постоянный загрузчик ProtoCAN для F2812 + + + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + + + + + + + + com.ti.ccstudio.core.ccsNature + + org.eclipse.cdt.core.cnature + + org.eclipse.cdt.core.ccnature + + org.eclipse.cdt.managedbuilder.core.managedBuildNature + + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + + + + ti/DSP281x_CpuTimers.c + + 1 + + PCAN_ROOT/vendor/ti/f2812/source/DSP281x_CpuTimers.c + + + + + ti/DSP281x_GlobalVariableDefs.c + + 1 + + PCAN_ROOT/vendor/ti/f2812/source/DSP281x_GlobalVariableDefs.c + + + + + ti/DSP281x_PieCtrl.c + + 1 + + PCAN_ROOT/vendor/ti/f2812/source/DSP281x_PieCtrl.c + + + + + ti/DSP281x_SysCtrl.c + + 1 + + PCAN_ROOT/vendor/ti/f2812/source/DSP281x_SysCtrl.c + + + + + ti/DSP281x_usDelay.asm + + 1 + + PCAN_ROOT/vendor/ti/f2812/source/DSP281x_usDelay.asm + + + + + DSP281x_Headers_nonBIOS.cmd + + 1 + + PCAN_ROOT/vendor/ti/f2812/cmd/DSP281x_Headers_nonBIOS.cmd + + + + + + + + PCAN_ROOT + + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/c/protocan-boot/projects/ccs/f2812/F2812_CAN_NOR.cmd b/c/protocan-boot/projects/ccs/f2812/F2812_CAN_NOR.cmd new file mode 100644 index 0000000..d47c8ac --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/F2812_CAN_NOR.cmd @@ -0,0 +1,28 @@ +MEMORY /* Постоянный загрузчик F2812 хранится во внутренней Flash, обновляемые данные — во внешней AM29LV800BT. */ +{ /* Адреса указаны в 16-битных словах C28x, независимо от размера файлов CAN. */ +PAGE 0: /* Исполняемый код и его копируемая RAM-часть. */ + FLASHA : origin = 0x3F6000, length = 0x001F80 /* Сектор A исключает зарезервированные слова CSM в верхних 128 словах. */ + BEGIN : origin = 0x3F7FF6, length = 0x000002 /* Аппаратный Flash boot F2812 начинает длинный переход из двух слов. */ + RAMFUNCS : origin = 0x008F00, length = 0x000100 /* Последние 256 слов L0 содержат InitFlash и исключены из SCI8 payload приложения. */ + RESET : origin = 0x3FFFC0, length = 0x000002 /* ROM reset не программируется при установке загрузчика. */ +PAGE 1: /* Рабочая RAM постоянно работающего загрузчика не должна входить в загружаемый файл. */ + RAMM0 : origin = 0x000050, length = 0x0003B0 /* Исключает первые 80 слов Boot ROM scratch. */ + RAMM1 : origin = 0x000400, length = 0x000400 /* Отдельный стек на 1024 слова совпадает с аппаратным банком M1. */ + RAMDATA : origin = 0x009000, length = 0x001000 /* Банк L1 хранит очередь CAN и состояния загрузчика до перехода в приложение. */ +} /* Верхний H0 и внешняя SRAM остаются доступны payload приложения. */ +SECTIONS /* Ни одна загружаемая секция OUT не записывается во внешнюю NOR автоматически. */ +{ /* Все команды программирования NOR исполняются из внутреннего сектора A. */ + codestart : > BEGIN, PAGE = 0 /* Направляет аппаратный boot в watchdog-safe C startup. */ + .text : > FLASHA, PAGE = 0 /* Размещает общий ProtoCAN, driver NOR и проверку SCI8 в постоянной Flash. */ + .fast_run : > FLASHA, PAGE = 0 /* Штатный DSP281x_usDelay вызывается ещё из InitSysCtrl до копирования ramfuncs, поэтому его LOAD/RUN должны сразу находиться во Flash. */ + .cinit : > FLASHA, PAGE = 0 /* Таблицы ROM-модели инициализируют состояние до main. */ + .pinit : > FLASHA, PAGE = 0 /* Сохраняет стандартный startup для возможных статических конструкторов. */ + .econst : > FLASHA, PAGE = 0 /* Константы не расходуют ограниченную RAM L1. */ + .switch : > FLASHA, PAGE = 0 /* Таблицы switch остаются доступны во время erase внешнего чипа. */ + ramfuncs : LOAD = FLASHA, RUN = RAMFUNCS, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), RUN_START(_RamfuncsRunStart), PAGE = 0 /* InitFlash копируется в внутреннюю RAM до изменения таймингов Flash. */ + .stack : > RAMM1, PAGE = 1 /* Стек не пересекает RAM назначения проверяемого образа. */ + .ebss : > RAMDATA, PAGE = 1 /* Состояния очереди и текущей сессии исключены из разрешённых SCI8 адресов. */ + .esysmem : > RAMDATA, PAGE = 1 /* Поддерживает стандартную секцию runtime, хотя алгоритм не требует heap. */ + .fast_vars1 : > RAMDATA, PAGE = 1 /* Подключает штатный HSPCLK выбранного TI SDK без размещения случайной orphan-секции. */ + .reset : > RESET, PAGE = 0, TYPE = DSECT /* Не выдаёт ROM reset за программируемую часть OUT. */ +} /* Не создаёт секции OTP или паролей CSM. */ diff --git a/c/protocan-boot/projects/ccs/f2812/board.c b/c/protocan-boot/projects/ccs/f2812/board.c new file mode 100644 index 0000000..e19e090 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/board.c @@ -0,0 +1,30 @@ +#include "DSP281x_Device.h" /* Использует оригинальные TI определения GPIO и XINTF F2812. */ +#include "../../../ports/tms320f2812/boot2812.h" /* Получает отдельный аппаратный профиль внешней NOR ПМ67. */ +static void operation(unsigned int a, unsigned int b, unsigned int c, unsigned int d) /* Повторяет управляющую защёлку CPLD из big_dsp_module.c штатной платы. */ +{ /* GPIOA13/A14/A15 и GPIOB13 задают код, GPIOB15 формирует строб. */ + EALLOW; /* Разрешает запись системных GPIO платы. */ + GpioDataRegs.GPADAT.bit.GPIOA13 = a; GpioDataRegs.GPADAT.bit.GPIOA14 = b; /* Первые два бита аппаратной команды соответствуют oper_mode1/2. */ + GpioDataRegs.GPADAT.bit.GPIOA15 = c; GpioDataRegs.GPBDAT.bit.GPIOB13 = d; /* Третий и четвёртый биты повторяют штатный write_oper. */ + asm(" NOP"); GpioDataRegs.GPBDAT.bit.GPIOB15 = 0; /* Снимает строб после установки всех четырёх битов команды. */ + asm(" RPT #2 || NOP"); GpioDataRegs.GPBDAT.bit.GPIOB15 = 1; /* Даёт защёлке время установления и формирует активный фронт. */ + asm(" RPT #2 || NOP"); GpioDataRegs.GPBDAT.bit.GPIOB15 = 0; /* Возвращает строб в исходное состояние с выдержкой как в рабочем драйвере. */ + asm(" RPT #2 || NOP"); EDIS; /* Завершает длительность импульса до следующей команды CPLD. */ +} /* Команда не изменяет выбранные аппаратные boot-перемычки контроллера. */ +void Boot2812_BoardInit(void) /* Настраивает подтверждённую схему ПМ67 с AM29LV800BT на XINTF zone6. */ +{ /* Значения линий взяты из setup_oper_line/init_flash/xintf_zone6and7_timing действующего проекта BALZAM_167. */ + EALLOW; /* GPIO mux/direction и XINTF изменяются в разрешённом защищённом контексте. */ + GpioMuxRegs.GPAMUX.bit.C1TRIP_GPIOA13 = 0; GpioMuxRegs.GPAMUX.bit.C2TRIP_GPIOA14 = 0; GpioMuxRegs.GPAMUX.bit.C3TRIP_GPIOA15 = 0; /* Выбирает GPIO для трёх командных линий CPLD вместо функций event manager. */ + GpioMuxRegs.GPBMUX.bit.C4TRIP_GPIOB13 = 0; GpioMuxRegs.GPBMUX.bit.C6TRIP_GPIOB15 = 0; /* Освобождает четвёртый бит команды и строб CPLD. */ + GpioMuxRegs.GPADIR.bit.GPIOA13 = 1; GpioMuxRegs.GPADIR.bit.GPIOA14 = 1; GpioMuxRegs.GPADIR.bit.GPIOA15 = 1; /* Переводит командные линии A в выходы, как рабочий драйвер платы. */ + GpioMuxRegs.GPBDIR.bit.GPIOB13 = 1; GpioMuxRegs.GPBDIR.bit.GPIOB15 = 1; /* Разрешает выдачу четвёртого бита и импульса защёлки. */ + XintfRegs.XINTCNF2.bit.XTIMCLK = 1; XintfRegs.XINTCNF2.bit.WRBUFF = 0; /* XTIMCLK=SYSCLKOUT/2; отключённая буферизация сохраняет порядок unlock-циклов AMD. */ + XintfRegs.XINTCNF2.bit.CLKOFF = 0; XintfRegs.XINTCNF2.bit.CLKMODE = 0; XintfRegs.XINTCNF2.bit.MPNMC = 0; /* Повторяет штатный режим XCLKOUT и микроконтроллерный boot платы. */ + XintfRegs.XTIMING6.bit.XWRLEAD = 3; XintfRegs.XTIMING6.bit.XWRACTIVE = 7; XintfRegs.XTIMING6.bit.XWRTRAIL = 3; /* Времена записи NOR повторяют проверенный flash_tools/init_flash платы в единицах XTIMCLK. */ + XintfRegs.XTIMING6.bit.XRDLEAD = 3; XintfRegs.XTIMING6.bit.XRDACTIVE = 3; XintfRegs.XTIMING6.bit.XRDTRAIL = 3; /* Времена чтения соответствуют штатному профилю AM29LV800BT-70EI. */ + XintfRegs.XTIMING6.bit.X2TIMING = 0; XintfRegs.XTIMING6.bit.USEREADY = 0; XintfRegs.XTIMING6.bit.READYMODE = 0; XintfRegs.XTIMING6.bit.XSIZE = 3; /* Выбирает 16-битную зону без внешнего READY и без дополнительного удвоения тактов. */ + XintfRegs.XTIMING2.bit.XWRLEAD = 3; XintfRegs.XTIMING2.bit.XWRACTIVE = 7; XintfRegs.XTIMING2.bit.XWRTRAIL = 3; /* Консервативный x16 режим внешней SRAM позволяет загружать приложение в zone2. */ + XintfRegs.XTIMING2.bit.XRDLEAD = 3; XintfRegs.XTIMING2.bit.XRDACTIVE = 7; XintfRegs.XTIMING2.bit.XRDTRAIL = 3; /* Удлинённое чтение SRAM не зависит от коротких прикладных таймингов. */ + XintfRegs.XTIMING2.bit.X2TIMING = 0; XintfRegs.XTIMING2.bit.USEREADY = 0; XintfRegs.XTIMING2.bit.READYMODE = 0; XintfRegs.XTIMING2.bit.XSIZE = 3; /* Не включает неподтверждённую линию READY платы. */ + asm(" RPT #7 || NOP"); EDIS; /* Сбрасывает pipeline после изменения XINTF до первого внешнего чтения. */ + operation(1U, 1U, 1U, 1U); operation(1U, 0U, 1U, 0U); operation(0U, 0U, 0U, 0U); /* Штатные select_nothing, select_strob_67_for_flash, select_work_with_flash выбирают CPU-доступ к NOR. */ +} /* Изменение схемы CPLD требует отдельного профиля платы, а не другого размера EEPROM. */ diff --git a/c/protocan-boot/projects/ccs/f2812/boot_store.c b/c/protocan-boot/projects/ccs/f2812/boot_store.c new file mode 100644 index 0000000..e825b09 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/boot_store.c @@ -0,0 +1 @@ +#include "../../../ports/tms320f2812/boot_store.c" /* Подключает проверку SCI8 и публикацию NOR manifest без копирования кода в проект CCS. */ diff --git a/c/protocan-boot/projects/ccs/f2812/codestart.asm b/c/protocan-boot/projects/ccs/f2812/codestart.asm new file mode 100644 index 0000000..b69fe2f --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/codestart.asm @@ -0,0 +1,12 @@ + .ref _c_int00 ; Стандартный COFF startup применяет .cinit и вызывает main после отключения раннего watchdog. + .sect "codestart" ; Boot ROM передаёт управление двухсловному переходу по аппаратному адресу слова 0x33FFF6. + LB flash_boot_start ; Переходит к короткой подготовке C28x во Flash, сохраняя точный размер аппаратного входа два слова. + .text ; Последовательность взята из штатного TI DSP2833x_CodeStartBranch.asm и размещается в секторе основного кода. +flash_boot_start: ; Отключает watchdog до возможной длительной обработки таблиц инициализации C, а не только после входа в main. + SETC OBJMODE ; Выбирает C28x object mode, требуемый стандартным COFF startup процессора F28335. + EALLOW ; Разрешает запись защищённого регистра WDCR перед запуском C runtime. + MOVZ DP, #7029h>>6 ; Адрес слова WDCR=0x7029 из карты F28335; DP выбирает соответствующую страницу по 64 слова. + MOV @7029h, #0068h ; Значение 0x0068 содержит контрольные биты WDCHK=101 и WDDIS=1, как официальный TI startup. + EDIS ; Возвращает защиту системных регистров перед переходом в библиотечную инициализацию. + LB _c_int00 ; Применяет штатную ROM-модель инициализации и затем запускает текущий main 167. + .end ; Завершает модуль, не добавляя произвольных данных рядом с CSM-паролями сектора A. diff --git a/c/protocan-boot/projects/ccs/f2812/main.c b/c/protocan-boot/projects/ccs/f2812/main.c new file mode 100644 index 0000000..880a3f0 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/main.c @@ -0,0 +1,114 @@ +#include "DSP281x_Device.h" /* Использует оригинальные регистры F2812, не подменяя их заголовками F28335. */ +#include "DSP281x_Examples.h" /* Подключает штатные PLL, watchdog, PIE и CpuTimers выбранного TI SDK. */ +#include "../../../ports/tms320f2812/boot2812.h" /* Выбирает отдельные NOR, Product Type и ProtoCAN-адрес F2812. */ +#include /* Инициализирует все состояния независимо от прежнего содержимого .ebss. */ +static pcan_boot_t boot; /* Этот экземпляр относится только к ПМ67/F2812 и не делит состояние с F28335. */ +static volatile unsigned int head, tail, overflow; /* ISR публикует готовые элементы очереди только после заполнения всех полей. */ +static struct { uint32_t id; unsigned int dlc; pcan_boot_byte_t data[8]; } queue[32]; /* Очередь на 31 кадр принимает окно из 16 блоков во время NOR-операций main. */ +static unsigned int tx_busy, reset_requested, operation_active, current_command; /* Отделяет физическое TX ACK, запрос reset и текущую долгую команду. */ +static uint32_t sent_at, busy_at; /* Миллисекундные отметки ограничивают TX и частоту BUSY-ответов. */ +unsigned long Boot2812_Now(void) /* Все тайм-ауты порта работают от одного Timer1. */ +{ /* Прямой счётчик C28x имеет ту же ширину, что uint32_t. */ + return CpuTimer1.InterruptCount; /* Период Timer1 ниже установлен в одну миллисекунду. */ +} /* Беззнаковые разности сохраняют корректность через переполнение. */ +interrupt void boot_tick(void) /* Прямое прерывание Timer1 не обращается к коду приложения. */ +{ /* Долгие erase/verify не должны замораживать часы либо приём CAN. */ + CpuTimer1.InterruptCount++; KickDog(); /* Миллисекундный tick и штатное обслуживание watchdog загрузчика выполняются даже во время polling NOR. */ +} /* Поведение watchdog загружаемого приложения задаёт его собственный startup. */ +static void receive(volatile struct MBOX *box, uint32_t mask) /* Копирует один Extended кадр выделенного mailbox в очередь. */ +{ /* Wire-парсер и запись памяти выполняются позднее общим ядром в main. */ + unsigned int next = (head + 1U) & 31U, i, type; uint32_t id, low, high; /* Индексы кольца ограничены 32 элементами независимо от содержимого CAN. */ + if (!(ECanaRegs.CANRMP.all & mask)) return; /* Не читает старое содержимое mailbox без нового RX-флага. */ + id = box->MSGID.all & 0x1FFFFFFFUL; type = pcan_boot_id_msg_type(id); /* Получает 29-битный ID и тип через общий codec. */ + if ((box->MSGID.all & 0x80000000UL) && !box->MSGCTRL.bit.RTR && pcan_boot_id_route(id) == 0U && (type == 9U || type == 10U || type == 13U) && ((pcan_boot_id_device_type(id) == BOOT2812_DEVICE_TYPE && pcan_boot_id_device_id(id) == BOOT2812_DEVICE_ID) || (type == 13U && pcan_boot_id_device_type(id) == 7U && pcan_boot_id_device_id(id) == 15U && !pcan_boot_id_msg_body(id)))) { /* Допускает только адресный Boot и точное discovery; чужие приборы и RTR не занимают очередь. */ + if (next == tail) overflow = 1U; /* Потеря кадра отменит сессию, а не разрешит незаметно неполный файл. */ + else { /* Сначала формирует весь элемент, затем публикует новый head. */ + queue[head].id = id; queue[head].dlc = box->MSGCTRL.bit.DLC; /* Сохраняет фактические ID и длину для проверок общего ядра. */ + low = box->MDL.all; high = box->MDH.all; /* Два 32-битных снимка не смешивают октеты разных чтений регистров. */ + for (i = 0; i < 4U; ++i) { queue[head].data[i] = (low >> (i * 8U)) & 255U; queue[head].data[i + 4U] = (high >> (i * 8U)) & 255U; } /* DBO=0 передаёт младшие октеты MDL/MDH первыми. */ + head = next; /* Публикация после копирования исключает чтение main частично заполненного элемента. */ + } /* Завершает формирование очередного элемента кольца. */ + } /* Остальные кадры не изменяют никакие состояния протокола. */ + ECanaRegs.CANRMP.all = mask; /* Подтверждает только собственный прочитанный mailbox. */ +} /* В ISR отсутствуют erase, write, CRC и загрузка приложения. */ +interrupt void boot_can_rx(void) /* Использует отдельный аппаратный CAN F2812 на GPIOF6/F7. */ +{ /* Оба служебных RX mailbox относятся к одной линии ECAN0INTA. */ + receive(&ECanaMboxes.MBOX3, 8UL); receive(&ECanaMboxes.MBOX6, 64UL); /* Mailbox 3 принимает адресные кадры, 6 — broadcast discovery. */ + PieCtrlRegs.PIEACK.all = 0x0100U; /* ACK9 открывает группу PIE9 для следующего CAN IRQ. */ +} /* Возвращает управление прерванному main без обращения к прикладным каналам ПМ67. */ +static void tx_poll(void) /* Подтверждает физическую передачу, прежде чем разрешить следующий ответ или reset. */ +{ /* Ошибка шины ограничена четвертью секунды и не приводит к бесконечному ожиданию. */ + if (!tx_busy) return; /* Свободный mailbox не требует чтения старых ACK. */ + if (ECanaRegs.CANTA.all & 16UL) { ECanaRegs.CANTA.all = 16UL; tx_busy = 0U; } /* Снимает только фактический ACK ответа mailbox 4. */ + else if (Boot2812_Now() - sent_at >= 250UL) { /* Истёкшее ожидание не разрешает выполнить ранее заказанный reset. */ + ECanaRegs.CANTRR.all = 16UL; reset_requested = 0U; /* Запрашивает отмену и сохраняет управление recovery-загрузчику. */ + if (ECanaRegs.CANAA.all & 16UL) { ECanaRegs.CANAA.all = 16UL; tx_busy = 0U; } /* Не перезаписывает mailbox до подтверждённого завершения отмены. */ + } /* Поздний ACK после запроса отмены также не восстанавливает сброшенный reset_requested. */ +} /* Состояние передачи не зависит от относительного порядка BUSY и окончательного ответа. */ +static bool transmit(void *user, uint32_t id, const pcan_boot_byte_t *data, pcan_boot_byte_t dlc) /* Реализует физический ответ без дублирования формата ProtoCAN. */ +{ /* Вызывается только из main или синхронного NOR callback, никогда из RX ISR. */ + unsigned int i; uint32_t low = 0UL, high = 0UL, started = Boot2812_Now(), budget = 1000000UL; (void)user; /* Ограничение проходов сохраняет выход при остановленном Timer1. */ + while (tx_busy && --budget && Boot2812_Now() - started < 250UL) tx_poll(); /* Даёт предыдущему BUSY физически уйти, прежде чем отправить окончательный OK. */ + if (tx_busy || dlc > 8U) return false; /* Не теряет неподтверждённый ответ перезаписью регистров. */ + for (i = 0; i < dlc; ++i) { if (i < 4U) low |= (uint32_t)(data[i] & 255U) << (8U * i); else high |= (uint32_t)(data[i] & 255U) << (8U * (i - 4U)); } /* Упаковывает октеты C28x в MDL/MDH при DBO=0. */ + EALLOW; ECanaRegs.CANME.all &= ~16UL; /* Идентификатор TX изменяется только при отключённом mailbox. */ + ECanaMboxes.MBOX4.MSGID.all = 0x80000000UL | id; ECanaMboxes.MBOX4.MSGCTRL.all = dlc; /* IDE=1 включает Extended формат, длина сохраняется из codec. */ + ECanaMboxes.MBOX4.MDL.all = low; ECanaMboxes.MBOX4.MDH.all = high; /* Фиксирует все данные до подачи запроса передачи. */ + ECanaRegs.CANTA.all = 16UL; ECanaRegs.CANAA.all = 16UL; ECanaRegs.CANME.all |= 16UL; ECanaRegs.CANTRS.all = 16UL; EDIS; /* Удаляет старые ACK и запускает один новый аппаратный ответ. */ + sent_at = Boot2812_Now(); tx_busy = 1U; /* Следующий ответ и REBOOT ждут фактический CAN ACK. */ + return true; /* Ядро считает кадр принятым аппаратным передатчиком. */ +} /* Wire-содержимое сформировано только общим ProtoCAN codec. */ +void Boot2812_Busy(void) /* Долгие erase и проверки продолжают сообщать состояние текущей команды. */ +{ /* Функция не извлекает новые команды из очереди и не допускает вложенный процессинг сессии. */ + uint32_t now = Boot2812_Now(); tx_poll(); /* Подтверждает ранее отправленный BUSY по фактическому TX ACK. */ + if (operation_active && !tx_busy && now - busy_at >= 250UL) { busy_at = now; (void)pcan_boot_report_busy(&boot, current_command, now); } /* Ответ каждые 250 мс удерживает клиент живым при секундном стирании NOR. */ +} /* Финальный статус после callback отправит обычное ядро. */ +static void request_reset(void *user) /* Команда REBOOT не сбрасывает аппарат до передачи её статусного ответа. */ +{ /* Аппаратный reset выполнит main после освобождения TX mailbox. */ + (void)user; reset_requested = 1U; /* Не вызывает watchdog непосредственно из callback codec. */ +} /* Потеря TX ACK отменяет этот запрос в tx_poll. */ +static void can_init(void) /* Отдельные clock/GPIO F2812 не используют настройки F28335. */ +{ /* SYSCLKOUT=150 МГц при штатных XCLKIN=30 МГц и PLLCR=10 в включённом TI SDK. */ + EALLOW; GpioMuxRegs.GPFMUX.bit.CANTXA_GPIOF6 = 1; GpioMuxRegs.GPFMUX.bit.CANRXA_GPIOF7 = 1; /* Назначение CAN берётся из оригинального DSP281x_ECan.c. */ + ECanaRegs.CANTIOC.all = 8UL; ECanaRegs.CANRIOC.all = 8UL; ECanaRegs.CANME.all = 0UL; /* Включает CAN-функции и отключает mailbox до полной настройки. */ + ECanaRegs.CANMC.all = 0x3080UL; /* SCB/CCR/ABO выбирают eCAN, режим настройки и автоматическое восстановление шины. */ + while (!ECanaRegs.CANES.bit.CCE) {} /* Ожидает разрешения аппаратуры менять CANBTC. */ + ECanaRegs.CANBTC.all = (29UL << 16) | 0x017AUL; /* F2812: 150 МГц/(BRP+1=30)/(1+16+3 tq)=250000 бит/с, SJW=2 tq. */ + ECanaRegs.CANMC.all &= ~0x1000UL; while (ECanaRegs.CANES.bit.CCE) {} /* Выходит из режима настройки перед включением приёма. */ + ECanaMboxes.MBOX3.MSGID.all = 0xC0000000UL | pcan_boot_make_id(0U, 0U, BOOT2812_DEVICE_TYPE, BOOT2812_DEVICE_ID, 0U, 0U); /* AME/IDE и адресный фильтр отделяют выбранный прибор от остальных узлов CAN. */ + ECanaLAMRegs.LAM3.all = 0x100FFFFFUL; ECanaMboxes.MBOX3.MSGCTRL.all = 8UL; /* Игнорирует priority/type/body при аппаратном отборе; точные типы проверяет ISR/codec. */ + ECanaMboxes.MBOX6.MSGID.all = 0xC0000000UL | pcan_boot_make_id(0U, 0U, 7U, 15U, 13U, 0U); /* Broadcast разрешён только для discovery, а не для стирания/программирования. */ + ECanaLAMRegs.LAM6.all = 0x10000000UL; ECanaMboxes.MBOX6.MSGCTRL.all = 0UL; ECanaMboxes.MBOX4.MSGCTRL.all = 0UL; /* Фильтр discovery игнорирует только priority; зарезервированные биты MSGCTRL очищены. */ + ECanaRegs.CANMD.all = 72UL; ECanaRegs.CANMIL.all = 0UL; ECanaRegs.CANMIM.all = 72UL; /* RX 3/6 и TX4 работают на линии ECAN0INTA; остальных mailbox нет. */ + ECanaRegs.CANRMP.all = 0xFFFFFFFFUL; ECanaRegs.CANRML.all = 0xFFFFFFFFUL; ECanaRegs.CANTA.all = 0xFFFFFFFFUL; /* Удаляет старые флаги перед первым разрешением IRQ. */ + ECanaRegs.CANGIF0.all = 0xFFFFFFFFUL; ECanaRegs.CANGIM.all = 1UL; ECanaRegs.CANME.all = 88UL; /* Включает только три настроенных mailbox и прерывание линии 0. */ + PieVectTable.ECAN0INTA = &boot_can_rx; PieCtrlRegs.PIEIER9.bit.INTx5 = 1; EDIS; IER |= M_INT9; /* Подключает короткий постоянный RX ISR группы PIE9. */ +} /* Конфигурация и состояние ПМ35/F28335 остаются независимыми. */ +void main(void) /* Запускается аппаратным внутренним Flash boot F2812 через 3F7FF6. */ +{ /* Прежний внешний flat-образ не переписывается автоматически и не заменяет проверенную SCI8-таблицу. */ + pcan_boot_config_t config; pcan_boot_port_t port; uint32_t started, entry; unsigned int tried = 0U; /* Небольшие настройки и адрес входа помещаются в постоянный стек M1. */ + InitSysCtrl(); DINT; IER = 0U; IFR = 0U; /* Настраивает PLL=150 МГц и исключает старые IRQ до создания собственных векторов. */ + memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, &RamfuncsLoadEnd - &RamfuncsLoadStart); InitFlash(); /* Штатная InitFlash выполняется из RAM, пока весь остальной код хранится во внутренней Flash A. */ + InitPieCtrl(); InitCpuTimers(); Boot2812_BoardInit(); /* Подготавливает PIE/Timer1 и доступ к подтверждённой AM29LV800BT через CPLD. */ + head = tail = overflow = tx_busy = reset_requested = operation_active = current_command = 0U; sent_at = busy_at = 0UL; /* Явно очищает COFF .ebss и очередь до включения CAN IRQ. */ + memset(&config, 0, sizeof(config)); memset(&port, 0, sizeof(port)); /* Не оставляет неопределённые callbacks нового публичного API. */ + config.device_type = BOOT2812_DEVICE_TYPE; config.device_id = BOOT2812_DEVICE_ID; config.product_type = BOOT2812_PRODUCT; config.hardware_revision = 1U; /* Отдельный адрес 3/6 и Product 2812 отличают основной контроллер от F28335. */ + config.active_slot = 0U; config.slot_count = 1U; config.max_image_size = BOOT2812_IMAGE_BYTES; config.ack_window = 16U; config.session_timeout_ms = 30000UL; /* Single-slot отражает NOR-раздел без ложного обещания A/B-отката. */ + port.send = transmit; port.erase_slot = Boot2812_Erase; port.write_slot = Boot2812_Write; port.verify_status = Boot2812_Verify; port.set_pending_slot = Boot2812_Commit; port.reboot = request_reset; /* Алгоритм ProtoCAN вызывает только аппаратные операции внешней NOR. */ + if (!pcan_boot_init(&boot, &config, &port, 0)) for (;;) {} /* Ошибка конфигурации не разрешает произвольную запись памяти. */ + ConfigCpuTimer(&CpuTimer1, 150.0F, 1000.0F); EALLOW; PieVectTable.XINT13 = &boot_tick; EDIS; /* PLL выбранного TI SDK даёт 150 МГц; 1000 мкс соответствуют миллисекундным тайм-аутам протокола. */ + CpuTimer1Regs.TCR.all = 0x4020U; IER |= M_INT13; can_init(); PieCtrlRegs.PIECRTL.bit.ENPIE = 1; EINT; started = Boot2812_Now(); /* Начинает трёхсекундное окно recovery только после готовности физического CAN. */ + for (;;) { /* Постоянный main обслуживает запись и автоматически запускает только подтверждённый manifest. */ + tx_poll(); pcan_boot_poll(&boot, Boot2812_Now()); KickDog(); /* Тайм-ауты сессии, discovery и watchdog не зависят от очередного окна данных. */ + if (!tx_busy && reset_requested) { DINT; EALLOW; SysCtrlRegs.WDCR = 0x0028U; EDIS; for (;;) {} } /* После физического ACK REBOOT запускает аппаратный watchdog reset без старых ISR. */ + if (overflow || (ECanaRegs.CANRML.all & 72UL)) { overflow = 0U; ECanaRegs.CANRML.all = 72UL; tail = head; pcan_boot_abort(&boot); } /* Потеря mailbox/очереди отменяет сессию и требует передачи заново. */ + if (!tx_busy && tail != head) { /* Обрабатывает один целиком сформированный ISR элемент за проход. */ + current_command = pcan_boot_id_msg_type(queue[tail].id) == 9U ? pcan_boot_id_msg_body(queue[tail].id) & 255U : 0U; operation_active = 1U; /* BUSY содержит именно команду, которая выполняется сейчас. */ + (void)pcan_boot_process(&boot, queue[tail].id, queue[tail].data, queue[tail].dlc); operation_active = 0U; tail = (tail + 1U) & 31U; /* Производственный codec проверяет session/порядок/CRC и вызывает NOR callbacks только в main. */ + } /* Пока TX занят, очередь сохраняет все следующие кадры окна. */ + if (!tried && !tx_busy && boot.state == PCAN_BOOT_STATE_IDLE && Boot2812_Now() - started >= BOOT2812_RECOVERY_MS) { /* ENTER_BOOT удерживает загрузчик; без сессии допускается автоматический запуск сохранённого CAN-образа. */ + tried = 1U; /* Пустой или испорченный manifest не должен проверяться заново на каждом такте main. */ + if (Boot2812_NorIdentify() && Boot2812_Load(&entry)) { DINT; IER = 0U; IFR = 0U; CpuTimer1Regs.TCR.bit.TSS = 1; ECanaRegs.CANMIM.all = 0UL; ((void (*)(void))entry)(); for (;;) {} } /* Запускает только полностью проверенную RAM-таблицу; приложение само создаст свои ISR и C runtime. */ + } /* При отказе остаётся доступен CAN recovery без EEPROM. */ + } /* Ни один путь не исполняет код из стираемой внешней NOR. */ +} /* Завершение загрузчика выполняется только аппаратным reset либо проверенным переходом в приложение. */ diff --git a/c/protocan-boot/projects/ccs/f2812/nor_flash.c b/c/protocan-boot/projects/ccs/f2812/nor_flash.c new file mode 100644 index 0000000..dde47de --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/nor_flash.c @@ -0,0 +1 @@ +#include "../../../ports/tms320f2812/nor_flash.c" /* Собирает канонический драйвер AM29LV800BT из templates, сохраняя hardware callbacks отдельно от протокола. */ diff --git a/c/protocan-boot/projects/ccs/f2812/shared_boot.c b/c/protocan-boot/projects/ccs/f2812/shared_boot.c new file mode 100644 index 0000000..7c877f4 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/shared_boot.c @@ -0,0 +1 @@ +#include "../../../src/pcan_boot.c" /* Подключает общий ProtoCAN codec, сессии и CRC32 без второй реализации протокола. */ diff --git a/c/protocan-boot/projects/ccs/f2812/targetConfigs/TMS320F2812.ccxml b/c/protocan-boot/projects/ccs/f2812/targetConfigs/TMS320F2812.ccxml new file mode 100644 index 0000000..4b062df --- /dev/null +++ b/c/protocan-boot/projects/ccs/f2812/targetConfigs/TMS320F2812.ccxml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/c/protocan-boot/projects/ccs/f28335/.ccsproject b/c/protocan-boot/projects/ccs/f28335/.ccsproject new file mode 100644 index 0000000..44f2f89 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f28335/.ccsproject @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/c/protocan-boot/projects/ccs/f28335/.cproject b/c/protocan-boot/projects/ccs/f28335/.cproject new file mode 100644 index 0000000..5c10a85 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f28335/.cproject @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/c/protocan-boot/projects/ccs/f28335/.project b/c/protocan-boot/projects/ccs/f28335/.project new file mode 100644 index 0000000..c1b7273 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f28335/.project @@ -0,0 +1,115 @@ + + + + F28335_CAN_AB + + Отдельный постоянный загрузчик ProtoCAN для F28335 + + + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + + + + + + + + com.ti.ccstudio.core.ccsNature + + org.eclipse.cdt.core.cnature + + org.eclipse.cdt.core.ccnature + + org.eclipse.cdt.managedbuilder.core.managedBuildNature + + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + + + + ti/DSP2833x_ADC_cal.asm + + 1 + + PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_ADC_cal.asm + + + + + ti/DSP2833x_CpuTimers.c + + 1 + + PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_CpuTimers.c + + + + + ti/DSP2833x_GlobalVariableDefs.c + + 1 + + PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_GlobalVariableDefs.c + + + + + ti/DSP2833x_PieCtrl.c + + 1 + + PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_PieCtrl.c + + + + + ti/DSP2833x_SysCtrl.c + + 1 + + PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_SysCtrl.c + + + + + ti/DSP2833x_usDelay.asm + + 1 + + PCAN_ROOT/vendor/ti/f28335/source/DSP2833x_usDelay.asm + + + + + DSP2833x_Headers_nonBIOS.cmd + + 1 + + PCAN_ROOT/vendor/ti/f28335/cmd/DSP2833x_Headers_nonBIOS.cmd + + + + + + + + PCAN_ROOT + + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/c/protocan-boot/projects/ccs/f28335/F28335_CAN_AB.cmd b/c/protocan-boot/projects/ccs/f28335/F28335_CAN_AB.cmd new file mode 100644 index 0000000..161ce61 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f28335/F28335_CAN_AB.cmd @@ -0,0 +1,30 @@ +MEMORY /* Отделяет постоянный загрузчик от адресов RAM payload приложения 167. */ +{ /* Все адреса и длины указаны в 16-битных словах CPU C28x. */ +PAGE 0: /* Исполняемые секции и их Flash LOAD-адреса. */ + FLASHA : origin = 0x338000, length = 0x007F80 /* Сектор A до зарезервированной CSM-области содержит постоянный загрузчик. */ + BEGIN : origin = 0x33FFF6, length = 0x000002 /* Два слова аппаратного Flash boot перехода; пароли CSM не выделяются. */ + RAMFUNCS : origin = 0x00F800, length = 0x000800 /* Верхние 2048 слов RAM загрузчика нужны InitFlash и не входят в SCI8 payload приложения. */ + ADC_CAL : origin = 0x380080, length = 0x000009 /* Заводская калибровка TI используется без записи/стирания. */ + RESET : origin = 0x3FFFC0, length = 0x000002 /* Аппаратный reset находится в ROM и не программируется. */ +PAGE 1: /* Рабочие данные не пересекают код RAM-приложения ниже E000. */ + BOOT_SHARED : origin = 0x000050, length = 0x000008 /* Общие с приложением восемь слов NOINIT handoff после ROM scratch 0..4F. */ + RAMM0 : origin = 0x000058, length = 0x0003A8 /* Малый банк доступен служебным неинициализированным данным. */ + RAMM1 : origin = 0x000400, length = 0x000400 /* Стек на 1024 слова не меняет расположение при переходе в приложение. */ + RAMDATA : origin = 0x00E000, length = 0x001800 /* 6144 слова store/очереди; приложение использует их только после перехода в C startup. */ +} /* Завершает физическую карту постоянного загрузчика. */ +SECTIONS /* Не выделяет ни одного загружаемого слова в RAM приложения. */ +{ /* Инициализированные Flash-секции остаются в секторе A. */ + codestart : > BEGIN, PAGE = 0 /* Аппаратный переход передаёт управление watchdog-safe C startup. */ + .text : > FLASHA, PAGE = 0 /* Весь постоянный алгоритм и библиотеки исполняются из Flash A. */ + .cinit : > FLASHA, PAGE = 0 /* Таблицы ROM-модели подготавливают данные загрузчика до main. */ + .pinit : > FLASHA, PAGE = 0 /* Сохраняет стандартный порядок C runtime, если компилятор создаст эту секцию. */ + .econst : > FLASHA, PAGE = 0 /* Константы протокола и имена сервиса не расходуют рабочую RAM. */ + .switch : > FLASHA, PAGE = 0 /* Таблицы переходов находятся в постоянной области загрузчика. */ + ramfuncs : LOAD = FLASHA, RUN = RAMFUNCS, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), RUN_START(_RamfuncsRunStart), PAGE = 0 /* InitFlash копируется до изменения настроек самой Flash. */ + .boot_shared : > BOOT_SHARED, PAGE = 1, TYPE = NOINIT /* Не обнуляет session/slot, полученные через watchdog reset. */ + .stack : > RAMM1, PAGE = 1 /* Стек не пересекает ни handoff, ни загружаемые секции SCI8. */ + .ebss : > RAMDATA, PAGE = 1 /* Размещает очередь, журнал и структуры драйвера вне RAM payload. */ + .esysmem : > RAMDATA, PAGE = 1 /* Поддерживает стандартную секцию runtime без использования heap в алгоритме. */ + .reset : > RESET, PAGE = 0, TYPE = DSECT /* Reset-вектор ROM описывается, но не попадает в программируемый OUT. */ + .adc_cal : > ADC_CAL, PAGE = 0, TYPE = NOLOAD /* Сохраняет заводские данные ADC TI при установке загрузчика. */ +} /* Не создаёт секций CSM, OTP или паролей. */ diff --git a/c/protocan-boot/projects/ccs/f28335/codestart.asm b/c/protocan-boot/projects/ccs/f28335/codestart.asm new file mode 100644 index 0000000..b69fe2f --- /dev/null +++ b/c/protocan-boot/projects/ccs/f28335/codestart.asm @@ -0,0 +1,12 @@ + .ref _c_int00 ; Стандартный COFF startup применяет .cinit и вызывает main после отключения раннего watchdog. + .sect "codestart" ; Boot ROM передаёт управление двухсловному переходу по аппаратному адресу слова 0x33FFF6. + LB flash_boot_start ; Переходит к короткой подготовке C28x во Flash, сохраняя точный размер аппаратного входа два слова. + .text ; Последовательность взята из штатного TI DSP2833x_CodeStartBranch.asm и размещается в секторе основного кода. +flash_boot_start: ; Отключает watchdog до возможной длительной обработки таблиц инициализации C, а не только после входа в main. + SETC OBJMODE ; Выбирает C28x object mode, требуемый стандартным COFF startup процессора F28335. + EALLOW ; Разрешает запись защищённого регистра WDCR перед запуском C runtime. + MOVZ DP, #7029h>>6 ; Адрес слова WDCR=0x7029 из карты F28335; DP выбирает соответствующую страницу по 64 слова. + MOV @7029h, #0068h ; Значение 0x0068 содержит контрольные биты WDCHK=101 и WDDIS=1, как официальный TI startup. + EDIS ; Возвращает защиту системных регистров перед переходом в библиотечную инициализацию. + LB _c_int00 ; Применяет штатную ROM-модель инициализации и затем запускает текущий main 167. + .end ; Завершает модуль, не добавляя произвольных данных рядом с CSM-паролями сектора A. diff --git a/c/protocan-boot/projects/ccs/f28335/main.c b/c/protocan-boot/projects/ccs/f28335/main.c new file mode 100644 index 0000000..fa829d2 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f28335/main.c @@ -0,0 +1,127 @@ +#include "DSP2833x_Device.h" /* Использует действующую частоту и штатную карту регистров той же платы 167. */ +#include "DSP2833x_Examples.h" /* Предоставляет InitSysCtrl, InitPieCtrl, InitFlash и управление Timer1. */ +#include "../../../ports/tms320f28335/f28335_can_boot.h" /* Подключает адрес, сервисы и очередь существующего загрузчика. */ +#include "../../../ports/tms320f28335/f28335_boot_platform.h" /* Использует общий handoff, SPI и энергонезависимый A/B-журнал. */ +#include /* Копирует ramfuncs до настройки времен доступа Flash. */ +extern Uint16 RamfuncsLoadStart, RamfuncsLoadEnd, RamfuncsRunStart; /* Адреса LOAD/RUN задаёт отдельный linker загрузчика в словах C28x. */ +static f28335_boot_store_t image_store; /* Журнал загрузки остаётся в RAM E000..FFFF до перехода в приложение. */ +interrupt void boot_tick(void) /* Timer1 продолжает миллисекундные тайм-ауты общего CAN/SPI порта. */ +{ /* Этот ISR принадлежит постоянному загрузчику, а не кандидату приложения. */ + CpuTimer1.InterruptCount++; /* Один тик равен одной миллисекунде согласно ConfigCpuTimer ниже. */ + ServiceDog(); /* Длительные CRC/SPI операции загрузчика не должны сбрасывать аппарат во время обновления. */ +} /* Возвращает управление основному циклу загрузчика. */ +interrupt void boot_can_rx(void) /* CAN IRQ выполняет только короткий перенос принятых кадров в общую очередь. */ +{ /* Запись EEPROM, CRC и публикация pending остаются в главном цикле. */ + F28335CanBoot_RxISR(); /* Читает только выделенные mailbox 3 и 6 существующего адаптера. */ + PieCtrlRegs.PIEACK.all = 0x0100U; /* Бит 8 подтверждает группу PIE9, в которой находится ECAN0INTA. */ +} /* Позволяет принять следующее окно CAN, пока main занят SPI. */ +static void boot_can_init(void) /* Настраивает тот же физический CAN-A и 250 кбит/с, что приложение 167. */ +{ /* Загрузчик не использует прикладные mailbox 0..2 и не меняет адрес общего порта. */ + Uint32 shadow; /* Защищённые eCAN-регистры изменяются только полными 32-битными обращениями. */ + EALLOW; /* Разрешает настройку мультиплексора, eCAN и таблицы векторов. */ + GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1; /* GPIO30 служит CANRXA, как в штатном InitCan проекта. */ + GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1; /* GPIO31 служит CANTXA того же трансивера. */ + ECanaRegs.CANTIOC.all = 8UL; /* Бит TXFUNC включает функцию CAN у выхода контроллера. */ + ECanaRegs.CANRIOC.all = 8UL; /* Бит RXFUNC включает аппаратный вход CAN. */ + ECanaRegs.CANME.all = 0UL; /* Изменяет mailbox и фильтры только при выключенных ящиках. */ + ECanaRegs.CANMIM.all = 0UL; /* Ни один старый mailbox не должен создавать IRQ во время настройки. */ + ECanaRegs.CANMIL.all = 0UL; /* Направляет служебные mailbox на ECAN0INTA группы PIE9. */ + ECanaRegs.CANMC.all = 0x00003080UL; /* SCB=1 выбирает eCAN, ABO=1 автоматическое восстановление, CCR=1 режим настройки битового времени; SRES остаётся нулём. */ + while (!ECanaRegs.CANES.bit.CCE) {} /* Не пишет CANBTC до аппаратного подтверждения режима настройки. */ + shadow = ((Uint32)(CLKMULT * 3L - 1L) << 16) | 0x0000017AUL; /* BRP=CLKMULT*3-1, SJW=1, TSEG1=15, TSEG2=2 как в приложении: 250000 бит/с при текущем SYSCLKOUT. */ + ECanaRegs.CANBTC.all = shadow; /* Передаёт параметры одним 32-битным обращением к eCAN. */ + ECanaRegs.CANMC.all &= ~0x00001000UL; /* Снимает CCR после настройки тактов CAN. */ + while (ECanaRegs.CANES.bit.CCE) {} /* Ждёт возврата контроллера к обычной работе перед включением фильтров. */ + ECanaRegs.CANTA.all = 0xFFFFFFFFUL; /* Удаляет старые TX ACK, которые не относятся к новой сессии. */ + ECanaRegs.CANRMP.all = 0xFFFFFFFFUL; /* Удаляет старые RX-флаги до включения IRQ. */ + ECanaRegs.CANRML.all = 0xFFFFFFFFUL; /* Начинает контроль потери mailbox с чистого состояния. */ + ECanaRegs.CANGIF0.all = 0xFFFFFFFFUL; /* Снимает накопленные флаги линии CAN0. */ + ECanaRegs.CANGIM.all = 1UL; /* I0EN разрешает mailbox IRQ по линии 0; ошибки не требуют прикладного ISR. */ + PieVectTable.ECAN0INTA = &boot_can_rx; /* Использует постоянный обработчик загрузчика вместо кода RAM-приложения. */ + PieCtrlRegs.PIEIER9.bit.INTx5 = 1; /* Разрешает ECAN0INTA в группе PIE9. */ + EDIS; /* Возвращает защиту аппаратной конфигурации. */ + IER |= M_INT9; /* Разрешает группе CAN доставлять IRQ ядру после общего EINT. */ +} /* Общий порт затем настроит адресные mailbox 3/4/6. */ +static unsigned int boot_periph_id(void) /* Повторяет аппаратное чтение Mode из peripher.c, чтобы после reset адрес загрузчика совпадал с приложением. */ +{ /* Четыре активных низким уровнем перемычки существующей ПМ35 задают номера 1–16. */ + unsigned int periph_id; /* Номер является ID PERIPH из Excel, а не уменьшенным на единицу индексом старого CAN. */ + EALLOW; /* Разрешает настройку только четырёх входов адресных перемычек. */ + GpioCtrlRegs.GPAMUX2.bit.GPIO20=0; /* GPIO20 работает входом адреса с весом 2, как в get_Mode приложения. */ + GpioCtrlRegs.GPAMUX2.bit.GPIO21=0; /* GPIO21 работает входом адреса с весом 1, а не альтернативной периферией. */ + GpioCtrlRegs.GPAMUX2.bit.GPIO22=0; /* GPIO22 работает входом адреса с весом 4. */ + GpioCtrlRegs.GPBMUX2.bit.GPIO51=0; /* GPIO51 работает входом адреса с весом 8. */ + GpioCtrlRegs.GPADIR.bit.GPIO20=0; /* Запрещает выходной драйвер, чтобы загрузчик не воздействовал на перемычку. */ + GpioCtrlRegs.GPADIR.bit.GPIO21=0; /* Оставляет младшую адресную перемычку входом. */ + GpioCtrlRegs.GPADIR.bit.GPIO22=0; /* Оставляет третий разряд аппаратного номера входом. */ + GpioCtrlRegs.GPBDIR.bit.GPIO51=0; /* Оставляет старшую перемычку входом порта B. */ + EDIS; /* Восстанавливает защиту конфигурации GPIO до чтения физического номера. */ + periph_id=1U+!GpioDataRegs.GPADAT.bit.GPIO21; /* Штатный Mode начинается с 1; замкнутая GPIO21 добавляет единицу. */ + periph_id+=2U*!GpioDataRegs.GPADAT.bit.GPIO20; /* Замкнутая GPIO20 добавляет два к номеру платы. */ + periph_id+=4U*!GpioDataRegs.GPADAT.bit.GPIO22; /* Замкнутая GPIO22 добавляет четыре к номеру платы. */ + periph_id+=8U*!GpioDataRegs.GPBDAT.bit.GPIO51; /* Замкнутая GPIO51 добавляет восемь; аппаратный диапазон заканчивается на 16. */ + return periph_id; /* Общий CAN-порт преобразует номер 16 в Type 2 / Device 0 согласно Excel. */ +} /* Приложение и recovery используют один и тот же физический адрес без общего значения 3/7. */ +static bool ram_word(void *user, uint32_t address, uint16_t value) /* Аппаратная запись одного слова уже проверенной таблицы SCI8. */ +{ /* Повторяет нижнюю защиту RAM даже при ошибке вызывающего слоя. */ + (void)user; /* Контекст не нужен для единственной внутренней RAM данного F28335. */ + if (address < 0x8000UL || address >= 0xE000UL) return false; /* Не позволяет таблице затронуть периферию, handoff, стек или RAM загрузчика. */ + *(volatile Uint16 *)address = value; /* Адрес измеряется в 16-битных словах C28x, значение уже декодировано из SCI8. */ + return true; /* Сообщает полную запись слова, а не частичное выполнение секции. */ +} /* После загрузки всех слов общий store вернёт проверенную точку входа. */ +static uint16_t flash_word(void *user, uint32_t address) /* Читает только фиксированный заголовок и проверенный диапазон приложения ниже сектора A. */ +{ /* Загрузчик остаётся во Flash A, поэтому чтение H–B не меняет выполняемый код. */ + (void)user; /* Единственная внутренняя Flash не требует отдельного контекста источника. */ + return *(volatile Uint16 *)address; /* C28x адресует Flash 16-битными словами; разбиение на октеты выполняет общий валидатор CRC. */ +} /* Никакая запись или стирание Flash при выборе источника запуска не выполняется. */ +static void start_application(uint32_t entry, unsigned int source) /* Передаёт управление Flash либо EEPROM только после проверки соответствующего образа. */ +{ /* Останавливает собственные IRQ до C startup приложения, который заново настроит периферию и рабочую RAM. */ + DINT; IER = 0U; IFR = 0U; /* Старые прерывания не должны войти в очередь или стек завершённого загрузчика. */ + CpuTimer1Regs.TCR.bit.TSS = 1; /* Прекращает миллисекундные IRQ до запуска прикладного InitSysCtrl. */ + ECanaRegs.CANMIM.all = 0UL; /* Не доставляет CAN IRQ во время смены векторов приложения. */ + F28335Boot_SetRunning(source); /* Сохраняет достоверный источник: 0/1 для EEPROM A/B либо FE для проверенной Flash. */ + ((void (*)(void))entry)(); /* Вызывает watchdog-safe startup Flash или проверенную точку C runtime RAM-образа. */ + for (;;) {} /* Ошибочный возврат приложения не использует перезаписанное состояние загрузчика. */ +} /* Возврат к boot происходит только аппаратным reset с согласованным handoff. */ +void F28335Boot_Quiesce(void) /* Перед повторным входом загрузчика его собственные IRQ будут отключены общим Reset. */ +{ /* Силовые выходы загрузчик не включает; прикладная остановка выполняется до входа в него. */ + CpuTimer2Regs.TCR.bit.TSS = 1; /* Удерживает старый SPI Timer2 остановленным перед watchdog reset. */ +} /* Общий аппаратный слой сохранит session и включит watchdog. */ +void main(void) /* Постоянный загрузчик запускается аппаратным Flash boot по адресу 33FFF6. */ +{ /* Пустая EEPROM и неподтверждённый кандидат оставляют доступным CAN recovery. */ + f28335_boot_io_t io; /* Доступ к M95M02 предоставляет существующий переносимый SPI-порт. */ + unsigned int slot, session, periph_id; /* Слот, сессия handoff и физический номер PERIPH сохраняются отдельно от адресов памяти. */ + uint32_t entry, started; /* Адрес запуска измеряется словами CPU; started хранит миллисекунды стартового окна CAN. */ + InitSysCtrl(); /* Повторяет PLL и SYSCLKOUT проекта 167, отключая watchdog на раннем старте. */ + DINT; /* Не использует IRQ до настройки таблицы векторов и Timer1. */ + IER = 0U; IFR = 0U; /* Исключает доставку старых прерываний после watchdog reset. */ + memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, &RamfuncsLoadEnd - &RamfuncsLoadStart); /* Переносит InitFlash в RAM до изменения времен доступа Flash. */ + InitFlash(); /* Настраивает доступ к постоянному коду по штатной процедуре TI. */ + InitPieCtrl(); /* Очищает разрешения и флаги всех групп PIE перед установкой двух собственных векторов. */ + InitCpuTimers(); /* Останавливает Timer0/1/2 и сбрасывает их управляющие структуры. */ + ConfigCpuTimer(&CpuTimer1, SYSCLKOUT / 1000000L, 1000UL); /* Период 1000 мкс даёт единый миллисекундный tick для протокола и SPI WIP. */ + EALLOW; PieVectTable.XINT13 = &boot_tick; EDIS; /* Привязывает прямое прерывание Timer1 к постоянному ISR загрузчика. */ + CpuTimer1Regs.TCR.all = 0x4020U; /* Разрешает прерывание Timer1 и запускает счётчик, как приложение 167. */ + IER |= M_INT13; /* Разрешает миллисекундные прерывания ядра. */ + periph_id=boot_periph_id(); /* Читает реальные перемычки до адресных mailbox и до ответа на ENTER_BOOT после reset. */ + boot_can_init(); /* Настраивает трансивер и физическую скорость до общих фильтров и первой передачи. */ + session = F28335Boot_RequestedSession(); /* Потребляет только достоверный запрос приложения с magic и XOR-контролем. */ + F28335CanBoot_Init(periph_id); /* Открывает журнал и адресные Boot mailbox только для физического PERIPH данной платы. */ + PieCtrlRegs.PIECTRL.bit.ENPIE = 1; /* Разрешает таблицу PIE после записи обоих используемых векторов. */ + EINT; /* Приём окна CAN продолжается во время синхронных SPI-транзакций main. */ + if (session) F28335CanBoot_Resume(session); /* Отвечает ENTER_BOOT после reset с той же session и остаётся в recovery. */ + else { /* Обычный reset даёт CAN окно, затем предпочитает проверенную внутреннюю Flash и использует EEPROM как резерв. */ + started = F28335Boot_Now(); /* Отсчитывает три секунды от готового CAN, а не от начала настройки PLL и SPI. */ + while ((uint32_t)(F28335Boot_Now()-started)<3000UL && !F28335CanBoot_Active()) { F28335CanBoot_Service(); ServiceDog(); } /* ENTER_BOOT удерживает recovery; обычный PING не изменяет выбранный источник запуска. */ + F28335CanBoot_Service(); /* Разбирает кадр на границе трёхсекундного окна до последней проверки активного сеанса. */ + if (!F28335CanBoot_Active()) { /* Не запускает основную или резервную программу поверх открытого сеанса CAN Boot. */ + if (f28335_flash_app_validate(flash_word, 0, &entry)) start_application(entry, F28335_BOOT_FLASH_SLOT); /* Flash приоритетна только при правильном FAB1, допустимых адресах и совпавшей CRC всех LOAD-секций. */ + io.read = F28335Boot_Read; io.write = F28335Boot_Write; io.user = 0; /* Передаёт store ту же аппаратную реализацию, что обслуживает CAN. */ + if (f28335_boot_open(&image_store, &io) && f28335_boot_select(&image_store, &slot) && slot < 2U && f28335_boot_load(&image_store, slot, ram_word, 0, &entry)) { /* Проверяет CRC/SCI8, сохраняет attempted до пробного запуска и копирует только допустимую RAM. */ + start_application(entry, slot); /* Резервный EEPROM-образ получает прежние trial/CONFIRM и автоматический откат A/B. */ + } /* При ошибке чтения, CRC, таблицы или журнала не выполняет неизвестный entry. */ + F28335CanBoot_Init(periph_id); /* При переходе в recovery перечитывает журнал, сохраняя прежний физический адрес платы. */ + } /* Открытый CAN-сеанс сохраняет метаданные, выбранный слот и подтверждения без повторного Init. */ + } /* Завершает выбор между адресным входом и обычным запуском приложения. */ + F28335Boot_SetRunning(F28335_AB_NONE); /* Отмечает режим загрузчика, сохраняя уже восстановленную session в RAM автомата. */ + for (;;) { F28335CanBoot_Service(); ServiceDog(); } /* Обслуживает обновления и остаётся доступным при пустой/повреждённой EEPROM. */ +} /* Нормальный выход выполняется только через запуск RAM-приложения либо watchdog reset. */ diff --git a/c/protocan-boot/projects/ccs/f28335/shared_boot.c b/c/protocan-boot/projects/ccs/f28335/shared_boot.c new file mode 100644 index 0000000..733eb5d --- /dev/null +++ b/c/protocan-boot/projects/ccs/f28335/shared_boot.c @@ -0,0 +1,5 @@ +#include "../../../src/pcan_boot.c" /* Подключает единственный общий автомат ProtoCAN Boot и CRC32. */ +#include "../../../ports/tms320f28335/f28335_boot_store.c" /* Использует проверенный A/B-журнал, readback, SCI8 и откат. */ +#include "../../../ports/tms320f28335/f28335_flash_app.c" /* Проверяет FAB1 и CRC приложения ниже сектора A перед выбором основного Flash либо резервной EEPROM. */ +#include "../../../ports/tms320f28335/f28335_boot_hw.c" /* Подключает те же SPI, watchdog и handoff, что RAM-приложение. */ +#include "../../../ports/tms320f28335/f28335_can_boot.c" /* F28335_BOOT_LOADER=1 разрешает запись слотов только постоянному загрузчику. */ diff --git a/c/protocan-boot/projects/ccs/f28335/targetConfigs/TMS320F28335.ccxml b/c/protocan-boot/projects/ccs/f28335/targetConfigs/TMS320F28335.ccxml new file mode 100644 index 0000000..d074222 --- /dev/null +++ b/c/protocan-boot/projects/ccs/f28335/targetConfigs/TMS320F28335.ccxml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/c/protocan-boot/src/pcan_boot.c b/c/protocan-boot/src/pcan_boot.c index 2748d03..e1d3945 100644 --- a/c/protocan-boot/src/pcan_boot.c +++ b/c/protocan-boot/src/pcan_boot.c @@ -89,6 +89,17 @@ static bool send_status(pcan_boot_t *boot, pcan_boot_byte_t command, pcan_boot_b return send_frame(boot, PCAN_BOOT_MSG_STATUS, body, data, 8U); } +uint32_t pcan_boot_crc32_update(uint32_t crc, const pcan_boot_byte_t *data, size_t length) /* Публичный readback использует тот же полином и отражение, что приём DATA. */ +{ /* Не создаёт второго аппаратно зависимого варианта CRC в портах NOR/EEPROM. */ + return crc32_update(crc, data, length); /* Продолжает ранее полученное состояние либо начинает с нуля. */ +} /* Сохраняет существующую wire-совместимость всех портов. */ +bool pcan_boot_report_busy(pcan_boot_t *boot, pcan_boot_byte_t command, uint32_t now_ms) /* Позволяет синхронному erase отвечать, пока аппаратная операция ещё не завершена. */ +{ /* Порт вызывает функцию только в контексте main с живым экземпляром сессии. */ + if (boot == NULL) return false; /* Не обращается к неинициализированному экземпляру аппаратного порта. */ + boot->now_ms = boot->last_activity_ms = now_ms; /* Продвижение erase/verify считается живой активностью: длинная операция не должна сама истечь по тайм-ауту сессии. */ + return send_status(boot, command, PCAN_BOOT_STATUS_BUSY); /* Номер следующего блока и CRC берутся из настоящего состояния ядра. */ +} /* Окончательный OK/ошибку по завершении callback отправляет обычный автомат. */ + /* IDENTIFY имеет отдельный тип сообщения DISCOVERY и Body=1. Он доступен * без открытия сессии, поэтому обнаружение устройства не должно запускать обновление. */ static bool send_identity(pcan_boot_t *boot) diff --git a/c/protocan-boot/tests/f28335_stubs/DSP2833x_Device.h b/c/protocan-boot/tests/f28335_stubs/DSP2833x_Device.h index 00842d5..bd2cf58 100644 --- a/c/protocan-boot/tests/f28335_stubs/DSP2833x_Device.h +++ b/c/protocan-boot/tests/f28335_stubs/DSP2833x_Device.h @@ -9,5 +9,5 @@ static struct { struct MBOX MBOX3, MBOX4, MBOX6; } ECanaMboxes; static struct { struct test_reg CANME,CANMD,CANRMP,CANRML,CANMIM,CANTA,CANAA,CANTRS,CANTRR; } ECanaRegs; static struct { struct test_reg LAM3,LAM6; } ECanaLAMRegs; static struct { unsigned long InterruptCount; } CpuTimer1; -static struct { unsigned WDCR; } SysCtrlRegs; +/* Watchdog/reset моделируются callbacks; неиспользуемая глобальная копия SysCtrlRegs не требуется. */ #endif diff --git a/c/protocan-boot/tests/run_tests.py b/c/protocan-boot/tests/run_tests.py index 5180dea..48bbe9d 100644 --- a/c/protocan-boot/tests/run_tests.py +++ b/c/protocan-boot/tests/run_tests.py @@ -12,16 +12,21 @@ if not cc: store = 'ports/tms320f28335/f28335_boot_store.c' cases = [ ('core', [], ['src/pcan_boot.c', 'tests/test_pcan_boot.c']), + ('busy', ['-DPCAN_BOOT_WIDE_BYTES'], ['src/pcan_boot.c', 'tests/test_pcan_busy.c']), # Длительный NOR erase с BUSY продлевает session и сохраняет wire-поля ответа. ('store_native', [], [store, 'tests/test_f28335_boot_store.c']), ('store_wide', ['-DPCAN_BOOT_WIDE_BYTES'], [store, 'tests/test_f28335_boot_store.c']), ('loader', ['-DPCAN_BOOT_WIDE_BYTES'], [store, 'src/pcan_boot.c', 'tests/test_f28335_can_boot.c']), ('application', ['-DPCAN_BOOT_WIDE_BYTES', '-DF28335_BOOT_LOADER=0'], [store, 'src/pcan_boot.c', 'tests/test_f28335_can_boot.c']), + ('f2812_nor', ['-DPCAN_BOOT_WIDE_BYTES', '-DBOOT2812_HOST'], ['src/pcan_boot.c', 'ports/tms320f2812/nor_flash.c', 'ports/tms320f2812/boot_store.c', 'tests/test_f2812_nor.c']), # Проверяет настоящий AMD driver, NOR manifest, SCI8 и восстановление после обрывов записи. + ('stm32f103', ['-DTEST_STM32F103', '-Itests/stm32_stubs'], ['src/pcan_boot.c', 'ports/stm32f103/pcan_boot_stm32f103.c', 'tests/test_stm32_ports.c']), # Проверяет production-порт F103: границы страниц, все хвосты CAN, CRC readback и отказ reset без TX ACK. + ('stm32f407', ['-Itests/stm32_stubs'], ['src/pcan_boot.c', 'ports/stm32f407/pcan_boot_stm32f407.c', 'tests/test_stm32_ports.c']), # Проверяет production-порт F407, включая сохранность загрузчика и EEPROM-кольца секторов 6/7. + ('stm32g474', ['-DTEST_STM32G474', '-Itests/stm32_stubs'], ['src/pcan_boot.c', 'ports/stm32g474/pcan_boot_stm32g474.c', 'tests/test_stm32_ports.c']), # Проверяет FDCAN, обе геометрии DBANK, границу банков и запрет bank swap/ошибочной ёмкости Flash. ] with tempfile.TemporaryDirectory(prefix='f28335-ab-') as tmp: for name, defines, sources in cases: exe = Path(tmp) / (name + '.exe') - subprocess.run([cc, '-std=c99', '-Wall', '-Wextra', '-Werror', '-Iinclude', + subprocess.run([cc, '-std=c99', '-Wall', '-Wextra', '-Werror', '-Wno-misleading-indentation', '-Iinclude', # GCC допускает существующие однострочные циклы старых аппаратных моделей без подавления остальных ошибок. '-Itests/f28335_stubs', *defines, *sources, '-o', str(exe)], cwd=root, check=True) sample = os.environ.get('F28335_SAMPLE_IMAGE') if name == 'store_wide' else None subprocess.run([str(exe), *([sample] if sample else [])], check=True, timeout=30) diff --git a/c/protocan-boot/tests/stm32_stubs/stm32_hal_fake.h b/c/protocan-boot/tests/stm32_stubs/stm32_hal_fake.h new file mode 100644 index 0000000..f548ae1 --- /dev/null +++ b/c/protocan-boot/tests/stm32_stubs/stm32_hal_fake.h @@ -0,0 +1,50 @@ +#ifndef STM32_HAL_FAKE_H /* Изолирует модель HAL от повторного включения семейных обёрток. */ +#define STM32_HAL_FAKE_H /* Включается только host-тестами, без регистров реального устройства. */ +#include /* Определяет типы адресов, таймеров и программируемых значений HAL. */ +typedef enum { HAL_OK = 0, HAL_ERROR = 1 } HAL_StatusTypeDef; /* Модель различает успех и аппаратный отказ. */ +typedef struct { uint32_t TSR; } CAN_TypeDef; /* Хранит только флаги завершения передачи, читаемые production-портом. */ +extern CAN_TypeDef stm32_test_can; /* Единственный экземпляр модели CAN1 принадлежит тестовому процессу. */ +#define CAN1 (&stm32_test_can) /* Заменяет адрес аппаратных регистров безопасным host-объектом. */ +typedef struct { CAN_TypeDef *Instance; } CAN_HandleTypeDef; /* Сохраняет используемое production-кодом поле HAL handle. */ +typedef struct { uint32_t StdId, ExtId, IDE, RTR, DLC, TransmitGlobalTime; } CAN_TxHeaderTypeDef; /* Повторяет поля TX-заголовка современного HAL bxCAN. */ +typedef struct { uint32_t StdId, ExtId, IDE, RTR, DLC; } CAN_RxHeaderTypeDef; /* Повторяет входные поля, проверяемые перед разбором кадра. */ +typedef struct { uint32_t FilterBank, FilterMode, FilterScale, FilterIdHigh, FilterIdLow, FilterMaskIdHigh, FilterMaskIdLow, FilterFIFOAssignment, FilterActivation, SlaveStartFilterBank; } CAN_FilterTypeDef; /* Позволяет проверить реальные маски адреса и broadcast discovery. */ +typedef struct { uint32_t TypeErase, PageAddress, NbPages, VoltageRange, Sector, NbSectors, Banks, Page; } FLASH_EraseInitTypeDef; /* Модель покрывает поля F1/F4/G4, но не подменяет ARM-проверку настоящих заголовков. */ +#define CAN_ID_EXT 4U /* IDE=1 расположен в бите 2 регистрового идентификатора bxCAN. */ +#define CAN_RTR_DATA 0U /* RTR=0 обозначает обычный кадр с данными. */ +#define CAN_TX_MAILBOX0 1U /* HAL кодирует первый mailbox младшим битом маски. */ +#define CAN_TX_MAILBOX1 2U /* HAL кодирует второй mailbox следующим битом маски. */ +#define CAN_TX_MAILBOX2 4U /* HAL кодирует третий mailbox битом 2. */ +#define CAN_TSR_TXOK0 2U /* Успешная передача mailbox 0: TSR bit 1. */ +#define CAN_TSR_TXOK1 512U /* Успешная передача mailbox 1: TSR bit 9. */ +#define CAN_TSR_TXOK2 131072U /* Успешная передача mailbox 2: TSR bit 17. */ +#define CAN_TSR_RQCP0 1U /* W1C подтверждение завершения mailbox 0 расположено в бите 0 TSR. */ +#define CAN_TSR_RQCP1 256U /* W1C подтверждение завершения mailbox 1 расположено в бите 8 TSR. */ +#define CAN_TSR_RQCP2 65536U /* W1C подтверждение завершения mailbox 2 расположено в бите 16 TSR. */ +#define CAN_FILTERMODE_IDMASK 0U /* Фильтр использует аппаратное сравнение по маске. */ +#define CAN_FILTERSCALE_32BIT 1U /* Модель различает полный 32-битный регистровый формат. */ +#define CAN_FILTER_FIFO0 0U /* Фильтры направляются в первый аппаратный FIFO. */ +#define CAN_RX_FIFO0 0U /* Production-порт читает только FIFO0. */ +#define ENABLE 1U /* HAL включает банк фильтра единичным флагом. */ +#define FLASH_TYPEERASE_PAGES 0U /* Семейный тип стирания STM32F1 в тестовом контракте. */ +#define FLASH_TYPEERASE_SECTORS 1U /* Семейный тип стирания STM32F4 в тестовом контракте. */ +#define FLASH_TYPEPROGRAM_HALFWORD 1U /* Выбирает двухбайтовую операцию модели F1. */ +#define FLASH_TYPEPROGRAM_WORD 2U /* Выбирает четырёхбайтовую операцию модели F4. */ +#define FLASH_VOLTAGE_RANGE_3 2U /* Модель проверяет профиль x32 с VDD 2,7..3,6 В. */ +#define FLASH_SECTOR_2 2U /* Начальный разрешённый сектор STM32F407 в профиле climate. */ +uint32_t HAL_GetTick(void); /* Даёт управляемый монотонный таймер для проверки тайм-аутов. */ +uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *can); /* Позволяет имитировать постоянно занятый передатчик. */ +HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *can, CAN_TxHeaderTypeDef *header, uint8_t *data, uint32_t *mailbox); /* Сохраняет сформированный production-кодом ответ. */ +uint32_t HAL_CAN_IsTxMessagePending(CAN_HandleTypeDef *can, uint32_t mailbox); /* Позволяет имитировать незавершённую передачу перед reset. */ +HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *can, uint32_t mailbox); /* Фиксирует снятие TX-запроса после тайм-аута. */ +HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *can, CAN_FilterTypeDef *filter); /* Сохраняет оба аппаратных фильтра загрузчика. */ +HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *can); /* Позволяет проверить отказ запуска аппаратного транспорта. */ +uint32_t HAL_CAN_GetRxFifoFillLevel(CAN_HandleTypeDef *can, uint32_t fifo); /* Возвращает число заранее подготовленных входящих кадров. */ +HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *can, uint32_t fifo, CAN_RxHeaderTypeDef *header, uint8_t *data); /* Передаёт production-коду входной заголовок без обхода его проверок. */ +HAL_StatusTypeDef HAL_FLASH_Unlock(void); /* Устанавливает признак разрешённого изменения модели Flash. */ +HAL_StatusTypeDef HAL_FLASH_Lock(void); /* Восстанавливает блокировку после успеха и ошибок. */ +HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *erase, uint32_t *error); /* Стирает настоящую выбранную область host-отображения Flash. */ +HAL_StatusTypeDef HAL_FLASH_Program(uint32_t type, uint32_t address, uint64_t value); /* Программирует модель только в пределах профиля и с правильным выравниванием. */ +void FLASH_FlushCaches(void); /* Фиксирует обязательное обновление представления Flash F407 после записи перед readback. */ +void NVIC_SystemReset(void); /* Записывает факт reset вместо сброса host-процесса. */ +#endif /* Завершает минимальный контракт тестовой HAL-модели. */ diff --git a/c/protocan-boot/tests/stm32_stubs/stm32f1xx_hal.h b/c/protocan-boot/tests/stm32_stubs/stm32f1xx_hal.h new file mode 100644 index 0000000..3847482 --- /dev/null +++ b/c/protocan-boot/tests/stm32_stubs/stm32f1xx_hal.h @@ -0,0 +1 @@ +#include "stm32_hal_fake.h" /* Предоставляет host-модель HAL для production-порта F103. */ diff --git a/c/protocan-boot/tests/stm32_stubs/stm32f4xx_hal.h b/c/protocan-boot/tests/stm32_stubs/stm32f4xx_hal.h new file mode 100644 index 0000000..313b363 --- /dev/null +++ b/c/protocan-boot/tests/stm32_stubs/stm32f4xx_hal.h @@ -0,0 +1 @@ +#include "stm32_hal_fake.h" /* Предоставляет host-модель HAL для production-порта F407. */ diff --git a/c/protocan-boot/tests/stm32_stubs/stm32g4xx_hal.h b/c/protocan-boot/tests/stm32_stubs/stm32g4xx_hal.h new file mode 100644 index 0000000..3547077 --- /dev/null +++ b/c/protocan-boot/tests/stm32_stubs/stm32g4xx_hal.h @@ -0,0 +1,54 @@ +#ifndef STM32_G4_HAL_FAKE_H /* Защищает дополнительные FDCAN/Flash-типы от повторного включения. */ +#define STM32_G4_HAL_FAKE_H /* Обозначает активную host-модель HAL STM32G4. */ +#include "stm32_hal_fake.h" /* Повторно использует таймер, Flash API и host-модель базовых HAL-типов. */ +typedef struct { uint32_t OPTR; } FLASH_TypeDef; /* Моделирует DBANK и запрет BFB2, проверяемые production-портом. */ +typedef struct { uint32_t MEMRMP; } SYSCFG_TypeDef; /* Моделирует запрет программной перестановки физических банков. */ +typedef struct { uint32_t TXBTO; } FDCAN_GlobalTypeDef; /* Моделирует флаг подтверждённой физической передачи TX-буфера. */ +extern FLASH_TypeDef stm32_test_flash; extern SYSCFG_TypeDef stm32_test_syscfg; extern FDCAN_GlobalTypeDef stm32_test_fdcan; extern uint16_t stm32_test_flash_kib; /* Тест управляет независимыми аппаратными регистрами и физической ёмкостью MCU. */ +#define FLASH (&stm32_test_flash) /* Читает Flash geometry из безопасного host-объекта. */ +#define SYSCFG (&stm32_test_syscfg) /* Читает состояние remap из безопасного host-объекта. */ +#define FDCAN1 (&stm32_test_fdcan) /* Единственный выделенный контроллер G474-порта. */ +#define FLASHSIZE_BASE ((uintptr_t)&stm32_test_flash_kib) /* Подменяет аппаратный density-register проверяемым значением в КиБ. */ +#define FLASH_BASE 0x08000000UL /* Сохраняет реальные адреса Cortex-M Flash в host-отображении. */ +#define FLASH_OPTR_DBANK 1U /* Независимый бит режима single/dual bank для геометрической проверки. */ +#define FLASH_OPTR_BFB2 2U /* Независимый бит запрещённого bank boot swap. */ +#define SYSCFG_MEMRMP_FB_MODE 1U /* Независимый бит запрещённого программного bank swap. */ +#define __HAL_RCC_SYSCFG_CLK_ENABLE() ((void)0) /* Host-регистр MEMRMP всегда доступен; реальный порт сам включает его clock. */ +#define FLASH_BANK_1 1U /* Выбирает первый физический Flash-банк в модели HAL. */ +#define FLASH_BANK_2 2U /* Выбирает второй физический Flash-банк в модели HAL. */ +#define FLASH_TYPEPROGRAM_DOUBLEWORD 3U /* Выбирает восьмибайтовую аппаратную запись G474. */ +typedef struct { FDCAN_GlobalTypeDef *Instance; struct { uint32_t ExtFiltersNbr; } Init; } FDCAN_HandleTypeDef; /* Повторяет проверяемый handle и число аппаратных extended-фильтров. */ +typedef struct { uint32_t Identifier, IdType, TxFrameType, DataLength, ErrorStateIndicator, BitRateSwitch, FDFormat, TxEventFifoControl; } FDCAN_TxHeaderTypeDef; /* Позволяет проверить classic extended TX и все используемые поля HAL. */ +typedef struct { uint32_t Identifier, IdType, RxFrameType, DataLength, FDFormat; } FDCAN_RxHeaderTypeDef; /* Позволяет подать неверный DLC, remote либо CAN FD кадр в настоящий RX adapter. */ +typedef struct { uint32_t IdType, FilterIndex, FilterType, FilterConfig, FilterID1, FilterID2; } FDCAN_FilterTypeDef; /* Сохраняет реальные адресные маски production-порта. */ +#define FDCAN_DLC_BYTES_0 (0U << 16U) /* Модель намеренно использует старое кодирование HAL DLC со сдвигом 16, в отличие от проверяемого ARM SDK. */ +#define FDCAN_DLC_BYTES_1 (1U << 16U) /* Один полезный октет в старом HAL-кодировании DLC. */ +#define FDCAN_DLC_BYTES_2 (2U << 16U) /* Два полезных октета в старом HAL-кодировании DLC. */ +#define FDCAN_DLC_BYTES_3 (3U << 16U) /* Три полезных октета в старом HAL-кодировании DLC. */ +#define FDCAN_DLC_BYTES_4 (4U << 16U) /* Четыре полезных октета в старом HAL-кодировании DLC. */ +#define FDCAN_DLC_BYTES_5 (5U << 16U) /* Пять полезных октетов в старом HAL-кодировании DLC. */ +#define FDCAN_DLC_BYTES_6 (6U << 16U) /* Шесть полезных октетов в старом HAL-кодировании DLC. */ +#define FDCAN_DLC_BYTES_7 (7U << 16U) /* Семь полезных октетов в старом HAL-кодировании DLC. */ +#define FDCAN_DLC_BYTES_8 (8U << 16U) /* Восемь полезных октетов в старом HAL-кодировании DLC. */ +#define FDCAN_EXTENDED_ID CAN_ID_EXT /* Объединяет входной формат тестовых сценариев bxCAN и FDCAN без изменения production-кода. */ +#define FDCAN_DATA_FRAME CAN_RTR_DATA /* Сохраняет значение обычного data-кадра для общей модели RX. */ +#define FDCAN_ESI_ACTIVE 0U /* Передатчик модели не находится в пассивном состоянии ошибок. */ +#define FDCAN_BRS_OFF 0U /* ProtoCAN Boot не переключает битовую скорость внутри кадра. */ +#define FDCAN_CLASSIC_CAN 0U /* Выбирает classic CAN вместо CAN FD. */ +#define FDCAN_NO_TX_EVENTS 0U /* Production-порт проверяет TXBTO, не используя отдельную TX Event FIFO. */ +#define FDCAN_FILTER_MASK 0U /* Фильтр сопоставляет ID и аппаратную маску адреса. */ +#define FDCAN_FILTER_TO_RXFIFO0 0U /* Оба разрешённых фильтра направляют сообщения в FIFO0. */ +#define FDCAN_RX_FIFO0 0U /* Загрузчик использует единственную входную FIFO0. */ +#define FDCAN_REJECT 2U /* Неподходящие стандартные и расширенные кадры должны отвергаться. */ +#define FDCAN_REJECT_REMOTE 1U /* Remote-запросы запрещены независимо от совпадения ID. */ +uint32_t HAL_FDCAN_GetTxFifoFreeLevel(const FDCAN_HandleTypeDef *can); /* Моделирует свободный либо постоянно занятый передатчик. */ +HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *can, const FDCAN_TxHeaderTypeDef *header, const uint8_t *data); /* Сохраняет безопасный TX payload и аппаратный результат. */ +uint32_t HAL_FDCAN_GetLatestTxFifoQRequestBuffer(const FDCAN_HandleTypeDef *can); /* Возвращает bitmask последнего поставленного TX-буфера. */ +uint32_t HAL_FDCAN_IsTxBufferMessagePending(const FDCAN_HandleTypeDef *can, uint32_t buffer); /* Удерживает запрос незавершённым для проверки тайм-аута перед reset. */ +HAL_StatusTypeDef HAL_FDCAN_AbortTxRequest(FDCAN_HandleTypeDef *can, uint32_t buffer); /* Фиксирует отмену неподтверждённой передачи. */ +HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *can, const FDCAN_FilterTypeDef *filter); /* Сохраняет два адресных фильтра G474. */ +HAL_StatusTypeDef HAL_FDCAN_ConfigGlobalFilter(FDCAN_HandleTypeDef *can, uint32_t standard, uint32_t extended, uint32_t remote_standard, uint32_t remote_extended); /* Проверяет запрет всех неразрешённых и remote кадров. */ +HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *can); /* Позволяет имитировать отказ аппаратного старта. */ +uint32_t HAL_FDCAN_GetRxFifoFillLevel(const FDCAN_HandleTypeDef *can, uint32_t fifo); /* Передаёт число подготовленных модельных кадров. */ +HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *can, uint32_t fifo, FDCAN_RxHeaderTypeDef *header, uint8_t *data); /* Подаёт кадр в настоящий production RX adapter с кодированием DLC выбранного HAL. */ +#endif /* Завершает дополнительные типы и API модели G474. */ diff --git a/c/protocan-boot/tests/test_f2812_nor.c b/c/protocan-boot/tests/test_f2812_nor.c new file mode 100644 index 0000000..08ac4ff --- /dev/null +++ b/c/protocan-boot/tests/test_f2812_nor.c @@ -0,0 +1,83 @@ +#include "../ports/tms320f2812/boot2812.h" /* Проверяет реальные callbacks NOR и общий ProtoCAN codec в wide-octet режиме. */ +#include /* Любое нарушение границ, публикации или CRC завершает тест ошибкой. */ +#include /* Модель физической x16 памяти использует ровно 16 бит на слово даже на ПК. */ +#include /* Сообщает результат поведенческих сценариев без физического JTAG. */ +#include /* Подготавливает память и отдельные структуры C-ядра перед серией. */ +static uint16_t memory[0x80000]; /* AM29LV800BT содержит 512K слов x16, то есть 1 МиБ. */ +static unsigned int state, selected, bad_id, erases, programmed, busy_calls, loaded_words, stuck; /* Состояния относятся только к модели командной шины AMD. */ +static long budget = -1; /* Отрицательное значение разрешает записи, ноль моделирует исчезновение питания перед очередным word program. */ +static unsigned long clock_ms; /* Детерминированные часы позволяют проверить ограниченный выход из polling. */ +unsigned long Boot2812_Now(void) { return clock_ms++; } /* Продвигает миллисекунды без зависимости теста от wall clock ПК. */ +void Boot2812_Busy(void) { ++busy_calls; } /* Подтверждает, что длительное ожидание вызывает разрешённый сервис BUSY. */ +void NorModel_LoadWord(uint32_t target, unsigned int value) /* Получает только реальные записи валидатора в разрешённую RAM приложения. */ +{ /* Тестовый образ ниже содержит пять слов H0. */ + assert(target >= 0x3F8000UL && target < 0x3F8005UL); assert(value == 0U); ++loaded_words; /* Неверный адрес либо повреждённый payload не может скрыться в аппаратной заглушке. */ +} /* Запись в адресное пространство процесса ПК отсутствует. */ +unsigned int NorModel_Read(unsigned long word) /* Имитирует обычное чтение либо режим autoselect чипа. */ +{ /* Все обращения обязаны оставаться внутри установленной физической NOR. */ + assert(word >= BOOT2812_NOR_BASE && word < BOOT2812_NOR_BASE + 0x80000UL); /* Выход на соседнюю XINTF-память является ошибкой драйвера. */ + if (selected) return word == BOOT2812_NOR_BASE ? (bad_id ? 2U : 1U) : 0x22DAU; /* Модель отличает правильный AMD от неподходящего производителя. */ + if (stuck && word >= BOOT2812_IMAGE_WORD) return 0U; /* DQ7=0/DQ5=0 удерживают erase busy до программного тайм-аута. */ + return memory[word - BOOT2812_NOR_BASE]; /* Возвращает настоящие 16-битные данные модели. */ +} /* Чтение не выполняет скрытых записей и не исправляет повреждённые данные. */ +void NorModel_Write(unsigned long word, unsigned int value) /* Проверяет настоящий unlock state machine драйвера, а не принимает готовые запросы erase. */ +{ /* Командные адреса трактуются как x16 смещения согласно datasheet AMD. */ + assert(word >= BOOT2812_NOR_BASE && word < BOOT2812_NOR_BASE + 0x80000UL); /* Любой командный цикл ограничен физическим чипом. */ + if (state == 3U) { /* После A0 следующий цикл обязательно содержит программируемое слово данных. */ + if (budget != 0) { memory[word - BOOT2812_NOR_BASE] &= (uint16_t)value; ++programmed; if (budget > 0) --budget; } /* NOR программирует только переходы 1→0; обрыв питания оставляет прежнее слово. */ + state = 0U; return; /* Программирование одного слова завершает командную последовательность. */ + } /* Значение F0 в payload не должно ошибочно интерпретироваться как отдельная команда Reset. */ + if (value == 0xF0U) { state = selected = 0U; return; } /* Reset возвращает обычное чтение независимо от предыдущей незавершённой команды. */ + if (state == 0U) { assert(word == BOOT2812_NOR_BASE + 0x555UL && value == 0xAAU); state = 1U; } /* Первый unlock-цикл проверяется вместе с адресом. */ + else if (state == 1U) { assert(word == BOOT2812_NOR_BASE + 0x2AAUL && value == 0x55U); state = 2U; } /* Второй цикл исключает ошибочную x8 адресацию. */ + else if (state == 2U) { /* Третий цикл выбирает только одну из поддерживаемых безопасных команд. */ + assert(word == BOOT2812_NOR_BASE + 0x555UL); /* Командный регистр находится по x16 смещению 555h. */ + if (value == 0x90U) { selected = 1U; state = 0U; } /* Autoselect не изменяет содержимое памяти. */ + else if (value == 0xA0U) state = 3U; /* Следующий цикл будет word program. */ + else { assert(value == 0x80U); state = 4U; } /* Стирание требует второй unlock-пары, а не одного произвольного слова. */ + } /* Завершает декодирование третьего такта AMD. */ + else if (state == 4U) { assert(word == BOOT2812_NOR_BASE + 0x555UL && value == 0xAAU); state = 5U; } /* Проверяет четвёртый цикл Sector Erase. */ + else if (state == 5U) { assert(word == BOOT2812_NOR_BASE + 0x2AAUL && value == 0x55U); state = 6U; } /* Проверяет пятый цикл Sector Erase. */ + else { /* Шестой цикл выбирает только разрешённый отдельный сектор. */ + unsigned long count = word == BOOT2812_META_WORD ? 0x2000UL : 0x8000UL, i; /* Модель различает обычные и последние top-boot сектора. */ + assert(value == 0x30U); assert(word == BOOT2812_META_WORD || word == BOOT2812_IMAGE_WORD || word == BOOT2812_IMAGE_WORD + 0x8000UL || word == BOOT2812_IMAGE_WORD + 0x10000UL); /* Запрещает Chip Erase и любые соседние секторы legacy/FPGA. */ + for (i = 0; i < count; ++i) memory[word - BOOT2812_NOR_BASE + i] = 0xFFFFU; /* Реально стирает все слова выбранного сектора модели. */ + ++erases; state = 0U; /* Сохраняет число аппаратных sector erase для проверки отказов до разрушительных циклов. */ + } /* Завершает разрешённую операцию command bus. */ +} /* Модель не предоставляет драйверу обходного пути прямой записи массива. */ +static pcan_boot_byte_t image[40]; /* Небольшой полный SCI8: заголовок 22, секция 6+10, терминатор 2 октета. */ +static pcan_boot_manifest_t manifest; /* Metadata используют те же размеры и совместимость, что настоящий клиент. */ +static void make_image(void) /* Создаёт независимо определённый SCI8 с entry=3F8000 и пятью нулевыми словами H0. */ +{ /* Нулевой payload облегчает точную проверку каждого перенесённого слова. */ + memset(image, 0, sizeof(image)); image[0] = 0xAAU; image[1] = 8U; image[18] = 0x3FU; image[21] = 0x80U; image[22] = 5U; image[24] = 0x3FU; image[27] = 0x80U; /* Адрес TI передаётся старшим словом вперёд, внутри слова — little endian. */ + memset(&manifest, 0, sizeof(manifest)); manifest.image_size = 40UL; manifest.image_crc32 = pcan_boot_crc32_update(0UL, image, 40U); /* Начальная CRC вычисляется общим codec по независимому массиву файла. */ + manifest.product_type = BOOT2812_PRODUCT; manifest.hardware_revision_min = manifest.hardware_revision_max = 1U; /* Проверяет исключительно совместимый профиль F2812. */ +} /* Последующие сценарии меняют данные с новой CRC, чтобы отделить ошибки структуры от ошибок передачи. */ +static void save_image(void) /* Заполняет слоты через настоящие production callbacks, а не memcpy в образ. */ +{ /* Каждая порция соответствует одному восьмиоктетному CAN DATA. */ + unsigned int i; assert(Boot2812_Erase(0, 0U)); /* Перед каждой полной передачей удаляет marker и три полных сектора образа. */ + for (i = 0; i < 40U; i += 8U) assert(Boot2812_Write(0, 0U, i, image + i, 8U)); /* Проверяет упаковку октетов и readback каждого x16 слова. */ +} /* Только после завершения записи разрешены VERIFY и COMMIT. */ +int main(void) /* Проверяет драйвер, SCI8, publication и независимость соседних данных платы. */ +{ /* Все операции используют модель, физический CAN/JTAG не открывается. */ + unsigned long i; uint32_t entry; unsigned int before, cut; /* Счётчики контролируют защищённые диапазоны и обрывы manifest. */ + for (i = 0; i < 0x80000UL; ++i) memory[i] = 0x5AA5U; make_image(); /* Заполняет весь чип контрольным значением, включая старые данные и FPGA. */ + bad_id = 1U; before = erases; assert(!Boot2812_Erase(0, 0U) && erases == before); bad_id = 0U; /* Неподходящий производитель блокируется до первого sector erase. */ + assert(!Boot2812_NorErase(0x100000UL) && !Boot2812_NorErase(BOOT2812_IMAGE_WORD + 1UL)); /* Не разрешает старую область либо адрес внутри разрешённого сектора вместо его точного начала. */ + assert(!Boot2812_NorProgram(0x130000UL, 0U)); /* FPGA-образ запрещён даже при ошибочном прямом вызове нижнего драйвера. */ + save_image(); assert(Boot2812_Verify(0, 0U, &manifest) == PCAN_BOOT_STATUS_OK); /* Реальный NOR readback и формат SCI8 должны совпасть с входом. */ + assert(!Boot2812_Load(&entry)); assert(Boot2812_Commit(0, 0U, &manifest)); loaded_words = 0U; assert(Boot2812_Load(&entry) && entry == 0x3F8000UL && loaded_words == 5U); /* До COMMIT загрузка запрещена, после него переносятся ровно проверенные слова H0. */ + before = programmed; assert(!Boot2812_NorProgram(BOOT2812_IMAGE_WORD, 0xFFFFU) && programmed == before); /* Перевод 0→1 отклоняется без лишней попытки аппаратного program. */ + for (cut = 0; cut <= 12U; ++cut) { /* Проверяет публикацию при обрыве на каждом месте manifest из двенадцати слов. */ + bool committed; save_image(); budget = (long)cut; committed = Boot2812_Commit(0, 0U, &manifest); budget = -1; /* Останавливает только циклы NOR word program, не подменяя механизм публикации. */ + loaded_words = 0U; assert(Boot2812_Load(&entry) == committed); /* Незавершённая публикация остаётся recovery; полностью опубликованный образ запускается. */ + } /* Предыдущие legacy-данные всё время остаются за пределами разрешённого erase. */ + save_image(); memory[BOOT2812_IMAGE_WORD - BOOT2812_NOR_BASE + 15UL] ^= 1U; assert(Boot2812_Verify(0, 0U, &manifest) == PCAN_BOOT_STATUS_CRC_ERROR); /* Порча физической NOR обнаруживается независимо от принятой потоковой CRC. */ + make_image(); image[18] = 0U; image[21] = 0x90U; image[24] = 0U; image[27] = 0x90U; manifest.image_crc32 = pcan_boot_crc32_update(0UL, image, 40U); save_image(); /* Формирует целостную, но опасную секцию в L1 работающего загрузчика. */ + assert(Boot2812_Verify(0, 0U, &manifest) == PCAN_BOOT_STATUS_INVALID_STATE && !Boot2812_Commit(0, 0U, &manifest)); /* Корректная CRC не разрешает перезапись очереди и состояния сессии. */ + make_image(); stuck = 1U; before = busy_calls; assert(!Boot2812_NorErase(BOOT2812_IMAGE_WORD) && busy_calls > before); stuck = 0U; /* Постоянный DQ7 busy даёт ограниченный отказ и вызывает живой сервис BUSY. */ + for (i = 0; i < 0x60000UL; ++i) assert(memory[i] == 0x5AA5U); /* Сохраняет весь нижний участок старого firmware, параметров и FPGA, а не одну контрольную точку. */ + for (i = 0x78000UL; i < 0x7E000UL; ++i) assert(memory[i] == 0x5AA5U); /* Промежуточные top-boot сектора 15/16/17 также не стираются. */ + puts("F2812 NOR: AMD commands, ID, bounds, CRC, SCI8, torn commit, timeout and legacy/FPGA preservation: OK"); /* Перечисляет программно проверенные свойства аппаратного порта. */ + return 0; /* Успех означает завершение всех граничных и отказных сценариев. */ +} /* Политика аппаратного boot/CPLD дополнительно проверяется на реальной плате. */ diff --git a/c/protocan-boot/tests/test_f28335_can_boot.c b/c/protocan-boot/tests/test_f28335_can_boot.c index 2c2ac74..9d1bc6a 100644 --- a/c/protocan-boot/tests/test_f28335_can_boot.c +++ b/c/protocan-boot/tests/test_f28335_can_boot.c @@ -12,34 +12,64 @@ void ServiceDog(void); static unsigned char memory[0x40000]; static unsigned int running=255,resets,reset_arg,dog_feeds; static int fail_write; +static unsigned int write_calls; /* Счётчик аппаратных записей доказывает, что чужие CAN-команды не касаются EEPROM. */ void ServiceDog(void) { ++dog_feeds; } bool F28335Boot_Read(void *u,uint32_t a,pcan_boot_byte_t *p,unsigned int n) { unsigned i; (void)u; assert(a+n<=sizeof(memory)); for(i=0;i>(i*8))&255; } +static void address_isolation(void) /* Проверяет все 32 назначения Excel, аппаратный RX-фильтр и защиту записи от соседних плат. */ +{ /* Одна модель последовательно представляет каждый физический PERIPH и получает команды всем остальным. */ + unsigned int periph,peer,type,command_id,before=write_calls; /* Сохраняет счётчик записи до проверки, чтобы обнаружить любой побочный эффект чужого кадра. */ + for(periph=0U;periph<32U;++periph) { /* Покрывает обе границы Type 1/2 и все четырёхбитные Device ID. */ + F28335CanBoot_Init(periph); /* Тот же production Init используется RAM-приложением и Flash recovery. */ + assert(addressed && boot.config.device_type==1U+periph/16U && boot.config.device_id==periph%16U); /* Сверяет независимую ожидаемую раскладку Excel со всей конфигурацией устройства. */ + assert((ECanaMboxes.MBOX3.MSGID.all&0x07F00000UL)==((uint32_t)(1U+periph/16U)<<24|((uint32_t)(periph%16U)<<20))); /* Проверяет аппаратный фильтр, а не только программный parser. */ + for(peer=0U;peer<32U;++peer) { /* Включает пары задатчик↔УМП1/УМП2 и совпадающий Device ID в другом Type. */ + if(peer==periph) continue; /* Собственный адрес должен обслуживаться штатными сценариями ниже, поэтому здесь проверяются только чужие. */ + for(type=9U;type<=11U;++type) { /* Проверяет управляющий сервис и оба пространства данных слотов A/B. */ + for(command_id=2U;command_id<=9U;++command_id) { /* ENTER, метаданные, ERASE, VERIFY, COMMIT, CONFIRM и REBOOT должны игнорировать чужой адрес. */ + uint32_t id=pcan_boot_make_id(1,0,1U+peer/16U,peer%16U,type,type==9U?0x100U|command_id:0U); /* Формирует реальный 29-битный запрос соседнему PERIPH с ненулевой сессией. */ + assert(!pcan_boot_process(&boot,id,0,0)); /* Ядро не должно подтверждать или выполнять команду, адресованную другой плате. */ + ECanaRegs.CANRMP.all=8UL; ECanaMboxes.MBOX3.MSGID.all=0x80000000UL|id; /* Моделирует доставку чужого кадра железом вопреки аппаратному фильтру. */ + ECanaMboxes.MBOX3.MSGCTRL.all=0U; ECanaMboxes.MBOX3.MSGCTRL.bit.DLC=0U; ECanaMboxes.MBOX3.MSGCTRL.bit.RTR=0U; /* Исключает RTR как причину отказа, проверяя именно адрес. */ + F28335CanBoot_RxISR(); assert(head==0U && tail==0U && !tx_busy); /* Дополнительная ISR-защита не ставит чужую команду в очередь и не отправляет ответ. */ + } /* Завершает проверку изменяющих команд для выбранного пространства MsgType. */ + } /* Завершает проверку данных A/B и управляющего сервиса соседа. */ + } /* Переходит к следующему чужому номеру без перезаписи модели EEPROM. */ + assert(!pcan_boot_process(&boot,pcan_boot_make_id(1,0,3,7,9,0x102),0,0)); /* Прежний общий адрес 3/7 больше не разрешает вход в загрузчик ни одной платы. */ + } /* Заканчивает проверку уникальности всей таблицы PERIPH. */ + F28335CanBoot_Init(32U); assert(!addressed && !(ECanaRegs.CANME.all&88UL)); /* Недопустимый номер выключает Boot mailbox вместо перехода на общий адрес. */ + F28335CanBoot_Resume(1U); F28335CanBoot_Service(); assert(write_calls==before); /* Неверный адрес и все чужие команды не выполняют ни одной аппаратной записи. */ +} /* Последующие регрессии проверяют успешное обновление задатчика по адресу 1/8. */ int main(void) { pcan_boot_byte_t image[40]={0xAA,8},meta[8],compat[8]={0x33,0x28,1,1,2,0,1,1}; unsigned i,slot; pcan_boot_manifest_t m; memset(memory,0xA5,sizeof(memory)); image[21]=0x80; image[22]=5; image[27]=0x80; - F28335CanBoot_Init(); assert(boot.config.max_image_size==130560 && boot.config.slot_count==2); + address_isolation(); F28335CanBoot_Init(8U); assert(boot.config.max_image_size==130560 && boot.config.slot_count==2); /* Проверяет изоляцию всей шины перед штатной передачей задатчику. */ if(!F28335_BOOT_LOADER) { /* SPI-ROM application without Flash-loader handoff cannot erase anything. */ command(2,0,0); assert(boot.last_status==PCAN_BOOT_STATUS_INVALID_STATE && !reset_requested); + running=F28335_BOOT_FLASH_SLOT; F28335CanBoot_Init(8U); /* Достоверный handoff постоянного boot разрешает CAN-сервис защищённому Flash-приложению. */ + assert(confirmed && F28335CanBoot_WatchdogAllowed()); /* Flash не выдаётся за неподтверждённый EEPROM-кандидат и сохраняет штатное обслуживание watchdog. */ + command(12,0,0); assert(!F28335CanBoot_Active()); /* Диагностический PING не должен открывать сеанс прошивки или удерживать обычный запуск. */ + command(2,0,0); assert(reset_requested && reset_session==1U && F28335CanBoot_Active()); /* ENTER_BOOT из Flash планирует переход с той же session без прямой записи EEPROM. */ + running=255U; F28335CanBoot_Init(8U); /* Возвращает исходный SPI-ROM сценарий перед прежними тестами trial/CONFIRM и отката. */ memset(&m,0,sizeof(m));m.image_size=40;m.image_crc32=f28335_boot_crc(0,image,40); m.product_type=0x2833;m.hardware_revision_min=m.hardware_revision_max=1; assert(f28335_boot_prepare(&store,0)); for(i=0;i<40;i+=8)assert(f28335_boot_write(&store,0,i,image+i,8)); assert(f28335_boot_commit(&store,0,&m)); assert(f28335_boot_select(&store,&slot)); - running=0; F28335CanBoot_Init(); + running=0; F28335CanBoot_Init(8U); /* Пробное приложение сохраняет адрес задатчика после handoff постоянного загрузчика. */ assert(!F28335CanBoot_WatchdogAllowed()); command(8,0,0);assert(boot.last_status==PCAN_BOOT_STATUS_INVALID_STATE); F28335CanBoot_Ready(); @@ -55,7 +85,7 @@ int main(void) command(3,meta,8);command(4,compat,8);assert(boot.target_slot==0); command(5,0,0); for(i=0;i<5;++i) { tx_busy=0; assert(pcan_boot_process(&boot, - pcan_boot_make_id(1,0,3,7,10,i),image+i*8,8)); } + pcan_boot_make_id(1,0,1,8,10,i),image+i*8,8)); } /* Данные первого слота передаются только адресу задатчика. */ command(6,0,0);assert(boot.state==PCAN_BOOT_STATE_VERIFIED); command(7,0,0);assert(store.pending==0 && boot.state==PCAN_BOOT_STATE_COMMITTED); command(7,0,0);assert(boot.last_status==0); @@ -67,16 +97,16 @@ int main(void) } command(12,0,0); assert((ECanaMboxes.MBOX4.MSGID.all&65535)==12); command(13,0,0); assert(ECanaMboxes.MBOX4.MDH.all==130560); - meta[0]=0;command(14,meta,1); assert(ECanaMboxes.MBOX4.MDL.all==0x33383246UL); /* F283 */ + meta[0]=0;command(14,meta,1); assert(ECanaMboxes.MBOX4.MDL.all==0x6164615AUL); /* Первые четыре октета ASCII имени Zadatchik равны «Zada». */ meta[0]=3;command(15,meta,1);assert(ECanaMboxes.MBOX4.MDL.all==0x3FEFCUL); - assert(!pcan_boot_process(&boot,pcan_boot_make_id(1,0,3,6,9,0x102),0,0)); + assert(!pcan_boot_process(&boot,pcan_boot_make_id(1,0,1,6,9,0x102),0,0)); /* Адрес УМП2 1/6 не должен открывать сессию задатчика 1/8. */ tx_busy=0; assert(pcan_boot_process(&boot,pcan_boot_make_id(1,0,7,15,13,0),0,0)); assert(boot.discovery_pending); pcan_boot_poll(&boot,boot.discovery_at); assert(!boot.discovery_pending && (ECanaMboxes.MBOX4.MSGID.all&65535)==1); assert(!pcan_boot_process(&boot,pcan_boot_make_id(1,0,7,15,9,0x102),0,0)); head=tail=0; ECanaRegs.CANRMP.all=8; - ECanaMboxes.MBOX3.MSGID.all=0x80000000UL|pcan_boot_make_id(1,0,3,7,9,12); + ECanaMboxes.MBOX3.MSGID.all=0x80000000UL|pcan_boot_make_id(1,0,1,8,9,12); /* Собственный PING задатчика проходит очередь после проверки чужих адресов. */ ECanaMboxes.MBOX3.MSGCTRL.bit.DLC=0; F28335CanBoot_RxISR(); assert(head==1 && tail==0); tx_busy=0; F28335CanBoot_Service(); assert(tail==1); diff --git a/c/protocan-boot/tests/test_pcan_busy.c b/c/protocan-boot/tests/test_pcan_busy.c new file mode 100644 index 0000000..a7f0b72 --- /dev/null +++ b/c/protocan-boot/tests/test_pcan_busy.c @@ -0,0 +1,22 @@ +#include "../include/pcan_boot.h" /* Проверяет публичный BUSY codec и продление сессии на настоящем ядре. */ +#include /* Несовпадение состояния или wire-полей завершает тест ненулевым результатом. */ +#include /* Инициализирует опциональные поля конфигурации без аппаратных зависимостей. */ +static unsigned int status, body; /* Сохраняет наблюдаемые поля последнего настоящего STATUS кадра. */ +static bool send_frame(void *user, uint32_t id, const pcan_boot_byte_t *data, pcan_boot_byte_t length) /* Модель заменяет только физическую отправку CAN. */ +{ /* Содержимое статуса формирует production send_status, а не этот тест. */ + (void)user; assert(length == 8U && pcan_boot_id_msg_type(id) == 12U); status = data[0]; body = pcan_boot_id_msg_body(id); return true; /* Проверяет тип, длину и сохранённую session/command. */ +} /* Передача считается физически принятой аппаратным портом. */ +static bool erase(void *user, pcan_boot_byte_t slot) { (void)user; return slot == 0U; } /* Минимальный single-slot callback удовлетворяет обязательному контракту init. */ +static bool write_data(void *user, pcan_boot_byte_t slot, uint32_t offset, const pcan_boot_byte_t *data, pcan_boot_byte_t length) { (void)user; (void)offset; (void)data; return slot == 0U && length <= 8U; } /* Тест не программирует никакое реальное хранилище. */ +int main(void) /* Проверяет, что операция длиннее исходного session timeout остаётся живой при BUSY. */ +{ /* Без этой проверки длительный NOR erase мог бы закончиться уже отменённой сессией. */ + pcan_boot_t boot; pcan_boot_config_t config; pcan_boot_port_t port; /* Использует тот же экземпляр автомата, что аппаратные проекты. */ + memset(&config, 0, sizeof(config)); memset(&port, 0, sizeof(port)); config.slot_count = 1U; config.active_slot = 0U; config.session_timeout_ms = 30000UL; /* Сессия истекает через 30 секунд реального бездействия. */ + port.send = send_frame; port.erase_slot = erase; port.write_slot = write_data; assert(pcan_boot_init(&boot, &config, &port, 0)); /* Не обходит production валидацию обязательных callbacks. */ + assert(pcan_boot_process(&boot, pcan_boot_make_id(1U, 0U, 0U, 0U, 9U, 0x0102U), 0, 0U)); /* Открывает session=1 штатной командой ENTER_BOOT. */ + assert(pcan_boot_report_busy(&boot, 5U, 40000UL) && status == 1U && body == 0x0105U); /* BUSY долгого ERASE содержит исходную session и обновляет часы активности после сорока секунд. */ + pcan_boot_poll(&boot, 69999UL); assert(boot.state == PCAN_BOOT_STATE_METADATA); /* Почти 30 секунд после последнего BUSY ещё не означают тайм-аут. */ + pcan_boot_poll(&boot, 70000UL); assert(boot.state == PCAN_BOOT_STATE_IDLE); /* После полного интервала без прогресса сессия снова отменяется обычным способом. */ + assert(!pcan_boot_report_busy(0, 5U, 0UL)); /* Неинициализированный порт не должен вызывать аппаратный send. */ + return 0; /* Все проверки используют одно производственное ядро и его codec. */ +} /* Криптография и аппаратные сроки конкретной NOR не моделируются этим unit-тестом. */ diff --git a/c/protocan-boot/tests/test_project_release.py b/c/protocan-boot/tests/test_project_release.py new file mode 100644 index 0000000..3387f8d --- /dev/null +++ b/c/protocan-boot/tests/test_project_release.py @@ -0,0 +1,66 @@ +"""Проверки локального экспорта постоянных CAN-загрузчиков из CCS и CLI.""" # Аппаратное программирование и сеть в сценариях не используются. +import hashlib # Сверяет контрольные суммы экспортированных байтов OUT. +import importlib.util # Загружает настоящий сборщик проектов без запуска компиляции. +import json # Проверяет manifest, подготовку и указатель последнего выпуска. +from pathlib import Path # Все результаты проверок находятся во временных каталогах. +import tempfile # Изолирует тесты от пользовательских Debug/Release и SETGUI. +import unittest # Проверки запускаются штатным Python без Qt и дополнительных пакетов. +from unittest.mock import patch # Заменяет только аппаратный OFD-анализ тестового OUT, сохраняя настоящий экспорт и SHA-256. + +SPEC = importlib.util.spec_from_file_location("checked_canboot_projects", Path(__file__).resolve().parents[1] / "projects/build.py") # Выбирает сборщик из того же checkout templates. +BUILD = importlib.util.module_from_spec(SPEC) # Создаёт модуль без вызова CLI и без доступа к плате. +SPEC.loader.exec_module(BUILD) # Выполняет реальные функции prebuild/postbuild, проверяемые ниже. + + +class ProjectReleaseTests(unittest.TestCase): # Проверяет маршруты обоих контроллеров и отказ копирования при неполной или несогласованной сборке. + def test_current_out_map_and_hashes_are_exported_for_both_configurations(self): # Debug/Release F28335/F2812 обязаны экспортировать только свой комплект. + for device in ("f28335", "f2812"): # Покрывает отдельные имена OUT и каталоги двух контроллеров. + for configuration in ("Debug", "Release"): # Проверяет обе конфигурации каждого CCS-проекта. + with self.subTest(device=device, configuration=configuration), tempfile.TemporaryDirectory(prefix="canboot release ") as temporary: # Пробелы в путях проверяют передачу каталогов без shell-подстановок. + output = Path(temporary) / configuration; export = Path(temporary) / "SETGUI/canboot" / device[1:] # Тестовый SETGUI не затрагивает реальные файлы прошивок. + BUILD.prepare(device, configuration, BUILD.DEFAULT_COMPILER, output) # Настоящий prebuild сохраняет ревизию, конфигурацию и SHA исходников. + name = BUILD.settings(device, configuration, BUILD.DEFAULT_COMPILER)[1]; image = output / (name + ".out") # Имя артефакта читается из действующего CCS-проекта. + image.write_bytes(b"current OUT " + device.encode("ascii")); image.with_suffix(".map").write_text("current map", encoding="utf-8") # Создаёт различимые артефакты текущего выбранного контроллера. + (output / "unrelated.out").write_bytes(b"old build") # Старый соседний OUT не должен попасть в экспорт текущего выпуска. + with patch.object(BUILD, "verify", return_value={"entry_word": 1, "boot_word": 2, "loaded_words": 3}): # Модель заменяет лишь TI-декодирование искусственных байтов OUT. + BUILD.postbuild(device, configuration, BUILD.DEFAULT_COMPILER, output, export) # Архивирование, копирование и проверка SHA выполняются настоящим общим кодом. + receipt = json.loads((output / "firmware/latest_build.json").read_text(encoding="utf-8")); copied = Path(receipt["exported_directory"]) # Указатель должен вести на конкретный скопированный выпуск. + self.assertEqual(copied.parent, export) # F28335 и F2812 не смешиваются в одном каталоге контроллера. + self.assertEqual({file.name for file in copied.iterdir()}, {image.name, image.with_suffix(".map").name, image.name + ".manifest.json", image.name + ".sha256", "firmware_identity.json"}) # Экспорт содержит полный текущий комплект без старых OUT или объектных файлов. + self.assertEqual((copied / image.name).read_bytes(), image.read_bytes()) # OUT сохраняется побайтно, включая COFF-символы для JTAG. + manifest = json.loads((copied / (image.name + ".manifest.json")).read_text(encoding="utf-8")) # Проверяет внешний паспорт именно экспортированного файла. + self.assertEqual((manifest["device"], manifest["configuration"], manifest["purpose"]), (device, configuration, "canboot")) # Паспорт сохраняет выбранный контроллер, режим сборки и назначение загрузчика. + self.assertEqual(manifest["sha256"], hashlib.sha256(image.read_bytes()).hexdigest()) # Контрольная сумма относится к точным байтам OUT. + + def test_changed_sources_or_configuration_prevent_export(self): # Несогласованная подготовка не должна выпускать даже формально существующий OUT. + with tempfile.TemporaryDirectory() as temporary: # Изолирует изменение тестовых метаданных от реального prebuild. + output = Path(temporary) / "Debug"; export = Path(temporary) / "SETGUI" # Каталог назначения заранее отсутствует для явной проверки отказа копирования. + BUILD.prepare("f28335", "Debug", BUILD.DEFAULT_COMPILER, output) # Создаёт согласованный паспорт до моделируемого изменения исходников. + with patch.object(BUILD, "source_hashes", return_value={}): # Моделирует изменение дерева после подготовки без записи production-файлов. + with self.assertRaisesRegex(ValueError, "changed"): BUILD.postbuild("f28335", "Debug", BUILD.DEFAULT_COMPILER, output, export) # Несовпадение SHA останавливает выпуск до проверки и копирования OUT. + with self.assertRaisesRegex(ValueError, "changed"): BUILD.postbuild("f28335", "Release", BUILD.DEFAULT_COMPILER, output, export) # Debug-подготовку нельзя выдать за Release даже при одинаковых исходниках. + self.assertFalse(export.exists()) # Ошибочные подготовки не создают папку успешного выпуска в GUI. + + def test_missing_map_or_invalid_coff_prevent_export(self): # Наличие OUT без карты или с запрещёнными LOAD-адресами не разрешает экспорт. + with tempfile.TemporaryDirectory() as temporary: # Тестовые файлы удаляются вместе с изолированным каталогом. + output = Path(temporary) / "Debug"; export = Path(temporary) / "SETGUI" # Не использует аппаратные каталоги реальной установки. + BUILD.prepare("f2812", "Debug", BUILD.DEFAULT_COMPILER, output) # Сохраняет штатные входные данные выбранного F2812. + image = output / "F2812_CAN_NOR.out"; image.write_bytes(b"invalid COFF") # Искусственный OUT не должен считаться проверенным загрузчиком. + with self.assertRaisesRegex(ValueError, "MAP"): BUILD.postbuild("f2812", "Debug", BUILD.DEFAULT_COMPILER, output, export) # Отсутствие карты обнаруживается до запуска OFD. + image.with_suffix(".map").write_text("map", encoding="utf-8") # Дополняет комплект, чтобы отдельно проверить отказ COFF-анализа. + with patch.object(BUILD, "verify", side_effect=ValueError("invalid COFF")): # Моделирует диагностированный TI-декодером неверный образ. + with self.assertRaisesRegex(ValueError, "invalid COFF"): BUILD.postbuild("f2812", "Debug", BUILD.DEFAULT_COMPILER, output, export) # Неверные Flash-данные блокируются до любой публикации файлов. + self.assertFalse(export.exists()) # Ни один путь ошибки не оставляет ложный новый выпуск в SETGUI. + + def test_ccs_steps_match_device_and_configuration(self): # Проверяет все четыре реальные настройки Build Steps, которые вызывает CCS. + for device in ("f28335", "f2812"): # Отдельно проверяет маршруты 28335 и 2812. + for configuration in BUILD.ET.parse(BUILD.ROOT / "projects/ccs" / device / ".cproject").findall(".//configuration"): # Читает действующий XML, включая Debug и Release. + prepare = configuration.get("prebuildStep"); postbuild = configuration.get("postbuildStep") # Извлекает уже раскодированные XML-команды со штатными кавычками. + self.assertIn("--step prepare", prepare); self.assertIn("--step postbuild", postbuild) # Обе фазы обязаны вызывать общий сборщик в соответствующем режиме. + for command in (prepare, postbuild): # Контроллер и конфигурация должны совпадать на обеих фазах. + self.assertIn("--device " + device, command); self.assertIn("--configuration " + configuration.get("name"), command) # Предотвращает случайный паспорт другого проекта либо Debug вместо Release. + self.assertIn("balzam167/canboot/" + device[1:], postbuild) # Конечный каталог соответствует контроллеру постоянного загрузчика. + + +if __name__ == "__main__": # Импорт тестов не запускает их побочным эффектом. + unittest.main() # Поддерживает прямой запуск штатным Python из любого рабочего каталога. diff --git a/c/protocan-boot/tests/test_stm32_ports.c b/c/protocan-boot/tests/test_stm32_ports.c new file mode 100644 index 0000000..119e863 --- /dev/null +++ b/c/protocan-boot/tests/test_stm32_ports.c @@ -0,0 +1,259 @@ +#if defined(_WIN32) /* Windows требует VirtualAlloc для отображения Flash по настоящему адресу MCU. */ +#include /* Предоставляет выделение виртуальной памяти по фиксированному адресу. */ +#else /* POSIX использует аналогичное приватное отображение без файлов устройства. */ +#define _DEFAULT_SOURCE /* Разрешает MAP_ANONYMOUS при строгом режиме C99. */ +#include /* Предоставляет mmap и munmap для модели адресного пространства STM32. */ +#endif /* Завершает выбор host-платформы. */ +#include /* Останавливает проверку на первом нарушении границ или протокольного контракта. */ +#include /* Выводит компактный результат каждого семейного прогона. */ +#include /* Копирует данные модели Flash и сериализованные поля manifest. */ +#if defined(TEST_STM32F103) /* Один сценарий исполняется с настоящим семейным production-портом F1. */ +#include "../ports/stm32f103/pcan_boot_stm32f103.h" /* Подключает API проверяемого профиля STM32F103C8. */ +#define PORT_INIT pcan_boot_stm32f103_init /* Выбирает функцию настройки F103 без копирования сценариев. */ +#define PORT_POLL pcan_boot_stm32f103_poll /* Выбирает основной цикл транспорта F103. */ +#define PORT_VECTORS pcan_boot_stm32f103_vectors_valid /* Выбирает семейную проверку границ SRAM и Flash. */ +#define APP_BASE PCAN_BOOT_F103_APP_ADDRESS /* Берёт исходный адрес KONOR из production-заголовка. */ +#define APP_END PCAN_BOOT_F103_FLASH_END /* Берёт верхнюю границу штатной Flash F103C8. */ +#define RAM_TOP 0x20005000UL /* Тестовый MSP указывает за последним байтом 20 КиБ SRAM F103C8. */ +#define TEST_HANDLE CAN_HandleTypeDef /* F103 использует штатный bxCAN handle HAL. */ +#define TEST_INSTANCE CAN1 /* F103 проверяется с выделенным CAN1. */ +#elif defined(TEST_STM32G474) /* Третий прогон использует production FDCAN/Flash-порт G474. */ +#include "../ports/stm32g474/pcan_boot_stm32g474.h" /* Подключает готовый reusable G474-порт, а не boot main. */ +#define PORT_INIT pcan_boot_stm32g474_init /* Выбирает текущую настройку single-slot FDCAN-порта. */ +#define PORT_POLL pcan_boot_stm32g474_poll /* Выбирает обработку FDCAN FIFO0 и таймеров ядра. */ +#define PORT_VECTORS() pcan_boot_stm32g474_vectors_valid(CAN_BOOT_APP_SIZE) /* Сохраняет смысл структурной проверки всего профиля для общих сценариев. */ +#define APP_BASE CAN_BOOT_APP_ADDRESS /* G474 приложение начинается после исходных 32 КиБ загрузчика. */ +#define APP_END CAN_BOOT_FLASH_END /* Профиль G474 использует оставшиеся 480 КиБ Flash. */ +#define RAM_TOP 0x20014000UL /* Векторы исходного CANdle G474 ограничены основной используемой SRAM 80 КиБ. */ +#define TEST_HANDLE FDCAN_HandleTypeDef /* G474 использует современный FDCAN handle вместо bxCAN. */ +#define TEST_INSTANCE FDCAN1 /* Проверяется только выделенный FDCAN1 исходной платы. */ +#else /* Второй прогон компилирует те же сценарии с настоящим F407-портом. */ +#include "../ports/stm32f407/pcan_boot_stm32f407.h" /* Подключает API профиля climate. */ +#define PORT_INIT pcan_boot_stm32f407_init /* Выбирает функцию настройки F407. */ +#define PORT_POLL pcan_boot_stm32f407_poll /* Выбирает основной цикл транспорта F407. */ +#define PORT_VECTORS pcan_boot_stm32f407_vectors_valid /* Выбирает проверку векторов F407. */ +#define APP_BASE PCAN_BOOT_F407_APP_ADDRESS /* Берёт начало сектора 2 из production-заголовка. */ +#define APP_END PCAN_BOOT_F407_FLASH_END /* Исключает EEPROM-кольцо секторов 6 и 7. */ +#define RAM_TOP 0x20020000UL /* Тестовый MSP указывает за последним байтом основной SRAM F407. */ +#define TEST_HANDLE CAN_HandleTypeDef /* F407 использует штатный bxCAN handle HAL. */ +#define TEST_INSTANCE CAN1 /* F407 проверяется с выделенным CAN1. */ +#endif /* Завершает выбор проверяемой аппаратной реализации. */ +CAN_TypeDef stm32_test_can; /* Эмулирует регистр подтверждения TX, читаемый production-кодом. */ +static uint8_t *flash; /* Ссылается на host-отображение физического диапазона Flash STM32. */ +static uint32_t tick, sends, resets, aborted, erases, writes; /* Считает время и аппаратные эффекты сценария. */ +static bool unlocked, fail_erase, fail_write, corrupt_write, no_mailbox, pending, tx_error, fail_start; /* Управляет воспроизводимыми отказами HAL. */ +static uint8_t last_tx[8], rx_bytes[8]; /* Хранит полный безопасно скопированный TX и единственный входной payload. */ +static CAN_RxHeaderTypeDef rx_header; /* Содержит входной IDE/RTR/DLC для проверок транспортного адаптера. */ +static CAN_FilterTypeDef filters[2]; /* Фиксирует адресный и broadcast-discovery фильтры. */ +static bool have_rx; /* Моделирует наличие одного доступного кадра FIFO0. */ +static bool cache_dirty; /* Фиксирует необходимость синхронизации Flash-кэша F407 после HAL program. */ +#if defined(TEST_STM32G474) /* Расширяет общую модель только для FDCAN/двухбанковой Flash G474. */ +FLASH_TypeDef stm32_test_flash; SYSCFG_TypeDef stm32_test_syscfg; FDCAN_GlobalTypeDef stm32_test_fdcan; uint16_t stm32_test_flash_kib; /* Предоставляет production-коду безопасные регистры геометрии и TX. */ +static bool dual_bank; /* Перебирает оба штатных DBANK-режима одного физического G474VE 512 КиБ. */ +uint32_t HAL_FDCAN_GetTxFifoFreeLevel(const FDCAN_HandleTypeDef *can) { (void)can; return no_mailbox ? 0U : 3U; } /* Воспроизводит ожидание свободного аппаратного TX FIFO. */ +HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *can, const FDCAN_TxHeaderTypeDef *header, const uint8_t *data) /* Проверяет настоящий TX adapter G474 с иным кодированием DLC HAL. */ +{ /* Все восемь доступных байтов payload обязан подготовить production-порт. */ + assert(can->Instance == FDCAN1 && header->IdType == FDCAN_EXTENDED_ID && header->TxFrameType == FDCAN_DATA_FRAME && header->FDFormat == FDCAN_CLASSIC_CAN && header->DataLength <= FDCAN_DLC_BYTES_8); /* Не допускает случайный CAN FD, standard или некорректный DLC. */ + (void)memcpy(last_tx, data, 8U); can->Instance->TXBTO = tx_error ? 0U : 1U; ++sends; return HAL_OK; /* Имитирует отдельный TXBTO и проверяет запрет reset при отсутствии подтверждённой передачи. */ +} /* Завершает модель передачи FDCAN. */ +uint32_t HAL_FDCAN_GetLatestTxFifoQRequestBuffer(const FDCAN_HandleTypeDef *can) { (void)can; return 1U; } /* Выбирает bitmask первого TX-буфера, как реальный API HAL. */ +uint32_t HAL_FDCAN_IsTxBufferMessagePending(const FDCAN_HandleTypeDef *can, uint32_t buffer) { (void)can; assert(buffer == 1U); return pending; } /* Позволяет проверить тайм-аут именно поставленного TX-запроса. */ +HAL_StatusTypeDef HAL_FDCAN_AbortTxRequest(FDCAN_HandleTypeDef *can, uint32_t buffer) { (void)can; assert(buffer == 1U); ++aborted; return HAL_OK; } /* Считает отменённые после тайм-аута кадры. */ +HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *can, const FDCAN_FilterTypeDef *filter) { (void)can; assert(filter->FilterIndex < 2U); filters[filter->FilterIndex].FilterBank = filter->FilterIndex; filters[filter->FilterIndex].FilterMaskIdHigh = (filter->FilterID2 << 3U) >> 16U; return HAL_OK; } /* Сохраняет аппаратные маски адреса и discovery для общих проверок. */ +HAL_StatusTypeDef HAL_FDCAN_ConfigGlobalFilter(FDCAN_HandleTypeDef *can, uint32_t standard, uint32_t extended, uint32_t remote_standard, uint32_t remote_extended) { (void)can; assert(standard == FDCAN_REJECT && extended == FDCAN_REJECT && remote_standard == FDCAN_REJECT_REMOTE && remote_extended == FDCAN_REJECT_REMOTE); return HAL_OK; } /* Не позволяет broad фильтрации обойти проверку адресов и remote-кадров. */ +HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *can) { (void)can; return fail_start ? HAL_ERROR : HAL_OK; } /* Воспроизводит отказ аппаратного запуска FDCAN. */ +uint32_t HAL_FDCAN_GetRxFifoFillLevel(const FDCAN_HandleTypeDef *can, uint32_t fifo) { (void)can; assert(fifo == FDCAN_RX_FIFO0); return have_rx; } /* Сообщает наличие подготовленного общего тестового RX-кадра. */ +HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *can, uint32_t fifo, FDCAN_RxHeaderTypeDef *header, uint8_t *data) { (void)can; (void)fifo; header->Identifier = rx_header.ExtId; header->IdType = rx_header.IDE; header->RxFrameType = rx_header.RTR; header->DataLength = rx_header.DLC << 16U; header->FDFormat = FDCAN_CLASSIC_CAN; (void)memcpy(data, rx_bytes, 8U); have_rx = false; return HAL_OK; } /* Проверяет decoder старого shifted-DLC HAL на тех же ошибочных входах, что bxCAN. */ +#endif /* Завершает аппаратную модель только для G474. */ +uint32_t HAL_GetTick(void) { return tick++; } /* Продвигает время даже в синхронном ожидании TX для воспроизводимого тайм-аута. */ +uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *can) { (void)can; return no_mailbox ? 0U : 3U; } /* Имитирует свободный либо постоянно занятый TX. */ +HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *can, CAN_TxHeaderTypeDef *header, uint8_t *data, uint32_t *mailbox) /* Захватывает ответ и состояние завершения его передачи. */ +{ /* Реальный codec и сборка payload остаются в production-коде. */ + assert(can->Instance == CAN1 && header->IDE == CAN_ID_EXT && header->RTR == CAN_RTR_DATA && header->DLC <= 8U); /* Проверяет аппаратный формат каждого ответа. */ + assert(can->Instance->TSR == (CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2)); /* До передачи порт обязан очистить старые TXOK/ошибки аппаратной записью W1C. */ + (void)memcpy(last_tx, data, sizeof(last_tx)); /* Восемь доступных байтов гарантирует локальный TX-буфер порта. */ + *mailbox = CAN_TX_MAILBOX0; /* Выбирает первый mailbox с известным TXOK-флагом. */ + can->Instance->TSR = tx_error ? 0U : CAN_TSR_TXOK0; /* Различает успешную передачу и снятый без ACK запрос. */ + ++sends; /* Фиксирует факт постановки кадра в передатчик. */ + return HAL_OK; /* Модель успешно приняла параметры аппаратной передачи. */ +} /* Завершает модель отправки кадра. */ +uint32_t HAL_CAN_IsTxMessagePending(CAN_HandleTypeDef *can, uint32_t mailbox) { (void)can; (void)mailbox; return pending; } /* Удерживает TX незавершённым для проверки запрета reset. */ +HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *can, uint32_t mailbox) { (void)can; (void)mailbox; ++aborted; return HAL_OK; } /* Считает отменённые после тайм-аута запросы. */ +HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *can, CAN_FilterTypeDef *filter) { (void)can; assert(filter->FilterBank < 2U); filters[filter->FilterBank] = *filter; return HAL_OK; } /* Проверяет владение только двумя заявленными банками. */ +HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *can) { (void)can; return fail_start ? HAL_ERROR : HAL_OK; } /* Даёт воспроизводимый отказ аппаратного запуска. */ +uint32_t HAL_CAN_GetRxFifoFillLevel(CAN_HandleTypeDef *can, uint32_t fifo) { (void)can; assert(fifo == CAN_RX_FIFO0); return have_rx; } /* Сообщает наличие подготовленного кадра. */ +HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *can, uint32_t fifo, CAN_RxHeaderTypeDef *header, uint8_t *data) { (void)can; (void)fifo; *header = rx_header; (void)memcpy(data, rx_bytes, 8U); have_rx = false; return HAL_OK; } /* Передаёт кадр через настоящий путь RX порта. */ +HAL_StatusTypeDef HAL_FLASH_Unlock(void) { unlocked = true; return HAL_OK; } /* Разрешает последующие модельные erase и program. */ +HAL_StatusTypeDef HAL_FLASH_Lock(void) { unlocked = false; return HAL_OK; } /* Восстанавливает аппаратную блокировку модели. */ +HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *erase, uint32_t *error) /* Моделирует геометрию стирания без изменения самого алгоритма порта. */ +{ /* Любое пересечение загрузчика либо резервной памяти немедленно проваливает тест. */ + uint32_t start, end; /* Вычисляет физический диапазон выбранной операции HAL. */ + assert(unlocked); /* Запрещает erase до аппаратной разблокировки. */ +#if defined(TEST_STM32F103) /* Проверяет 1-КиБ страницы среднего семейства F103. */ + assert(erase->TypeErase == FLASH_TYPEERASE_PAGES && erase->NbPages != 0U); /* Исключает подмену на mass erase. */ + start = erase->PageAddress; end = start + erase->NbPages * 1024U; /* Воспроизводит диапазон HAL page erase в байтах. */ +#elif defined(TEST_STM32G474) /* Проверяет физические страницы обоих банков G474. */ + uint32_t page_size = dual_bank ? 2048U : 4096U, bank_size = dual_bank ? 262144U : 524288U; /* Независимая геометрия по выбранному DBANK-режиму. */ + assert(erase->TypeErase == FLASH_TYPEERASE_PAGES && erase->NbPages == 1U && erase->Banks >= FLASH_BANK_1 && erase->Banks <= (dual_bank ? FLASH_BANK_2 : FLASH_BANK_1)); /* Не допускает второго физического банка в single-bank конфигурации. */ + start = FLASH_BASE + (erase->Banks == FLASH_BANK_2 ? bank_size : 0U) + erase->Page * page_size; end = start + page_size; /* Независимо восстанавливает физический диапазон erase из номера банка и страницы. */ +#else /* Проверяет конкретные секторы STM32F407. */ + static const uint32_t bounds[] = {0x08008000UL, 0x0800C000UL, 0x08010000UL, 0x08020000UL, 0x08040000UL}; /* Независимая карта физических границ секторов 2..5 из исходного climate. */ + assert(erase->TypeErase == FLASH_TYPEERASE_SECTORS && erase->Sector >= 2U && erase->Sector <= 5U && erase->NbSectors == 1U && erase->VoltageRange == FLASH_VOLTAGE_RANGE_3); /* Исключает загрузчик, EEPROM-кольцо и неверную разрядность Flash. */ + start = bounds[erase->Sector - 2U]; end = bounds[erase->Sector - 1U]; /* Определяет полный стираемый сектор по его физическому номеру. */ +#endif /* Завершает проверку геометрии семейства. */ + assert(start >= APP_BASE && end <= APP_END); /* Проверяет границы до обращения к host-памяти. */ + *error = 0U; ++erases; tick += 2000U; /* Воспроизводит длительный erase, превышающий короткий тайм-аут сессии. */ + if (fail_erase) return HAL_ERROR; /* Модель аппаратного отказа не должна оставить Flash разблокированной. */ + (void)memset((void *)(uintptr_t)start, 0xFF, end - start); /* Стирает только разрешённые реальные байты модели. */ + return HAL_OK; /* Выбранные страницы или сектор успешно очищены. */ +} /* Завершает независимую модель аппаратного erase. */ +HAL_StatusTypeDef HAL_FLASH_Program(uint32_t type, uint32_t address, uint64_t value) /* Программирует только выровненную аппаратную единицу. */ +{ /* Чтение результата выполняется настоящим production-кодом через тот же адрес. */ + uint32_t size = type == FLASH_TYPEPROGRAM_HALFWORD ? 2U : 4U; /* Различает аппаратные единицы F103 и F407. */ +#if defined(TEST_STM32G474) /* G474 программируется аппаратными doubleword, а не словами F4. */ + assert(type == FLASH_TYPEPROGRAM_DOUBLEWORD); size = 8U; /* Исключает неверную разрядность записи ECC Flash G474. */ +#endif /* Завершает выбор аппаратной единицы модели программирования. */ + assert(unlocked && address >= APP_BASE && address <= APP_END - size && address % size == 0U); /* Не допускает пересечения Flash-профиля или неверного выравнивания. */ + assert(!cache_dirty); /* Следующая запись не должна скрыть пропущенную синхронизацию предыдущего Flash readback. */ + ++writes; /* Считает обращения к реальному программированию HAL. */ + if (fail_write) return HAL_ERROR; /* Имитирует отказ до изменения данных. */ + (void)memcpy((void *)(uintptr_t)address, &value, size); /* Сохраняет именно аппаратно записанное полуслово либо слово. */ +#if !defined(TEST_STM32F103) && !defined(TEST_STM32G474) /* Только F407 требует явного flush от вызывающего порта; HAL G4 выполняет его внутри Program. */ + cache_dirty = true; /* Следующий readback требует семейного вызова FLASH_FlushCaches. */ +#endif /* Завершает моделирование необходимости синхронизации F407. */ + if (corrupt_write) *(uint8_t *)(uintptr_t)address ^= 1U; /* Вызывает readback-ошибку при формальном успехе HAL. */ + return HAL_OK; /* Даёт production-коду независимо перечитать память. */ +} /* Завершает модель программирования Flash. */ +void FLASH_FlushCaches(void) { cache_dirty = false; } /* Обновляет модель видимости записанных слов F407 перед последующим readback. */ +void NVIC_SystemReset(void) { ++resets; } /* Считает reset только после успешного ACK команды REBOOT. */ +static void put32(uint8_t *out, uint32_t value) /* Сериализует поля образа независимо от host-endian. */ +{ /* ProtoCAN manifest и Cortex-M векторы используют младший байт первым. */ + out[0] = (uint8_t)value; out[1] = (uint8_t)(value >> 8U); out[2] = (uint8_t)(value >> 16U); out[3] = (uint8_t)(value >> 24U); /* Записывает четыре октета little-endian без невыровненного доступа. */ +} /* Завершает тестовую сериализацию 32-битного поля. */ +static bool command(pcan_boot_stm32_t *port, uint8_t cmd, const uint8_t *data, uint8_t dlc) /* Отправляет адресную команду в настоящую state machine. */ +{ /* Сессия 9 и адрес 3:5 являются тестовыми значениями и не задают адрес рабочего устройства. */ + return pcan_boot_process(&port->boot, pcan_boot_make_id(1U, 0U, 3U, 5U, PCAN_BOOT_MSG_CONTROL, (uint16_t)(0x0900U | cmd)), data, dlc); /* Формирует SessionID в старшем октете Body и команду в младшем. */ +} /* Завершает подачу адресной команды. */ +static void setup(pcan_boot_stm32_t *port, TEST_HANDLE *can) /* Подготавливает независимое начальное состояние перед каждым сценарием. */ +{ /* Память вне приложения заполнена сторожевым значением для обнаружения повреждений. */ + pcan_boot_config_t config = {0}; /* Исключает влияние полей новых версий общего API. */ + tick = sends = resets = aborted = erases = writes = 0U; /* Сбрасывает наблюдаемые эффекты предыдущего сценария. */ + unlocked = fail_erase = fail_write = corrupt_write = no_mailbox = pending = tx_error = fail_start = have_rx = false; /* Возвращает все аппаратные отказы в исходное состояние. */ + cache_dirty = false; /* Новая сессия начинается без устаревшего cache-состояния предыдущей проверки. */ + (void)memset(flash, 0xA5, 0x81000U); /* Сторожевое заполнение покрывает все 512 КиБ Flash и сторожевую страницу после физического конца. */ + config.device_type = 3U; config.device_id = 5U; config.ack_window = 1U; config.session_timeout_ms = 1000U; /* Выбирает адрес и сессию короче модельного стирания. */ +#if defined(TEST_STM32G474) /* Подготавливает независимую физическую геометрию G474 для каждого сценария. */ + stm32_test_flash.OPTR = dual_bank ? FLASH_OPTR_DBANK : 0U; stm32_test_syscfg.MEMRMP = 0U; stm32_test_flash_kib = 512U; can->Init.ExtFiltersNbr = 2U; /* Сохраняет выбранный DBANK и выделяет два аппаратных extended-фильтра. */ +#endif /* Завершает подготовку FDCAN/Flash G474. */ + assert(PORT_INIT(port, can, &config)); /* Проверяет настоящую настройку single-slot, callbacks и двух фильтров. */ + assert(port->boot.config.slot_count == 1U && port->boot.config.active_slot == 0U && port->boot.config.max_image_size == APP_END - APP_BASE); /* Исключает возврат старой фиктивной A/B-конфигурации. */ +} /* Завершает подготовку сценария. */ +static void begin(pcan_boot_stm32_t *port, const uint8_t *image, uint32_t size) /* Открывает полную сессию с двумя частями manifest и стиранием. */ +{ /* Все ограничения проверяет общий production-автомат. */ + uint8_t metadata[8] = {0}; /* Product/HW/FW тестового устройства равны нулю. */ + assert(command(port, PCAN_BOOT_CMD_ENTER_BOOT, NULL, 0U)); /* Открывает адресную сессию 9. */ + put32(metadata, size); put32(metadata + 4U, pcan_boot_crc32_update(0U, image, size)); /* Передаёт полезную длину и ожидаемый CRC без хвоста FF. */ + assert(command(port, PCAN_BOOT_CMD_BEGIN_IMAGE, metadata, 8U)); /* Передаёт первую часть manifest. */ + (void)memset(metadata, 0, sizeof(metadata)); /* Очищает поля для части совместимости. */ + assert(command(port, PCAN_BOOT_CMD_BEGIN_COMPAT, metadata, 8U)); /* Передаёт совпадающий Product и диапазон HW. */ + assert(command(port, PCAN_BOOT_CMD_ERASE, NULL, 0U)); /* Вызывает настоящую семейную процедуру стирания. */ + assert(port->boot.state == PCAN_BOOT_STATE_RECEIVING && !unlocked); /* Стирание завершилось и Flash снова защищена. */ + PORT_POLL(port); /* Проверяет, что двухсекундный erase не погасил секундную сессию. */ + assert(port->boot.state == PCAN_BOOT_STATE_RECEIVING); /* Финальное обновление BUSY обязано продлить сессию после Flash stall. */ +} /* Завершает подготовку к передаче блоков образа. */ +static void upload(pcan_boot_stm32_t *port, const uint8_t *image, uint32_t size) /* Передаёт образ через общий decoder восьмибайтовых CAN-блоков. */ +{ /* Последний блок всегда имеет DLC=8, а аппаратный порт получает только полезный остаток. */ + uint32_t offset; /* Считает смещение полезных данных в байтах. */ + for (offset = 0U; offset < size; offset += 8U) { /* Повторяет реальное блочное поведение ProtoCAN Boot. */ + uint8_t block[8]; uint32_t count = size - offset; /* Выделяет полный payload и вычисляет фактический остаток. */ + if (count > 8U) count = 8U; /* Не читает за границей переданного тестового образа. */ + (void)memset(block, 0xFF, 8U); (void)memcpy(block, image + offset, count); /* Формирует wire-дополнение последнего кадра FF. */ + assert(pcan_boot_process(&port->boot, pcan_boot_make_id(1U, 0U, 3U, 5U, PCAN_BOOT_MSG_DATA_A, (uint16_t)(offset / 8U)), block, 8U)); /* Вызывает production-запись выбранного логического слота A. */ + assert(port->boot.state == PCAN_BOOT_STATE_RECEIVING && !unlocked && !cache_dirty); /* Каждый подтверждённый блок обязан оставить Flash защищённой и кэш синхронизированным. */ + } /* Завершает передачу образа. */ +} /* Завершает helper загрузки без обхода протокольной state machine. */ +static void test_update_and_tails(TEST_HANDLE *can) /* Проверяет все возможные остатки аппаратных полуслов/слов и полный COMMIT/REBOOT. */ +{ /* Размеры 16..23 покрывают все восемь вариантов последнего CAN-блока. */ + uint32_t size; /* Перебирает длины полезного образа в байтах. */ + for (size = 16U; size < 24U; ++size) { /* В каждом случае создаёт отдельную сессию обновления. */ + pcan_boot_stm32_t port; uint8_t image[24] = {0}; /* Изолирует состояние и небольшой образ с корректными векторами. */ + setup(&port, can); put32(image, RAM_TOP); put32(image + 4U, APP_BASE + 9U); /* Reset handler указывает внутрь образа, MSP лежит на верхней границе SRAM. */ + begin(&port, image, size); upload(&port, image, size); /* Выполняет реальную последовательность erase и DATA. */ + assert(memcmp((const void *)(uintptr_t)APP_BASE, image, size) == 0 && PORT_VECTORS()); /* Проверяет фактические байты Flash и векторы после программирования. */ + assert(*(uint8_t *)(uintptr_t)(APP_BASE + size) == 0xFFU); /* За полезной длиной остаётся FF, включая дополнение последней аппаратной единицы записи. */ + assert(*(uint8_t *)(uintptr_t)(APP_BASE - 1U) == 0xA5U && *(uint8_t *)(uintptr_t)APP_END == 0xA5U); /* Доказывает сохранность загрузчика и памяти сразу за приложением. */ + assert(command(&port, PCAN_BOOT_CMD_REBOOT, NULL, 0U) && resets == 0U); /* Запрещает reset до VERIFY и COMMIT даже при корректных векторах. */ + assert(command(&port, PCAN_BOOT_CMD_VERIFY, NULL, 0U) && port.boot.state == PCAN_BOOT_STATE_VERIFIED); /* Проверяет CRC именно прочитанной Flash. */ + assert(command(&port, PCAN_BOOT_CMD_COMMIT, NULL, 0U) && port.ready); /* Разрешает активацию проверенного образа. */ + pending = true; assert(!command(&port, PCAN_BOOT_CMD_REBOOT, NULL, 0U) && resets == 0U && aborted == 1U); /* Незавершённый TX ответа не должен вызвать reset. */ + pending = false; tx_error = true; assert(!command(&port, PCAN_BOOT_CMD_REBOOT, NULL, 0U) && resets == 0U); /* Снятый с ошибкой mailbox также не подтверждает отправку ACK. */ + tx_error = false; assert(command(&port, PCAN_BOOT_CMD_REBOOT, NULL, 0U) && resets == 1U); /* Подтверждённый TX допускает ровно один CMSIS reset. */ + } /* Завершает перебор всех хвостов последнего CAN-блока. */ +} /* Завершает основной end-to-end сценарий обновления. */ +static void test_failures_and_transport(TEST_HANDLE *can) /* Проверяет повреждения Flash, пограничные входы и фильтрацию внешних кадров. */ +{ /* Набор ошибок использует те же production-callbacks, что MCU. */ + pcan_boot_stm32_t port; uint8_t image[16] = {0}, one = 0x5AU; uint32_t before; /* Подготавливает минимальный образ и однобайтовый служебный payload. */ + setup(&port, can); put32(image, RAM_TOP); put32(image + 4U, APP_BASE + 9U); begin(&port, image, 16U); upload(&port, image, 16U); /* Записывает корректный образ для независимой проверки повреждения. */ + *(uint8_t *)(uintptr_t)(APP_BASE + 12U) ^= 1U; /* Имитирует повреждение Flash после успешного получения потока. */ + assert(command(&port, PCAN_BOOT_CMD_VERIFY, NULL, 0U) && port.boot.last_status == PCAN_BOOT_STATUS_CRC_ERROR && !port.ready); /* CRC потока остаётся верным, но readback обязан выявить ошибку. */ + setup(&port, can); put32(image + 4U, APP_BASE + 33U); begin(&port, image, 16U); upload(&port, image, 16U); /* Создаёт корректный CRC, но reset handler находится за фактическим образом. */ + assert(PORT_VECTORS() && command(&port, PCAN_BOOT_CMD_VERIFY, NULL, 0U) && port.boot.last_status == PCAN_BOOT_STATUS_INVALID_SIZE); /* Проверка диапазона профиля не заменяет проверку точной длины manifest. */ + put32((uint8_t *)(uintptr_t)APP_BASE, RAM_TOP - 1U); assert(!PORT_VECTORS()); /* Отвергает невыровненный начальный стек внутри допустимой SRAM. */ + put32((uint8_t *)(uintptr_t)APP_BASE, 0x20000000UL); assert(!PORT_VECTORS()); /* Нижняя граница SRAM не оставляет пространства для растущего вниз стека. */ + put32(image + 4U, APP_BASE + 9U); /* Восстанавливает корректную точку входа для следующих независимых проверок. */ + setup(&port, can); begin(&port, image, 16U); corrupt_write = true; /* Имитирует формальный успех HAL при неверном аппаратном readback. */ + assert(!port.boot.port.write_slot(&port, 0U, 0U, image, 8U) && !unlocked && port.written == 0U); /* Не подтверждает ни байта повреждённой записи и блокирует Flash. */ + corrupt_write = false; fail_write = true; assert(!port.boot.port.write_slot(&port, 0U, 0U, image, 8U) && !unlocked); /* При аппаратном отказе записи защита также восстанавливается. */ + fail_write = false; before = writes; /* Начинает проверку входов, которые не должны дойти до HAL. */ + assert(!port.boot.port.write_slot(&port, 1U, 0U, image, 8U) && !port.boot.port.write_slot(&port, 0U, 1U, image, 8U) && !port.boot.port.write_slot(&port, 0U, UINT32_MAX, image, 8U)); /* Отвергает чужой слот, невыровненный адрес и переполнение. */ + assert(!port.boot.port.write_slot(&port, 0U, 0U, image, 3U) && writes == before); /* Не программирует неполное аппаратное слово в середине образа. */ + assert(port.boot.port.send(&port, 1U, &one, 1U) && last_tx[0] == one && last_tx[1] == 0U && last_tx[7] == 0U); /* Короткий payload не читает семь отсутствующих октетов. */ + no_mailbox = true; assert(!port.boot.port.send(&port, 1U, &one, 1U)); no_mailbox = false; /* Ожидание свободного TX ограничено тайм-аутом. */ + fail_erase = true; assert(!port.boot.port.erase_slot(&port, 0U) && !unlocked); fail_erase = false; /* Отказ erase оставляет Flash заблокированной. */ + port.boot.manifest.image_size = APP_END - APP_BASE + 1U; before = erases; assert(!port.boot.port.erase_slot(&port, 0U) && erases == before); /* Превышение области не вызывает ни одной аппаратной операции. */ + setup(&port, can); before = sends; (void)memset(&rx_header, 0, sizeof(rx_header)); rx_header.ExtId = pcan_boot_make_id(1U, 0U, 3U, 5U, PCAN_BOOT_MSG_CONTROL, PCAN_BOOT_CMD_IDENTIFY); /* Готовит валидный адрес при неверном IDE. */ + have_rx = true; PORT_POLL(&port); assert(sends == before); /* Отвергает стандартный CAN-кадр до общего decoder. */ + rx_header.IDE = CAN_ID_EXT; rx_header.RTR = 2U; have_rx = true; PORT_POLL(&port); assert(sends == before); /* Отвергает remote-запрос вместо data-кадра. */ + rx_header.RTR = CAN_RTR_DATA; rx_header.DLC = 9U; have_rx = true; PORT_POLL(&port); assert(sends == before); /* Отвергает DLC больше ёмкости classic CAN. */ + rx_header.DLC = 0U; have_rx = true; PORT_POLL(&port); assert(sends == before + 1U); /* Валидный IDENTIFY проходит через настоящий FIFO adapter. */ + rx_header.ExtId = pcan_boot_make_id(1U, 0U, 7U, 15U, PCAN_BOOT_MSG_DISCOVERY, 0U); have_rx = true; PORT_POLL(&port); tick += 300U; PORT_POLL(&port); assert(sends == before + 2U); /* Broadcast discovery выдаёт отложенный адресный ответ без открытия сессии. */ + assert((filters[0].FilterMaskIdHigh & 0x8000U) == 0U && filters[1].FilterBank == 1U); /* Оба приоритета разрешены, discovery занимает отдельный банк. */ + fail_start = true; assert(!PORT_INIT(&port, can, &port.boot.config)); PORT_POLL(&port); assert(port.can == NULL); /* Отказ инициализации делает последующий poll безопасным. */ +} /* Завершает проверки отказов и транспортных границ. */ +static void test_full_capacity(TEST_HANDLE *can) /* Проверяет округление последней страницы/сектора и запись последнего аппаратного слова. */ +{ /* Полная ёмкость профиля затрагивает все разрешённые сектора, но не следующий. */ + pcan_boot_stm32_t port; uint8_t bytes[8] = {0}; uint32_t size = APP_END - APP_BASE; /* Готовит граничные значения в байтах. */ + setup(&port, can); port.boot.manifest.image_size = size; /* Задаёт максимальную длину без выделения большого wire-образа. */ + assert(port.boot.port.erase_slot(&port, 0U) && !unlocked); /* Стирает все разрешённые страницы или секторы production-алгоритмом. */ + port.written = size - 8U; assert(port.boot.port.write_slot(&port, 0U, size - 8U, bytes, 8U)); /* Проверяет последний допустимый блок точно на верхней границе. */ + assert(*(uint8_t *)(uintptr_t)(APP_BASE - 1U) == 0xA5U && *(uint8_t *)(uintptr_t)APP_END == 0xA5U); /* Не допускает стирания либо программирования соседних защищённых областей. */ +} /* Завершает проверку полного физического диапазона. */ +int main(void) /* Запускает регрессии production-порта в изолированном процессе. */ +{ /* Каждый процесс получает собственное отображение MCU Flash без доступа к устройству. */ + TEST_HANDLE can = {0}; can.Instance = TEST_INSTANCE; /* Подготавливает заранее настроенный HAL handle выделенного CAN1/FDCAN1. */ +#if defined(_WIN32) /* Выделяет фиксированный диапазон виртуальных адресов на Windows. */ + flash = VirtualAlloc((void *)(uintptr_t)0x08000000UL, 0x81000U, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); /* Моделирует 512 КиБ Flash STM32 и одну сторожевую страницу, включая сторожевые области. */ + assert(flash == (void *)(uintptr_t)0x08000000UL); /* Не выполняет тест, если адрес MCU недоступен в host-процессе. */ +#else /* Создаёт эквивалентное анонимное отображение на POSIX. */ + flash = mmap((void *)(uintptr_t)0x08000000UL, 0x81000U, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); /* Использует адрес как подсказку, не заменяя существующие отображения host-процесса. */ + assert(flash == (void *)(uintptr_t)0x08000000UL); /* Не продолжает проверки, если адрес MCU занят или mmap завершился ошибкой. */ +#endif /* Завершает выделение памяти модели. */ +#if defined(TEST_STM32G474) /* Прогоняет общие сценарии в обоих исходных DBANK-режимах G474VE. */ + for (unsigned mode = 0U; mode < 2U; ++mode) { /* Каждый режим независимо проверяет весь 480-КиБ слот и переход между физическими банками. */ + pcan_boot_stm32_t port; uint32_t before; dual_bank = mode != 0U; /* Выбирает single-bank 4 КиБ либо dual-bank 2 КиБ страницы. */ + test_update_and_tails(&can); test_failures_and_transport(&can); test_full_capacity(&can); /* Прогоняет полный flow, аппаратные ошибки, TX/RX и верхнюю границу Flash. */ + setup(&port, &can); port.boot.manifest.image_size = 16U; before = erases; stm32_test_flash.OPTR |= FLASH_OPTR_BFB2; /* Подготавливает опасную перестановку boot-банков. */ + assert(!port.boot.port.erase_slot(&port, 0U) && erases == before); stm32_test_flash.OPTR &= ~FLASH_OPTR_BFB2; /* Запрещённый BFB2 отвергается до HAL erase. */ + stm32_test_syscfg.MEMRMP = SYSCFG_MEMRMP_FB_MODE; assert(!port.boot.port.erase_slot(&port, 0U) && erases == before); stm32_test_syscfg.MEMRMP = 0U; /* Программная перестановка банков также не должна изменить Flash. */ + stm32_test_flash_kib = 256U; assert(!port.boot.port.erase_slot(&port, 0U) && erases == before); /* Профиль VE не должен стирать неизвестную меньшую физическую ёмкость. */ + } /* Завершает независимую проверку обеих аппаратных геометрий. */ +#else /* bxCAN-порты используют одну фиксированную аппаратную геометрию каждый. */ + test_update_and_tails(&can); test_failures_and_transport(&can); test_full_capacity(&can); /* Проверяет нормальный flow, аппаратные отказы и обе границы памяти. */ +#endif /* Завершает семейный набор host-сценариев. */ +#if defined(_WIN32) /* Освобождает всю зарезервированную область Windows. */ + assert(VirtualFree(flash, 0U, MEM_RELEASE)); /* Не оставляет виртуальную память после успешного теста. */ +#else /* Освобождает POSIX-отображение. */ + assert(munmap(flash, 0x81000U) == 0); /* Снимает модель Flash целиком. */ +#endif /* Завершает освобождение host-ресурсов. */ + puts("STM32 ProtoCAN port: OK"); return 0; /* Сообщает успешное завершение семейного прогона без аппаратных заявлений. */ +} /* Завершает host-регрессию реального MCU-порта. */ diff --git a/c/protocan-boot/vendor/ti/README.md b/c/protocan-boot/vendor/ti/README.md new file mode 100644 index 0000000..d16ec89 --- /dev/null +++ b/c/protocan-boot/vendor/ti/README.md @@ -0,0 +1,20 @@ +# Поддержка TI C2000 для самостоятельных проектов + +Здесь сохранён минимальный необходимый набор device headers, peripheral linker, +GlobalVariableDefs, SysCtrl, CpuTimers, PieCtrl и usDelay. Для F28335 также +подключён ADC_cal. Полные исходные copyright/version comments TI сохранены. + +- `f28335`: DSP2833x Header Files/Common Sources **v1.20**, вариант рабочей + платы 167 из `Source/External/v120`. В нём сохранены русские пояснения и + действующие XCLKIN=30 МГц, CLKMULT=2, SYSCLKOUT=60 МГц. +- `f2812`: DSP281x Header Files/Common Sources **v1.20**, вариант рабочей + платы ПМ67 из `22220/ural/TMS_new_bus/Src/v120`. Используется штатный + PLLCR=10 при XCLKIN=30 МГц, SYSCLKOUT=150 МГц. Сохранено исходное имя + регистра `PIECRTL` SDK и секция `.fast_run` у usDelay; linker проекта + размещает её во внутренней Flash для вызовов из раннего InitSysCtrl. + +Это существующая поддержка производителя; код аппаратных портов ProtoCAN +находится отдельно в `ports`, а настройки платы — в проектах CCS. Перенос +исходников TI устраняет зависимость от соседнего checkout конкретной прошивки. +Установленный TI compiler/runtime по-прежнему требуется; `libc`/RTS не +копируются в репозиторий. diff --git a/c/protocan-boot/vendor/ti/f2812/cmd/DSP281x_Headers_nonBIOS.cmd b/c/protocan-boot/vendor/ti/f2812/cmd/DSP281x_Headers_nonBIOS.cmd new file mode 100644 index 0000000..0b9ae9c --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/cmd/DSP281x_Headers_nonBIOS.cmd @@ -0,0 +1,102 @@ +/* +// TI File $Revision: /main/4 $ +// Checkin $Date: July 9, 2009 17:39:29 $ +//########################################################################### +// +// FILE: DSP281x_Headers_nonBIOS.cmd +// +// TITLE: DSP281x Peripheral registers linker command file +// +// DESCRIPTION: +// +// This file is for use in Non-BIOS applications. +// +// Linker command file to place the peripheral structures +// used within the DSP28 headerfiles into the correct memory +// mapped locations. +// +// This version of the file includes the PieVectorTable structure. +// For BIOS applications, please use the DSP281x_Headers_BIOS.cmd file +// which does not include the PieVectorTable structure. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### +*/ + +MEMORY +{ + PAGE 0: /* Program Memory */ + + PAGE 1: /* Data Memory */ + + DEV_EMU : origin = 0x000880, length = 0x000180 /* device emulation registers */ + PIE_VECT : origin = 0x000D00, length = 0x000100 /* PIE Vector Table */ + FLASH_REGS : origin = 0x000A80, length = 0x000060 /* FLASH registers */ + CSM : origin = 0x000AE0, length = 0x000010 /* code security module registers */ + XINTF : origin = 0x000B20, length = 0x000020 /* external interface registers */ + CPU_TIMER0 : origin = 0x000C00, length = 0x000008 /* CPU Timer0 registers */ + CPU_TIMER1 : origin = 0x000C08, length = 0x000008 /* CPU Timer1 registers */ + CPU_TIMER2 : origin = 0x000C10, length = 0x000008 /* CPU Timer2 registers */ + PIE_CTRL : origin = 0x000CE0, length = 0x000020 /* PIE control registers */ + ECANA : origin = 0x006000, length = 0x000040 /* eCAN control and status registers */ + ECANA_LAM : origin = 0x006040, length = 0x000040 /* eCAN local acceptance masks */ + ECANA_MOTS : origin = 0x006080, length = 0x000040 /* eCAN message object time stamps */ + ECANA_MOTO : origin = 0x0060C0, length = 0x000040 /* eCAN object time-out registers */ + ECANA_MBOX : origin = 0x006100, length = 0x000100 /* eCAN mailboxes */ + SYSTEM : origin = 0x007010, length = 0x000020 /* System control registers */ + SPIA : origin = 0x007040, length = 0x000010 /* SPI registers */ + SCIA : origin = 0x007050, length = 0x000010 /* SCI-A registers */ + XINTRUPT : origin = 0x007070, length = 0x000010 /* external interrupt registers */ + GPIOMUX : origin = 0x0070C0, length = 0x000020 /* GPIO mux registers */ + GPIODAT : origin = 0x0070E0, length = 0x000020 /* GPIO data registers */ + ADC : origin = 0x007100, length = 0x000020 /* ADC registers */ + EVA : origin = 0x007400, length = 0x000040 /* Event Manager A registers */ + EVB : origin = 0x007500, length = 0x000040 /* Event Manager B registers */ + SCIB : origin = 0x007750, length = 0x000010 /* SCI-B registers */ + MCBSPA : origin = 0x007800, length = 0x000040 /* McBSP registers */ + CSM_PWL : origin = 0x3F7FF8, length = 0x000008 /* Part of FLASHA. CSM password locations. */ +} + + +SECTIONS +{ + PieVectTableFile : > PIE_VECT, PAGE = 1 + +/*** Peripheral Frame 0 Register Structures ***/ + DevEmuRegsFile : > DEV_EMU, PAGE = 1 + FlashRegsFile : > FLASH_REGS, PAGE = 1 + CsmRegsFile : > CSM, PAGE = 1 + XintfRegsFile : > XINTF, PAGE = 1 + CpuTimer0RegsFile : > CPU_TIMER0, PAGE = 1 + CpuTimer1RegsFile : > CPU_TIMER1, PAGE = 1 + CpuTimer2RegsFile : > CPU_TIMER2, PAGE = 1 + PieCtrlRegsFile : > PIE_CTRL, PAGE = 1 + +/*** Peripheral Frame 1 Register Structures ***/ + ECanaRegsFile : > ECANA, PAGE = 1 + ECanaLAMRegsFile : > ECANA_LAM PAGE = 1 + ECanaMboxesFile : > ECANA_MBOX PAGE = 1 + ECanaMOTSRegsFile : > ECANA_MOTS PAGE = 1 + ECanaMOTORegsFile : > ECANA_MOTO PAGE = 1 + +/*** Peripheral Frame 2 Register Structures ***/ + SysCtrlRegsFile : > SYSTEM, PAGE = 1 + SpiaRegsFile : > SPIA, PAGE = 1 + SciaRegsFile : > SCIA, PAGE = 1 + XIntruptRegsFile : > XINTRUPT, PAGE = 1 + GpioMuxRegsFile : > GPIOMUX, PAGE = 1 + GpioDataRegsFile : > GPIODAT PAGE = 1 + AdcRegsFile : > ADC, PAGE = 1 + EvaRegsFile : > EVA, PAGE = 1 + EvbRegsFile : > EVB, PAGE = 1 + ScibRegsFile : > SCIB, PAGE = 1 + McbspaRegsFile : > MCBSPA, PAGE = 1 + +/*** Code Security Module Register Structures ***/ + CsmPwlFile : > CSM_PWL, PAGE = 1 +} + + +/******************* end of file ************************/ diff --git a/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_DefaultIsr.h b/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_DefaultIsr.h new file mode 100644 index 0000000..e617abd --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_DefaultIsr.h @@ -0,0 +1,123 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 28, 2005 15:22:28 $ +//########################################################################### +// +// FILE: DSP281x_DefaultIsr.h +// +// TITLE: DSP281x Devices Default Interrupt Service Routines Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_DEFAULT_ISR_H +#define DSP281x_DEFAULT_ISR_H + +#ifdef __cplusplus +extern "C" { +#endif + + +//--------------------------------------------------------------------------- +// Default Interrupt Service Routine Declarations: +// +// The following function prototypes are for the +// default ISR routines used with the default PIE vector table. +// This default vector table is found in the DSP28_PieVect.h +// file. +// + +// Non-Peripheral Interrupts: +interrupt void INT13_ISR(void); // XINT13 or CPU-Timer 1 +interrupt void INT14_ISR(void); // CPU-Timer2 +interrupt void DATALOG_ISR(void); // Datalogging interrupt +interrupt void RTOSINT_ISR(void); // RTOS interrupt +interrupt void EMUINT_ISR(void); // Emulation interrupt +interrupt void NMI_ISR(void); // Non-maskable interrupt +interrupt void ILLEGAL_ISR(void); // Illegal operation TRAP +interrupt void USER1_ISR(void); // User Defined trap 1 +interrupt void USER2_ISR(void); // User Defined trap 2 +interrupt void USER3_ISR(void); // User Defined trap 3 +interrupt void USER4_ISR(void); // User Defined trap 4 +interrupt void USER5_ISR(void); // User Defined trap 5 +interrupt void USER6_ISR(void); // User Defined trap 6 +interrupt void USER7_ISR(void); // User Defined trap 7 +interrupt void USER8_ISR(void); // User Defined trap 8 +interrupt void USER9_ISR(void); // User Defined trap 9 +interrupt void USER10_ISR(void); // User Defined trap 10 +interrupt void USER11_ISR(void); // User Defined trap 11 +interrupt void USER12_ISR(void); // User Defined trap 12 + +// Group 1 PIE Interrupt Service Routines: +interrupt void PDPINTA_ISR(void); // EV-A +interrupt void PDPINTB_ISR(void); // EV-B +interrupt void XINT1_ISR(void); +interrupt void XINT2_ISR(void); +interrupt void ADCINT_ISR(void); // ADC +interrupt void TINT0_ISR(void); // Timer 0 +interrupt void WAKEINT_ISR(void); // WD + +// Group 2 PIE Interrupt Service Routines: +interrupt void CMP1INT_ISR(void); // EV-A +interrupt void CMP2INT_ISR(void); // EV-A +interrupt void CMP3INT_ISR(void); // EV-A +interrupt void T1PINT_ISR(void); // EV-A +interrupt void T1CINT_ISR(void); // EV-A +interrupt void T1UFINT_ISR(void); // EV-A +interrupt void T1OFINT_ISR(void); // EV-A + +// Group 3 PIE Interrupt Service Routines: +interrupt void T2PINT_ISR(void); // EV-A +interrupt void T2CINT_ISR(void); // EV-A +interrupt void T2UFINT_ISR(void); // EV-A +interrupt void T2OFINT_ISR(void); // EV-A +interrupt void CAPINT1_ISR(void); // EV-A +interrupt void CAPINT2_ISR(void); // EV-A +interrupt void CAPINT3_ISR(void); // EV-A + +// Group 4 PIE Interrupt Service Routines: +interrupt void CMP4INT_ISR(void); // EV-B +interrupt void CMP5INT_ISR(void); // EV-B +interrupt void CMP6INT_ISR(void); // EV-B +interrupt void T3PINT_ISR(void); // EV-B +interrupt void T3CINT_ISR(void); // EV-B +interrupt void T3UFINT_ISR(void); // EV-B +interrupt void T3OFINT_ISR(void); // EV-B + +// Group 5 PIE Interrupt Service Routines: +interrupt void T4PINT_ISR(void); // EV-B +interrupt void T4CINT_ISR(void); // EV-B +interrupt void T4UFINT_ISR(void); // EV-B +interrupt void T4OFINT_ISR(void); // EV-B +interrupt void CAPINT4_ISR(void); // EV-B +interrupt void CAPINT5_ISR(void); // EV-B +interrupt void CAPINT6_ISR(void); // EV-B + +// Group 6 PIE Interrupt Service Routines: +interrupt void SPIRXINTA_ISR(void); // SPI +interrupt void SPITXINTA_ISR(void); // SPI +interrupt void MRINTA_ISR(void); // McBSP +interrupt void MXINTA_ISR(void); // McBSP + + +// Group 9 PIE Interrupt Service Routines: +interrupt void SCIRXINTA_ISR(void); // SCI-A +interrupt void SCITXINTA_ISR(void); // SCI-A +interrupt void SCIRXINTB_ISR(void); // SCI-B +interrupt void SCITXINTB_ISR(void); // SCI-B +interrupt void ECAN0INTA_ISR(void); // eCAN +interrupt void ECAN1INTA_ISR(void); // eCAN + + +// Catch-all for Reserved Locations For testing purposes: +interrupt void PIE_RESERVED(void); // Reserved for test +interrupt void rsvd_ISR(void); // for test + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_DEFAULT_ISR_H definition + diff --git a/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_Examples.h b/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_Examples.h new file mode 100644 index 0000000..4a8cd6a --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_Examples.h @@ -0,0 +1,88 @@ +// TI File $Revision: /main/3 $ +// Checkin $Date: April 25, 2007 11:04:51 $ +//########################################################################### +// +// FILE: DSP281x_Examples.h +// +// TITLE: DSP281x Device Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_EXAMPLES_H +#define DSP281x_EXAMPLES_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*----------------------------------------------------------------------------- + Specify the clock rate of the CPU (SYSCLKOUT) in nS. + + Take into account the input clock frequency and the PLL multiplier + selected in SysCtrl.c (0xA by default). + + Use one of the values provided, or define your own. + The trailing L is required tells the compiler to treat + the number as a 64-bit value. + + Only one statement should be uncommented. + + Example: CLKIN is a 30MHz crystal. + + In SysCtrl.c the user specified PLLCR = 0xA for a + 150Mhz CPU clock (SYSCLKOUT = 150MHz). + + In this case, the CPU_RATE will be 6.667L + Uncomment the line: #define CPU_RATE 6.667L +-----------------------------------------------------------------------------*/ +//#define CPU_RATE 6.667L // for a 150MHz CPU clock speed (SYSCLKOUT) +#define CPU_RATE 7.143L // for a 140MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 8.333L // for a 120MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 10.000L // for a 100MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 13.330L // for a 75MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 20.000L // for a 50MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 33.333L // for a 30MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 41.667L // for a 24MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 50.000L // for a 20MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 66.667L // for a 15MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 100.000L // for a 10MHz CPU clock speed (SYSCLKOUT) + +//---------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Include Example Header Files: +// + +#include "DSP281x_GlobalPrototypes.h" // Prototypes for global functions within the + // .c files. + +#include "DSP281x_SWPrioritizedIsrLevels.h" // Used for Software Prioritization of ISR's + + +// Include files not used with DSP/BIOS +#ifndef DSP28_BIOS +#include "DSP281x_DefaultISR.h" +#endif + + +// DO NOT MODIFY THIS LINE. +#define DELAY_US(A) DSP28x_usDelay(((((long double) A * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L) + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_EXAMPELS_H definition + + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_GlobalPrototypes.h b/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_GlobalPrototypes.h new file mode 100644 index 0000000..65bfb6c --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_GlobalPrototypes.h @@ -0,0 +1,87 @@ +// TI File $Revision: /main/7 $ +// Checkin $Date: July 9, 2009 13:14:00 $ +//########################################################################### +// +// FILE: DSP281x_GlobalPrototypes.h +// +// TITLE: Global prototypes for DSP28 Examples +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_GLOBALPROTOTYPES_H +#define DSP281x_GLOBALPROTOTYPES_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/*---- shared global function prototypes -----------------------------------*/ +extern void InitAdc(void); +extern void InitPeripherals(void); +extern void InitECan(void); +extern void InitEv(void); +extern void InitGpio(void); +extern void InitMcbsp(void); +extern void InitPieCtrl(void); +extern void InitPieVectTable(void); +extern void EnableInterrupts(void); +extern void DisableInterrupts(void); +extern void InitSci(void); +extern void InitSpi(void); +extern void InitSysCtrl(void); +extern void InitXintf(void); +extern void InitXIntrupt(void); +extern void InitPll(Uint16 val); +extern void InitPeripheralClocks(void); + +// McBSP functions +// DSP281x_Mcbsp.c +extern void InitMcbspGpio(void); +extern void delay_loop(void); +extern void InitMcbspa8bit(void); +extern void InitMcbspa12bit(void); +extern void InitMcbspa16bit(void); +extern void InitMcbspa20bit(void); +extern void InitMcbspa24bit(void); +extern void InitMcbspa32bit(void); + +// Watchdog functions +// DSP28_SysCtrl.c +extern void KickDog(void); +extern void DisableDog(void); +extern Uint16 CsmUnlock(void); + +// DSP28_DBGIER.asm +extern void SetDBGIER(Uint16 dbgier); + +// DSP281x_usDelay.asm +extern void DSP28x_usDelay(Uint32 Count); + + +// CAUTION +// This function MUST be executed out of RAM. Executing it +// out of OTP/Flash will yield unpredictable results +extern void InitFlash(void); + + +void MemCopy(Uint16 *SourceAddr, Uint16* SourceEndAddr, Uint16* DestAddr); + + +//--------------------------------------------------------------------------- +// External symbols created by the linker cmd file +// DSP28 examples will use these to relocate code from one LOAD location +// in either Flash or XINTF to a different RUN location in internal +// RAM +extern Uint16 RamfuncsLoadStart; +extern Uint16 RamfuncsLoadEnd; +extern Uint16 RamfuncsRunStart; + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // - end of DSP281x_GLOBALPROTOTYPES_H + diff --git a/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_SWPrioritizedIsrLevels.h b/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_SWPrioritizedIsrLevels.h new file mode 100644 index 0000000..7495566 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/common/include/DSP281x_SWPrioritizedIsrLevels.h @@ -0,0 +1,5881 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 28, 2005 15:22:36 $ +//########################################################################### +// +// FILE: DSP281x_SWPrioritizedIsrLevels.h +// +// TITLE: DSP28 Devices Software Prioritized Interrupt Service Routine +// Level definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_SW_PRIORITZIED_ISR_H +#define DSP281x_SW_PRIORITZIED_ISR_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +//------------------------------------------------------------------------------- +// Interrupt Enable Register Allocation For F2810/12 Devices: +//------------------------------------------------------------------------------- +// Interrupts can be enabled/disabled using the CPU interrupt enable register +// (IER) and the PIE interrupt enable registers (PIIER1 to PIEIER12). The table +// below lists the allocation of the various interrupts to these registers: +// +//----------------------------------------------------------------------------------- +// CPU | PIEIER1 to PIEIER12 | +// IER | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | +// =====|=========|=========|=========|=========|=========|=========|=======|=======| +// INT1 |PDPINTA |PDPINTB | resvd | XINT1 | XINT2 |ADCINT | TINT0 |WAKEINT| +// | (EV-A) | (EV-B) | | | | | | | +// INT2 |CMP1INT |CMP2INT |CMP3INT |T1PINT |T1CINT |T1UFINT |T1OFINT| resvd | +// | (EV-A) | (EV-A) |(EV-A) |(EV-A) |(EV-A) |(EV-A) |(EV-A) | | +// INT3 |T2PINT |T2CINT |T2UFINT |T2OFINT |CAPINT1 |CAPINT2 |CAPINT3| resvd | +// | (EV-A) | (EV-A) |(EV-A) |(EV-A) |(EV-A) |(EV-A) |(EV-A) | | +// INT4 |CMP4INT |CMP5INT |CMP6INT |T3PINT |T3CINT |T3UFINT |T3OFINT| resvd | +// | (EV-B) | (EV-B) |(EV-B) |(EV-B) |(EV-B) |(EV-B) |(EV-B) | | +// INT5 |T4PINT |T4CINT |T4UFINT |T4OFINT |CAPINT4 |CAPINT5 |CAPINT6| resvd | +// | (EV-B) | (EV-B) |(EV-B) |(EV-B) |(EV-B) |(EV-B) |(EV-B) | | +// INT6 |SPIRXINTA|SPITXINTA| resvd | resvd | MRINTA | MXINTA | resvd | resvd | +// | (SPI-A) | (SPI-A) | | |(McBSP-A)|(McBSP-A)| | | +// INT7 | resvd | resvd | resvd | resvd | resvd | resvd | resvd | resvd | +// INT8 | resvd | resvd | resvd | resvd | resvd | resvd | resvd | resvd | +// INT9 |SCIRXINTA|SCITXINTA|SCIRXINTB|SCITXINTB|ECAN0INTA|ECAN1INTA| resvd | resvd | +// | (SCI-A) | (SCI-A) |(SCI-B) |(SCI-B) |(ECAN-A) |(ECAN-A) | | | +// INT10| resvd | resvd | resvd | resvd | resvd | resvd | resvd | resvd | +// INT11| resvd | resvd | resvd | resvd | resvd | resvd | resvd | resvd | +// INT12| resvd | resvd | resvd | resvd | resvd | resvd | resvd | resvd | +//------------------------------------------------------------------------------- +// INT13| INT13 +// INT14| INT14 +// INT15| DATALOG +// INT16| RTOSINT +//------------------------------------------------------------------------------- +// +//------------------------------------------------------------------------------- +// Set "Global" Interrupt Priority Level (IER register): +//------------------------------------------------------------------------------- +// The user must set the appropriate priority level for each of the CPU +// interrupts. This is termed as the "global" priority. The priority level +// must be a number between 1 (highest) to 16 (lowest). A value of 0 must +// be entered for reserved interrupts or interrupts that are not used. This +// will also reduce code size by not including ISR's that are not used. +// +// Note: The priority levels below are used to calculate the IER register +// interrupt masks MINT1 to MINT16. +// +// +// Note: The priority levels shown here may not make sense in a +// real application. This is for demonstration purposes only!!! +// +// The user should change these to values that make sense for +// their application. +// +// 0 = not used +// 1 = highest priority +// ... +// 16 = lowest priority +#define INT1PL 1 // Group1 Interrupts (PIEIER1) +#define INT2PL 4 // Group2 Interrupts (PIEIER2) +#define INT3PL 2 // Group3 Interrupts (PIEIER3) +#define INT4PL 4 // Group4 Interrupts (PIEIER4) +#define INT5PL 5 // Group5 Interrupts (PIEIER5) +#define INT6PL 3 // Group6 Interrupts (PIEIER6) +#define INT7PL 0 // reserved +#define INT8PL 0 // reserved +#define INT9PL 3 // Group9 Interrupts (PIEIER9) +#define INT10PL 0 // reserved +#define INT11PL 0 // reserved +#define INT12PL 0 // reserved +#define INT13PL 4 // XINT3 +#define INT14PL 4 // INT14 (TINT2) +#define INT15PL 4 // DATALOG +#define INT16PL 4 // RTOSINT + +//------------------------------------------------------------------------------- +// Set "Group" Interrupt Priority Level (PIEIER1 to PIEIER12 registers): +//------------------------------------------------------------------------------- +// The user must set the appropriate priority level for each of the PIE +// interrupts. This is termed as the "group" priority. The priority level +// must be a number between 1 (highest) to 8 (lowest). A value of 0 must +// be entered for reserved interrupts or interrupts that are not used. This +// will also reduce code size by not including ISR's that are not used: +// +// Note: The priority levels below are used to calculate the following +// PIEIER register interrupt masks: +// MG11 to MG18 +// MG21 to MG28 +// MG31 to MG38 +// MG41 to MG48 +// MG51 to MG58 +// MG61 to MG68 +// MG71 to MG78 +// MG81 to MG88 +// MG91 to MG98 +// MG101 to MG108 +// MG111 to MG118 +// MG121 to MG128 +// +// Note: The priority levels shown here may not make sense in a +// real application. This is for demonstration purposes only!!! +// +// The user should change these to values that make sense for +// their application. +// +// 0 = not used +// 1 = highest priority +// ... +// 8 = lowest priority +// +#define G11PL 7 // PDPINTA (EV-A) +#define G12PL 6 // PDPINTB (EV-B) +#define G13PL 0 // reserved +#define G14PL 1 // XINT1 (External) +#define G15PL 3 // XINT2 (External) +#define G16PL 2 // ADCINT (ADC) +#define G17PL 1 // TINT0 (CPU Timer 0) +#define G18PL 5 // WAKEINT (WD/LPM) + +#define G21PL 4 // CMP1INT (EV-A) +#define G22PL 3 // CMP2INT (EV-A) +#define G23PL 2 // CMP3INT (EV-A) +#define G24PL 1 // T1PINT (EV-A) +#define G25PL 5 // T1CINT (EV-A) +#define G26PL 6 // T1UFINT (EV-A) +#define G27PL 7 // T1OFINT (EV-A) +#define G28PL 0 // reserved + +#define G31PL 1 // T2PINT (EV-A) +#define G32PL 1 // T2CINT (EV-A) +#define G33PL 1 // T2UFINT (EV-A) +#define G34PL 2 // T2OFINT (EV-A) +#define G35PL 2 // CAPINT1 (EV-A) +#define G36PL 1 // CAPINT2 (EV-A) +#define G37PL 3 // CAPINT3 (EV-A) +#define G38PL 0 // reserved + +#define G41PL 2 // CMP4INT (EV-B) +#define G42PL 1 // CMP5INT (EV-B) +#define G43PL 3 // CMP6INT (EV-B) +#define G44PL 3 // T3PINT (EV-B) +#define G45PL 2 // T3CINT (EV-B) +#define G46PL 2 // T3UFINT (EV-B) +#define G47PL 1 // T3OFINT (EV-B) +#define G48PL 0 // reserved + +#define G51PL 1 // T4PINT (EV-B) +#define G52PL 7 // T4CINT (EV-B) +#define G53PL 2 // T4UFINT (EV-B) +#define G54PL 6 // T4OFINT (EV-B) +#define G55PL 5 // CAPINT4 (EV-B) +#define G56PL 6 // CAPINT5 (EV-B) +#define G57PL 7 // CAPINT6 (EV-B) +#define G58PL 0 // reserved + +#define G61PL 3 // SPIRXINTA (SPI-A) +#define G62PL 1 // SPITXINTA (SPI-A) +#define G63PL 0 // reserved +#define G64PL 0 // reserved +#define G65PL 2 // MRINTA (McBSP-A) +#define G66PL 1 // MXINTA (McBSP-A) +#define G67PL 0 // reserved +#define G68PL 0 // reserved + +#define G71PL 0 // reserved +#define G72PL 0 // reserved +#define G73PL 0 // reserved +#define G74PL 0 // reserved +#define G75PL 0 // reserved +#define G76PL 0 // reserved +#define G77PL 0 // reserved +#define G78PL 0 // reserved + +#define G81PL 0 // reserved +#define G82PL 0 // reserved +#define G83PL 0 // reserved +#define G84PL 0 // reserved +#define G85PL 0 // reserved +#define G86PL 0 // reserved +#define G87PL 0 // reserved +#define G88PL 0 // reserved + +#define G91PL 1 // SCIRXINTA (SCI-A) +#define G92PL 5 // SCITXINTA (SCI-A) +#define G93PL 3 // SCIRXINTB (SCI-B) +#define G94PL 4 // SCITXINTB (SCI-B) +#define G95PL 1 // ECAN0INTA (ECAN-A) +#define G96PL 1 // ECAN1INTA (ECAN-A) +#define G97PL 0 // reserved +#define G98PL 0 // reserved + +#define G101PL 0 // reserved +#define G102PL 0 // reserved +#define G103PL 0 // reserved +#define G104PL 0 // reserved +#define G105PL 0 // reserved +#define G106PL 0 // reserved +#define G107PL 0 // reserved +#define G108PL 0 // reserved + +#define G111PL 0 // reserved +#define G112PL 0 // reserved +#define G113PL 0 // reserved +#define G114PL 0 // reserved +#define G115PL 0 // reserved +#define G116PL 0 // reserved +#define G117PL 0 // reserved +#define G118PL 0 // reserved + +#define G121PL 0 // reserved +#define G122PL 0 // reserved +#define G123PL 0 // reserved +#define G124PL 0 // reserved +#define G125PL 0 // reserved +#define G126PL 0 // reserved +#define G127PL 0 // reserved +#define G128PL 0 // reserved + + +// There should be no need to modify code below this line +//------------------------------------------------------------------------------- +// Automatically generate IER interrupt masks MINT1 to MINT16: +// + +// Beginning of MINT1: +#if (INT1PL == 0) +#define MINT1_1PL ~(1 << 0) +#else +#define MINT1_1PL 0xFFFF +#endif + +#if (INT2PL >= INT1PL) || (INT2PL == 0) +#define MINT1_2PL ~(1 << 1) +#else +#define MINT1_2PL 0xFFFF +#endif + +#if (INT3PL >= INT1PL) || (INT3PL == 0) +#define MINT1_3PL ~(1 << 2) +#else +#define MINT1_3PL 0xFFFF +#endif + +#if (INT4PL >= INT1PL) || (INT4PL == 0) +#define MINT1_4PL ~(1 << 3) +#else +#define MINT1_4PL 0xFFFF +#endif + +#if (INT5PL >= INT1PL) || (INT5PL == 0) +#define MINT1_5PL ~(1 << 4) +#else +#define MINT1_5PL 0xFFFF +#endif + +#if (INT6PL >= INT1PL) || (INT6PL == 0) +#define MINT1_6PL ~(1 << 5) +#else +#define MINT1_6PL 0xFFFF +#endif + +#if (INT7PL >= INT1PL) || (INT7PL == 0) +#define MINT1_7PL ~(1 << 6) +#else +#define MINT1_7PL 0xFFFF +#endif + +#if (INT8PL >= INT1PL) || (INT8PL == 0) +#define MINT1_8PL ~(1 << 7) +#else +#define MINT1_8PL 0xFFFF +#endif + +#if (INT9PL >= INT1PL) || (INT9PL == 0) +#define MINT1_9PL ~(1 << 8) +#else +#define MINT1_9PL 0xFFFF +#endif + +#if (INT10PL >= INT1PL) || (INT10PL == 0) +#define MINT1_10PL ~(1 << 9) +#else +#define MINT1_10PL 0xFFFF +#endif + +#if (INT11PL >= INT1PL) || (INT11PL == 0) +#define MINT1_11PL ~(1 << 10) +#else +#define MINT1_11PL 0xFFFF +#endif + +#if (INT12PL >= INT1PL) || (INT12PL == 0) +#define MINT1_12PL ~(1 << 11) +#else +#define MINT1_12PL 0xFFFF +#endif + +#if (INT13PL >= INT1PL) || (INT13PL == 0) +#define MINT1_13PL ~(1 << 12) +#else +#define MINT1_13PL 0xFFFF +#endif + +#if (INT14PL >= INT1PL) || (INT14PL == 0) +#define MINT1_14PL ~(1 << 13) +#else +#define MINT1_14PL 0xFFFF +#endif + +#if (INT15PL >= INT1PL) || (INT15PL == 0) +#define MINT1_15PL ~(1 << 14) +#else +#define MINT1_15PL 0xFFFF +#endif + +#if (INT16PL >= INT1PL) || (INT16PL == 0) +#define MINT1_16PL ~(1 << 15) +#else +#define MINT1_16PL 0xFFFF +#endif + +#define MINT1 (MINT1_1PL & MINT1_2PL & MINT1_3PL & MINT1_4PL & \ + MINT1_5PL & MINT1_6PL & MINT1_7PL & MINT1_8PL & \ + MINT1_9PL & MINT1_10PL & MINT1_11PL & MINT1_12PL & \ + MINT1_13PL & MINT1_14PL & MINT1_15PL & MINT1_16PL) +// End Of MINT1. + +// Beginning of MINT2: +#if (INT1PL >= INT2PL) || (INT1PL == 0) +#define MINT2_1PL ~(1 << 0) +#else +#define MINT2_1PL 0xFFFF +#endif + +#if (INT2PL == 0) +#define MINT2_2PL ~(1 << 1) +#else +#define MINT2_2PL 0xFFFF +#endif + +#if (INT3PL >= INT2PL) || (INT3PL == 0) +#define MINT2_3PL ~(1 << 2) +#else +#define MINT2_3PL 0xFFFF +#endif + +#if (INT4PL >= INT2PL) || (INT4PL == 0) +#define MINT2_4PL ~(1 << 3) +#else +#define MINT2_4PL 0xFFFF +#endif + +#if (INT5PL >= INT2PL) || (INT5PL == 0) +#define MINT2_5PL ~(1 << 4) +#else +#define MINT2_5PL 0xFFFF +#endif + +#if (INT6PL >= INT2PL) || (INT6PL == 0) +#define MINT2_6PL ~(1 << 5) +#else +#define MINT2_6PL 0xFFFF +#endif + +#if (INT7PL >= INT2PL) || (INT7PL == 0) +#define MINT2_7PL ~(1 << 6) +#else +#define MINT2_7PL 0xFFFF +#endif + +#if (INT8PL >= INT2PL) || (INT8PL == 0) +#define MINT2_8PL ~(1 << 7) +#else +#define MINT2_8PL 0xFFFF +#endif + +#if (INT9PL >= INT2PL) || (INT9PL == 0) +#define MINT2_9PL ~(1 << 8) +#else +#define MINT2_9PL 0xFFFF +#endif + +#if (INT10PL >= INT2PL) || (INT10PL == 0) +#define MINT2_10PL ~(1 << 9) +#else +#define MINT2_10PL 0xFFFF +#endif + +#if (INT11PL >= INT2PL) || (INT11PL == 0) +#define MINT2_11PL ~(1 << 10) +#else +#define MINT2_11PL 0xFFFF +#endif + +#if (INT12PL >= INT2PL) || (INT12PL == 0) +#define MINT2_12PL ~(1 << 11) +#else +#define MINT2_12PL 0xFFFF +#endif + +#if (INT13PL >= INT2PL) || (INT13PL == 0) +#define MINT2_13PL ~(1 << 12) +#else +#define MINT2_13PL 0xFFFF +#endif + +#if (INT14PL >= INT2PL) || (INT14PL == 0) +#define MINT2_14PL ~(1 << 13) +#else +#define MINT2_14PL 0xFFFF +#endif + +#if (INT15PL >= INT2PL) || (INT15PL == 0) +#define MINT2_15PL ~(1 << 14) +#else +#define MINT2_15PL 0xFFFF +#endif + +#if (INT16PL >= INT2PL) || (INT16PL == 0) +#define MINT2_16PL ~(1 << 15) +#else +#define MINT2_16PL 0xFFFF +#endif + +#define MINT2 (MINT2_1PL & MINT2_2PL & MINT2_3PL & MINT2_4PL & \ + MINT2_5PL & MINT2_6PL & MINT2_7PL & MINT2_8PL & \ + MINT2_9PL & MINT2_10PL & MINT2_11PL & MINT2_12PL & \ + MINT2_13PL & MINT2_14PL & MINT2_15PL & MINT2_16PL) +// End Of MINT2. + +// Beginning of MINT3: +#if (INT1PL >= INT3PL) || (INT1PL == 0) +#define MINT3_1PL ~(1 << 0) +#else +#define MINT3_1PL 0xFFFF +#endif + +#if (INT2PL >= INT3PL) || (INT2PL == 0) +#define MINT3_2PL ~(1 << 1) +#else +#define MINT3_2PL 0xFFFF +#endif + +#if (INT3PL == 0) +#define MINT3_3PL ~(1 << 2) +#else +#define MINT3_3PL 0xFFFF +#endif + +#if (INT4PL >= INT3PL) || (INT4PL == 0) +#define MINT3_4PL ~(1 << 3) +#else +#define MINT3_4PL 0xFFFF +#endif + +#if (INT5PL >= INT3PL) || (INT5PL == 0) +#define MINT3_5PL ~(1 << 4) +#else +#define MINT3_5PL 0xFFFF +#endif + +#if (INT6PL >= INT3PL) || (INT6PL == 0) +#define MINT3_6PL ~(1 << 5) +#else +#define MINT3_6PL 0xFFFF +#endif + +#if (INT7PL >= INT3PL) || (INT7PL == 0) +#define MINT3_7PL ~(1 << 6) +#else +#define MINT3_7PL 0xFFFF +#endif + +#if (INT8PL >= INT3PL) || (INT8PL == 0) +#define MINT3_8PL ~(1 << 7) +#else +#define MINT3_8PL 0xFFFF +#endif + +#if (INT9PL >= INT3PL) || (INT9PL == 0) +#define MINT3_9PL ~(1 << 8) +#else +#define MINT3_9PL 0xFFFF +#endif + +#if (INT10PL >= INT3PL) || (INT10PL == 0) +#define MINT3_10PL ~(1 << 9) +#else +#define MINT3_10PL 0xFFFF +#endif + +#if (INT11PL >= INT3PL) || (INT11PL == 0) +#define MINT3_11PL ~(1 << 10) +#else +#define MINT3_11PL 0xFFFF +#endif + +#if (INT12PL >= INT3PL) || (INT12PL == 0) +#define MINT3_12PL ~(1 << 11) +#else +#define MINT3_12PL 0xFFFF +#endif + +#if (INT13PL >= INT3PL) || (INT13PL == 0) +#define MINT3_13PL ~(1 << 12) +#else +#define MINT3_13PL 0xFFFF +#endif + +#if (INT14PL >= INT3PL) || (INT14PL == 0) +#define MINT3_14PL ~(1 << 13) +#else +#define MINT3_14PL 0xFFFF +#endif + +#if (INT15PL >= INT3PL) || (INT15PL == 0) +#define MINT3_15PL ~(1 << 14) +#else +#define MINT3_15PL 0xFFFF +#endif + +#if (INT16PL >= INT3PL) || (INT16PL == 0) +#define MINT3_16PL ~(1 << 15) +#else +#define MINT3_16PL 0xFFFF +#endif + +#define MINT3 (MINT3_1PL & MINT3_2PL & MINT3_3PL & MINT3_4PL & \ + MINT3_5PL & MINT3_6PL & MINT3_7PL & MINT3_8PL & \ + MINT3_9PL & MINT3_10PL & MINT3_11PL & MINT3_12PL & \ + MINT3_13PL & MINT3_14PL & MINT3_15PL & MINT3_16PL) +// End Of MINT3. + +// Beginning of MINT4: +#if (INT1PL >= INT4PL) || (INT1PL == 0) +#define MINT4_1PL ~(1 << 0) +#else +#define MINT4_1PL 0xFFFF +#endif + +#if (INT2PL >= INT4PL) || (INT2PL == 0) +#define MINT4_2PL ~(1 << 1) +#else +#define MINT4_2PL 0xFFFF +#endif + +#if (INT3PL >= INT4PL) || (INT3PL == 0) +#define MINT4_3PL ~(1 << 2) +#else +#define MINT4_3PL 0xFFFF +#endif + +#if (INT4PL == 0) +#define MINT4_4PL ~(1 << 3) +#else +#define MINT4_4PL 0xFFFF +#endif + +#if (INT5PL >= INT4PL) || (INT5PL == 0) +#define MINT4_5PL ~(1 << 4) +#else +#define MINT4_5PL 0xFFFF +#endif + +#if (INT6PL >= INT4PL) || (INT6PL == 0) +#define MINT4_6PL ~(1 << 5) +#else +#define MINT4_6PL 0xFFFF +#endif + +#if (INT7PL >= INT4PL) || (INT7PL == 0) +#define MINT4_7PL ~(1 << 6) +#else +#define MINT4_7PL 0xFFFF +#endif + +#if (INT8PL >= INT4PL) || (INT8PL == 0) +#define MINT4_8PL ~(1 << 7) +#else +#define MINT4_8PL 0xFFFF +#endif + +#if (INT9PL >= INT4PL) || (INT9PL == 0) +#define MINT4_9PL ~(1 << 8) +#else +#define MINT4_9PL 0xFFFF +#endif + +#if (INT10PL >= INT4PL) || (INT10PL == 0) +#define MINT4_10PL ~(1 << 9) +#else +#define MINT4_10PL 0xFFFF +#endif + +#if (INT11PL >= INT4PL) || (INT11PL == 0) +#define MINT4_11PL ~(1 << 10) +#else +#define MINT4_11PL 0xFFFF +#endif + +#if (INT12PL >= INT4PL) || (INT12PL == 0) +#define MINT4_12PL ~(1 << 11) +#else +#define MINT4_12PL 0xFFFF +#endif + +#if (INT13PL >= INT4PL) || (INT13PL == 0) +#define MINT4_13PL ~(1 << 12) +#else +#define MINT4_13PL 0xFFFF +#endif + +#if (INT14PL >= INT4PL) || (INT14PL == 0) +#define MINT4_14PL ~(1 << 13) +#else +#define MINT4_14PL 0xFFFF +#endif + +#if (INT15PL >= INT4PL) || (INT15PL == 0) +#define MINT4_15PL ~(1 << 14) +#else +#define MINT4_15PL 0xFFFF +#endif + +#if (INT16PL >= INT4PL) || (INT16PL == 0) +#define MINT4_16PL ~(1 << 15) +#else +#define MINT4_16PL 0xFFFF +#endif + +#define MINT4 (MINT4_1PL & MINT4_2PL & MINT4_3PL & MINT4_4PL & \ + MINT4_5PL & MINT4_6PL & MINT4_7PL & MINT4_8PL & \ + MINT4_9PL & MINT4_10PL & MINT4_11PL & MINT4_12PL & \ + MINT4_13PL & MINT4_14PL & MINT4_15PL & MINT4_16PL) +// End Of MINT4. + +// Beginning of MINT5: +#if (INT1PL >= INT5PL) || (INT1PL == 0) +#define MINT5_1PL ~(1 << 0) +#else +#define MINT5_1PL 0xFFFF +#endif + +#if (INT2PL >= INT5PL) || (INT2PL == 0) +#define MINT5_2PL ~(1 << 1) +#else +#define MINT5_2PL 0xFFFF +#endif + +#if (INT3PL >= INT5PL) || (INT3PL == 0) +#define MINT5_3PL ~(1 << 2) +#else +#define MINT5_3PL 0xFFFF +#endif + +#if (INT4PL >= INT5PL) || (INT4PL == 0) +#define MINT5_4PL ~(1 << 3) +#else +#define MINT5_4PL 0xFFFF +#endif + +#if (INT5PL == 0) +#define MINT5_5PL ~(1 << 4) +#else +#define MINT5_5PL 0xFFFF +#endif + +#if (INT6PL >= INT5PL) || (INT6PL == 0) +#define MINT5_6PL ~(1 << 5) +#else +#define MINT5_6PL 0xFFFF +#endif + +#if (INT7PL >= INT5PL) || (INT7PL == 0) +#define MINT5_7PL ~(1 << 6) +#else +#define MINT5_7PL 0xFFFF +#endif + +#if (INT8PL >= INT5PL) || (INT8PL == 0) +#define MINT5_8PL ~(1 << 7) +#else +#define MINT5_8PL 0xFFFF +#endif + +#if (INT9PL >= INT5PL) || (INT9PL == 0) +#define MINT5_9PL ~(1 << 8) +#else +#define MINT5_9PL 0xFFFF +#endif + +#if (INT10PL >= INT5PL) || (INT10PL == 0) +#define MINT5_10PL ~(1 << 9) +#else +#define MINT5_10PL 0xFFFF +#endif + +#if (INT11PL >= INT5PL) || (INT11PL == 0) +#define MINT5_11PL ~(1 << 10) +#else +#define MINT5_11PL 0xFFFF +#endif + +#if (INT12PL >= INT5PL) || (INT12PL == 0) +#define MINT5_12PL ~(1 << 11) +#else +#define MINT5_12PL 0xFFFF +#endif + +#if (INT13PL >= INT5PL) || (INT13PL == 0) +#define MINT5_13PL ~(1 << 12) +#else +#define MINT5_13PL 0xFFFF +#endif + +#if (INT14PL >= INT5PL) || (INT14PL == 0) +#define MINT5_14PL ~(1 << 13) +#else +#define MINT5_14PL 0xFFFF +#endif + +#if (INT15PL >= INT5PL) || (INT15PL == 0) +#define MINT5_15PL ~(1 << 14) +#else +#define MINT5_15PL 0xFFFF +#endif + +#if (INT16PL >= INT5PL) || (INT16PL == 0) +#define MINT5_16PL ~(1 << 15) +#else +#define MINT5_16PL 0xFFFF +#endif + +#define MINT5 (MINT5_1PL & MINT5_2PL & MINT5_3PL & MINT5_4PL & \ + MINT5_5PL & MINT5_6PL & MINT5_7PL & MINT5_8PL & \ + MINT5_9PL & MINT5_10PL & MINT5_11PL & MINT5_12PL & \ + MINT5_13PL & MINT5_14PL & MINT5_15PL & MINT5_16PL) +// End Of MINT5. + +// Beginning of MINT6: +#if (INT1PL >= INT6PL) || (INT1PL == 0) +#define MINT6_1PL ~(1 << 0) +#else +#define MINT6_1PL 0xFFFF +#endif + +#if (INT2PL >= INT6PL) || (INT2PL == 0) +#define MINT6_2PL ~(1 << 1) +#else +#define MINT6_2PL 0xFFFF +#endif + +#if (INT3PL >= INT6PL) || (INT3PL == 0) +#define MINT6_3PL ~(1 << 2) +#else +#define MINT6_3PL 0xFFFF +#endif + +#if (INT4PL >= INT6PL) || (INT4PL == 0) +#define MINT6_4PL ~(1 << 3) +#else +#define MINT6_4PL 0xFFFF +#endif + +#if (INT5PL >= INT6PL) || (INT5PL == 0) +#define MINT6_5PL ~(1 << 4) +#else +#define MINT6_5PL 0xFFFF +#endif + +#if (INT6PL == 0) +#define MINT6_6PL ~(1 << 5) +#else +#define MINT6_6PL 0xFFFF +#endif + +#if (INT7PL >= INT6PL) || (INT7PL == 0) +#define MINT6_7PL ~(1 << 6) +#else +#define MINT6_7PL 0xFFFF +#endif + +#if (INT8PL >= INT6PL) || (INT8PL == 0) +#define MINT6_8PL ~(1 << 7) +#else +#define MINT6_8PL 0xFFFF +#endif + +#if (INT9PL >= INT6PL) || (INT9PL == 0) +#define MINT6_9PL ~(1 << 8) +#else +#define MINT6_9PL 0xFFFF +#endif + +#if (INT10PL >= INT6PL) || (INT10PL == 0) +#define MINT6_10PL ~(1 << 9) +#else +#define MINT6_10PL 0xFFFF +#endif + +#if (INT11PL >= INT6PL) || (INT11PL == 0) +#define MINT6_11PL ~(1 << 10) +#else +#define MINT6_11PL 0xFFFF +#endif + +#if (INT12PL >= INT6PL) || (INT12PL == 0) +#define MINT6_12PL ~(1 << 11) +#else +#define MINT6_12PL 0xFFFF +#endif + +#if (INT13PL >= INT6PL) || (INT13PL == 0) +#define MINT6_13PL ~(1 << 12) +#else +#define MINT6_13PL 0xFFFF +#endif + +#if (INT14PL >= INT6PL) || (INT14PL == 0) +#define MINT6_14PL ~(1 << 13) +#else +#define MINT6_14PL 0xFFFF +#endif + +#if (INT15PL >= INT6PL) || (INT15PL == 0) +#define MINT6_15PL ~(1 << 14) +#else +#define MINT6_15PL 0xFFFF +#endif + +#if (INT16PL >= INT6PL) || (INT16PL == 0) +#define MINT6_16PL ~(1 << 15) +#else +#define MINT6_16PL 0xFFFF +#endif + +#define MINT6 (MINT6_1PL & MINT6_2PL & MINT6_3PL & MINT6_4PL & \ + MINT6_5PL & MINT6_6PL & MINT6_7PL & MINT6_8PL & \ + MINT6_9PL & MINT6_10PL & MINT6_11PL & MINT6_12PL & \ + MINT6_13PL & MINT6_14PL & MINT6_15PL & MINT6_16PL) +// End Of MINT6. + +// Beginning of MINT7: +#if (INT1PL >= INT7PL) || (INT1PL == 0) +#define MINT7_1PL ~(1 << 0) +#else +#define MINT7_1PL 0xFFFF +#endif + +#if (INT2PL >= INT7PL) || (INT2PL == 0) +#define MINT7_2PL ~(1 << 1) +#else +#define MINT7_2PL 0xFFFF +#endif + +#if (INT3PL >= INT7PL) || (INT3PL == 0) +#define MINT7_3PL ~(1 << 2) +#else +#define MINT7_3PL 0xFFFF +#endif + +#if (INT4PL >= INT7PL) || (INT4PL == 0) +#define MINT7_4PL ~(1 << 3) +#else +#define MINT7_4PL 0xFFFF +#endif + +#if (INT5PL >= INT7PL) || (INT5PL == 0) +#define MINT7_5PL ~(1 << 4) +#else +#define MINT7_5PL 0xFFFF +#endif + +#if (INT6PL >= INT7PL) || (INT6PL == 0) +#define MINT7_6PL ~(1 << 5) +#else +#define MINT7_6PL 0xFFFF +#endif + +#if (INT7PL == 0) +#define MINT7_7PL ~(1 << 6) +#else +#define MINT7_7PL 0xFFFF +#endif + +#if (INT8PL >= INT7PL) || (INT8PL == 0) +#define MINT7_8PL ~(1 << 7) +#else +#define MINT7_8PL 0xFFFF +#endif + +#if (INT9PL >= INT7PL) || (INT9PL == 0) +#define MINT7_9PL ~(1 << 8) +#else +#define MINT7_9PL 0xFFFF +#endif + +#if (INT10PL >= INT7PL) || (INT10PL == 0) +#define MINT7_10PL ~(1 << 9) +#else +#define MINT7_10PL 0xFFFF +#endif + +#if (INT11PL >= INT7PL) || (INT11PL == 0) +#define MINT7_11PL ~(1 << 10) +#else +#define MINT7_11PL 0xFFFF +#endif + +#if (INT12PL >= INT7PL) || (INT12PL == 0) +#define MINT7_12PL ~(1 << 11) +#else +#define MINT7_12PL 0xFFFF +#endif + +#if (INT13PL >= INT7PL) || (INT13PL == 0) +#define MINT7_13PL ~(1 << 12) +#else +#define MINT7_13PL 0xFFFF +#endif + +#if (INT14PL >= INT7PL) || (INT14PL == 0) +#define MINT7_14PL ~(1 << 13) +#else +#define MINT7_14PL 0xFFFF +#endif + +#if (INT15PL >= INT7PL) || (INT15PL == 0) +#define MINT7_15PL ~(1 << 14) +#else +#define MINT7_15PL 0xFFFF +#endif + +#if (INT16PL >= INT7PL) || (INT16PL == 0) +#define MINT7_16PL ~(1 << 15) +#else +#define MINT7_16PL 0xFFFF +#endif + +#define MINT7 (MINT7_1PL & MINT7_2PL & MINT7_3PL & MINT7_4PL & \ + MINT7_5PL & MINT7_6PL & MINT7_7PL & MINT7_8PL & \ + MINT7_9PL & MINT7_10PL & MINT7_11PL & MINT7_12PL & \ + MINT7_13PL & MINT7_14PL & MINT7_15PL & MINT7_16PL) +// End Of MINT7. + +// Beginning of MINT8: +#if (INT1PL >= INT8PL) || (INT1PL == 0) +#define MINT8_1PL ~(1 << 0) +#else +#define MINT8_1PL 0xFFFF +#endif + +#if (INT2PL >= INT8PL) || (INT2PL == 0) +#define MINT8_2PL ~(1 << 1) +#else +#define MINT8_2PL 0xFFFF +#endif + +#if (INT3PL >= INT8PL) || (INT3PL == 0) +#define MINT8_3PL ~(1 << 2) +#else +#define MINT8_3PL 0xFFFF +#endif + +#if (INT4PL >= INT8PL) || (INT4PL == 0) +#define MINT8_4PL ~(1 << 3) +#else +#define MINT8_4PL 0xFFFF +#endif + +#if (INT5PL >= INT8PL) || (INT5PL == 0) +#define MINT8_5PL ~(1 << 4) +#else +#define MINT8_5PL 0xFFFF +#endif + +#if (INT6PL >= INT8PL) || (INT6PL == 0) +#define MINT8_6PL ~(1 << 5) +#else +#define MINT8_6PL 0xFFFF +#endif + +#if (INT7PL >= INT8PL) || (INT7PL == 0) +#define MINT8_7PL ~(1 << 6) +#else +#define MINT8_7PL 0xFFFF +#endif + +#if (INT8PL == 0) +#define MINT8_8PL ~(1 << 7) +#else +#define MINT8_8PL 0xFFFF +#endif + +#if (INT9PL >= INT8PL) || (INT9PL == 0) +#define MINT8_9PL ~(1 << 8) +#else +#define MINT8_9PL 0xFFFF +#endif + +#if (INT10PL >= INT8PL) || (INT10PL == 0) +#define MINT8_10PL ~(1 << 9) +#else +#define MINT8_10PL 0xFFFF +#endif + +#if (INT11PL >= INT8PL) || (INT11PL == 0) +#define MINT8_11PL ~(1 << 10) +#else +#define MINT8_11PL 0xFFFF +#endif + +#if (INT12PL >= INT8PL) || (INT12PL == 0) +#define MINT8_12PL ~(1 << 11) +#else +#define MINT8_12PL 0xFFFF +#endif + +#if (INT13PL >= INT8PL) || (INT13PL == 0) +#define MINT8_13PL ~(1 << 12) +#else +#define MINT8_13PL 0xFFFF +#endif + +#if (INT14PL >= INT8PL) || (INT14PL == 0) +#define MINT8_14PL ~(1 << 13) +#else +#define MINT8_14PL 0xFFFF +#endif + +#if (INT15PL >= INT8PL) || (INT15PL == 0) +#define MINT8_15PL ~(1 << 14) +#else +#define MINT8_15PL 0xFFFF +#endif + +#if (INT16PL >= INT8PL) || (INT16PL == 0) +#define MINT8_16PL ~(1 << 15) +#else +#define MINT8_16PL 0xFFFF +#endif + +#define MINT8 (MINT8_1PL & MINT8_2PL & MINT8_3PL & MINT8_4PL & \ + MINT8_5PL & MINT8_6PL & MINT8_7PL & MINT8_8PL & \ + MINT8_9PL & MINT8_10PL & MINT8_11PL & MINT8_12PL & \ + MINT8_13PL & MINT8_14PL & MINT8_15PL & MINT8_16PL) +// End Of MINT8. + +// Beginning of MINT9: +#if (INT1PL >= INT9PL) || (INT1PL == 0) +#define MINT9_1PL ~(1 << 0) +#else +#define MINT9_1PL 0xFFFF +#endif + +#if (INT2PL >= INT9PL) || (INT2PL == 0) +#define MINT9_2PL ~(1 << 1) +#else +#define MINT9_2PL 0xFFFF +#endif + +#if (INT3PL >= INT9PL) || (INT3PL == 0) +#define MINT9_3PL ~(1 << 2) +#else +#define MINT9_3PL 0xFFFF +#endif + +#if (INT4PL >= INT9PL) || (INT4PL == 0) +#define MINT9_4PL ~(1 << 3) +#else +#define MINT9_4PL 0xFFFF +#endif + +#if (INT5PL >= INT9PL) || (INT5PL == 0) +#define MINT9_5PL ~(1 << 4) +#else +#define MINT9_5PL 0xFFFF +#endif + +#if (INT6PL >= INT9PL) || (INT6PL == 0) +#define MINT9_6PL ~(1 << 5) +#else +#define MINT9_6PL 0xFFFF +#endif + +#if (INT7PL >= INT9PL) || (INT7PL == 0) +#define MINT9_7PL ~(1 << 6) +#else +#define MINT9_7PL 0xFFFF +#endif + +#if (INT8PL >= INT9PL) || (INT8PL == 0) +#define MINT9_8PL ~(1 << 7) +#else +#define MINT9_8PL 0xFFFF +#endif + +#if (INT9PL == 0) +#define MINT9_9PL ~(1 << 8) +#else +#define MINT9_9PL 0xFFFF +#endif + +#if (INT10PL >= INT9PL) || (INT10PL == 0) +#define MINT9_10PL ~(1 << 9) +#else +#define MINT9_10PL 0xFFFF +#endif + +#if (INT11PL >= INT9PL) || (INT11PL == 0) +#define MINT9_11PL ~(1 << 10) +#else +#define MINT9_11PL 0xFFFF +#endif + +#if (INT12PL >= INT9PL) || (INT12PL == 0) +#define MINT9_12PL ~(1 << 11) +#else +#define MINT9_12PL 0xFFFF +#endif + +#if (INT13PL >= INT9PL) || (INT13PL == 0) +#define MINT9_13PL ~(1 << 12) +#else +#define MINT9_13PL 0xFFFF +#endif + +#if (INT14PL >= INT9PL) || (INT14PL == 0) +#define MINT9_14PL ~(1 << 13) +#else +#define MINT9_14PL 0xFFFF +#endif + +#if (INT15PL >= INT9PL) || (INT15PL == 0) +#define MINT9_15PL ~(1 << 14) +#else +#define MINT9_15PL 0xFFFF +#endif + +#if (INT16PL >= INT9PL) || (INT16PL == 0) +#define MINT9_16PL ~(1 << 15) +#else +#define MINT9_16PL 0xFFFF +#endif + +#define MINT9 (MINT9_1PL & MINT9_2PL & MINT9_3PL & MINT9_4PL & \ + MINT9_5PL & MINT9_6PL & MINT9_7PL & MINT9_8PL & \ + MINT9_9PL & MINT9_10PL & MINT9_11PL & MINT9_12PL & \ + MINT9_13PL & MINT9_14PL & MINT9_15PL & MINT9_16PL) +// End Of MINT9. + +// Beginning of MINT10: +#if (INT1PL >= INT10PL) || (INT1PL == 0) +#define MINT10_1PL ~(1 << 0) +#else +#define MINT10_1PL 0xFFFF +#endif + +#if (INT2PL >= INT10PL) || (INT2PL == 0) +#define MINT10_2PL ~(1 << 1) +#else +#define MINT10_2PL 0xFFFF +#endif + +#if (INT3PL >= INT10PL) || (INT3PL == 0) +#define MINT10_3PL ~(1 << 2) +#else +#define MINT10_3PL 0xFFFF +#endif + +#if (INT4PL >= INT10PL) || (INT4PL == 0) +#define MINT10_4PL ~(1 << 3) +#else +#define MINT10_4PL 0xFFFF +#endif + +#if (INT5PL >= INT10PL) || (INT5PL == 0) +#define MINT10_5PL ~(1 << 4) +#else +#define MINT10_5PL 0xFFFF +#endif + +#if (INT6PL >= INT10PL) || (INT6PL == 0) +#define MINT10_6PL ~(1 << 5) +#else +#define MINT10_6PL 0xFFFF +#endif + +#if (INT7PL >= INT10PL) || (INT7PL == 0) +#define MINT10_7PL ~(1 << 6) +#else +#define MINT10_7PL 0xFFFF +#endif + +#if (INT8PL >= INT10PL) || (INT8PL == 0) +#define MINT10_8PL ~(1 << 7) +#else +#define MINT10_8PL 0xFFFF +#endif + +#if (INT9PL >= INT10PL) || (INT9PL == 0) +#define MINT10_9PL ~(1 << 8) +#else +#define MINT10_9PL 0xFFFF +#endif + +#if (INT10PL == 0) +#define MINT10_10PL ~(1 << 9) +#else +#define MINT10_10PL 0xFFFF +#endif + +#if (INT11PL >= INT10PL) || (INT11PL == 0) +#define MINT10_11PL ~(1 << 10) +#else +#define MINT10_11PL 0xFFFF +#endif + +#if (INT12PL >= INT10PL) || (INT12PL == 0) +#define MINT10_12PL ~(1 << 11) +#else +#define MINT10_12PL 0xFFFF +#endif + +#if (INT13PL >= INT10PL) || (INT13PL == 0) +#define MINT10_13PL ~(1 << 12) +#else +#define MINT10_13PL 0xFFFF +#endif + +#if (INT14PL >= INT10PL) || (INT14PL == 0) +#define MINT10_14PL ~(1 << 13) +#else +#define MINT10_14PL 0xFFFF +#endif + +#if (INT15PL >= INT10PL) || (INT15PL == 0) +#define MINT10_15PL ~(1 << 14) +#else +#define MINT10_15PL 0xFFFF +#endif + +#if (INT16PL >= INT10PL) || (INT16PL == 0) +#define MINT10_16PL ~(1 << 15) +#else +#define MINT10_16PL 0xFFFF +#endif + +#define MINT10 (MINT10_1PL & MINT10_2PL & MINT10_3PL & MINT10_4PL & \ + MINT10_5PL & MINT10_6PL & MINT10_7PL & MINT10_8PL & \ + MINT10_9PL & MINT10_10PL & MINT10_11PL & MINT10_12PL & \ + MINT10_13PL & MINT10_14PL & MINT10_15PL & MINT10_16PL) +// End Of MINT10. + +// Beginning of MINT11: +#if (INT1PL >= INT11PL) || (INT1PL == 0) +#define MINT11_1PL ~(1 << 0) +#else +#define MINT11_1PL 0xFFFF +#endif + +#if (INT2PL >= INT11PL) || (INT2PL == 0) +#define MINT11_2PL ~(1 << 1) +#else +#define MINT11_2PL 0xFFFF +#endif + +#if (INT3PL >= INT11PL) || (INT3PL == 0) +#define MINT11_3PL ~(1 << 2) +#else +#define MINT11_3PL 0xFFFF +#endif + +#if (INT4PL >= INT11PL) || (INT4PL == 0) +#define MINT11_4PL ~(1 << 3) +#else +#define MINT11_4PL 0xFFFF +#endif + +#if (INT5PL >= INT11PL) || (INT5PL == 0) +#define MINT11_5PL ~(1 << 4) +#else +#define MINT11_5PL 0xFFFF +#endif + +#if (INT6PL >= INT11PL) || (INT6PL == 0) +#define MINT11_6PL ~(1 << 5) +#else +#define MINT11_6PL 0xFFFF +#endif + +#if (INT7PL >= INT11PL) || (INT7PL == 0) +#define MINT11_7PL ~(1 << 6) +#else +#define MINT11_7PL 0xFFFF +#endif + +#if (INT8PL >= INT11PL) || (INT8PL == 0) +#define MINT11_8PL ~(1 << 7) +#else +#define MINT11_8PL 0xFFFF +#endif + +#if (INT9PL >= INT11PL) || (INT9PL == 0) +#define MINT11_9PL ~(1 << 8) +#else +#define MINT11_9PL 0xFFFF +#endif + +#if (INT10PL >= INT11PL) || (INT10PL == 0) +#define MINT11_10PL ~(1 << 9) +#else +#define MINT11_10PL 0xFFFF +#endif + +#if (INT11PL == 0) +#define MINT11_11PL ~(1 << 10) +#else +#define MINT11_11PL 0xFFFF +#endif + +#if (INT12PL >= INT11PL) || (INT12PL == 0) +#define MINT11_12PL ~(1 << 11) +#else +#define MINT11_12PL 0xFFFF +#endif + +#if (INT13PL >= INT11PL) || (INT13PL == 0) +#define MINT11_13PL ~(1 << 12) +#else +#define MINT11_13PL 0xFFFF +#endif + +#if (INT14PL >= INT11PL) || (INT14PL == 0) +#define MINT11_14PL ~(1 << 13) +#else +#define MINT11_14PL 0xFFFF +#endif + +#if (INT15PL >= INT11PL) || (INT15PL == 0) +#define MINT11_15PL ~(1 << 14) +#else +#define MINT11_15PL 0xFFFF +#endif + +#if (INT16PL >= INT11PL) || (INT16PL == 0) +#define MINT11_16PL ~(1 << 15) +#else +#define MINT11_16PL 0xFFFF +#endif + +#define MINT11 (MINT11_1PL & MINT11_2PL & MINT11_3PL & MINT11_4PL & \ + MINT11_5PL & MINT11_6PL & MINT11_7PL & MINT11_8PL & \ + MINT11_9PL & MINT11_10PL & MINT11_11PL & MINT11_12PL & \ + MINT11_13PL & MINT11_14PL & MINT11_15PL & MINT11_16PL) +// End Of MINT11. + +// Beginning of MINT12: +#if (INT1PL >= INT12PL) || (INT1PL == 0) +#define MINT12_1PL ~(1 << 0) +#else +#define MINT12_1PL 0xFFFF +#endif + +#if (INT2PL >= INT12PL) || (INT2PL == 0) +#define MINT12_2PL ~(1 << 1) +#else +#define MINT12_2PL 0xFFFF +#endif + +#if (INT3PL >= INT12PL) || (INT3PL == 0) +#define MINT12_3PL ~(1 << 2) +#else +#define MINT12_3PL 0xFFFF +#endif + +#if (INT4PL >= INT12PL) || (INT4PL == 0) +#define MINT12_4PL ~(1 << 3) +#else +#define MINT12_4PL 0xFFFF +#endif + +#if (INT5PL >= INT12PL) || (INT5PL == 0) +#define MINT12_5PL ~(1 << 4) +#else +#define MINT12_5PL 0xFFFF +#endif + +#if (INT6PL >= INT12PL) || (INT6PL == 0) +#define MINT12_6PL ~(1 << 5) +#else +#define MINT12_6PL 0xFFFF +#endif + +#if (INT7PL >= INT12PL) || (INT7PL == 0) +#define MINT12_7PL ~(1 << 6) +#else +#define MINT12_7PL 0xFFFF +#endif + +#if (INT8PL >= INT12PL) || (INT8PL == 0) +#define MINT12_8PL ~(1 << 7) +#else +#define MINT12_8PL 0xFFFF +#endif + +#if (INT9PL >= INT12PL) || (INT9PL == 0) +#define MINT12_9PL ~(1 << 8) +#else +#define MINT12_9PL 0xFFFF +#endif + +#if (INT10PL >= INT12PL) || (INT10PL == 0) +#define MINT12_10PL ~(1 << 9) +#else +#define MINT12_10PL 0xFFFF +#endif + +#if (INT11PL >= INT12PL) || (INT11PL == 0) +#define MINT12_11PL ~(1 << 10) +#else +#define MINT12_11PL 0xFFFF +#endif + +#if (INT12PL == 0) +#define MINT12_12PL ~(1 << 11) +#else +#define MINT12_12PL 0xFFFF +#endif + +#if (INT13PL >= INT12PL) || (INT13PL == 0) +#define MINT12_13PL ~(1 << 12) +#else +#define MINT12_13PL 0xFFFF +#endif + +#if (INT14PL >= INT12PL) || (INT14PL == 0) +#define MINT12_14PL ~(1 << 13) +#else +#define MINT12_14PL 0xFFFF +#endif + +#if (INT15PL >= INT12PL) || (INT15PL == 0) +#define MINT12_15PL ~(1 << 14) +#else +#define MINT12_15PL 0xFFFF +#endif + +#if (INT16PL >= INT12PL) || (INT16PL == 0) +#define MINT12_16PL ~(1 << 15) +#else +#define MINT12_16PL 0xFFFF +#endif + +#define MINT12 (MINT12_1PL & MINT12_2PL & MINT12_3PL & MINT12_4PL & \ + MINT12_5PL & MINT12_6PL & MINT12_7PL & MINT12_8PL & \ + MINT12_9PL & MINT12_10PL & MINT12_11PL & MINT12_12PL & \ + MINT12_13PL & MINT12_14PL & MINT12_15PL & MINT12_16PL) +// End Of MINT12. + +// Beginning of MINT13: +#if (INT1PL >= INT13PL) || (INT1PL == 0) +#define MINT13_1PL ~(1 << 0) +#else +#define MINT13_1PL 0xFFFF +#endif + +#if (INT2PL >= INT13PL) || (INT2PL == 0) +#define MINT13_2PL ~(1 << 1) +#else +#define MINT13_2PL 0xFFFF +#endif + +#if (INT3PL >= INT13PL) || (INT3PL == 0) +#define MINT13_3PL ~(1 << 2) +#else +#define MINT13_3PL 0xFFFF +#endif + +#if (INT4PL >= INT13PL) || (INT4PL == 0) +#define MINT13_4PL ~(1 << 3) +#else +#define MINT13_4PL 0xFFFF +#endif + +#if (INT5PL >= INT13PL) || (INT5PL == 0) +#define MINT13_5PL ~(1 << 4) +#else +#define MINT13_5PL 0xFFFF +#endif + +#if (INT6PL >= INT13PL) || (INT6PL == 0) +#define MINT13_6PL ~(1 << 5) +#else +#define MINT13_6PL 0xFFFF +#endif + +#if (INT7PL >= INT13PL) || (INT7PL == 0) +#define MINT13_7PL ~(1 << 6) +#else +#define MINT13_7PL 0xFFFF +#endif + +#if (INT8PL >= INT13PL) || (INT8PL == 0) +#define MINT13_8PL ~(1 << 7) +#else +#define MINT13_8PL 0xFFFF +#endif + +#if (INT9PL >= INT13PL) || (INT9PL == 0) +#define MINT13_9PL ~(1 << 8) +#else +#define MINT13_9PL 0xFFFF +#endif + +#if (INT10PL >= INT13PL) || (INT10PL == 0) +#define MINT13_10PL ~(1 << 9) +#else +#define MINT13_10PL 0xFFFF +#endif + +#if (INT11PL >= INT13PL) || (INT11PL == 0) +#define MINT13_11PL ~(1 << 10) +#else +#define MINT13_11PL 0xFFFF +#endif + +#define MINT13_12PL ~(1 << 11) + +#if (INT13PL == 0) +#define MINT13_13PL ~(1 << 12) +#else +#define MINT13_13PL 0xFFFF +#endif + +#if (INT14PL >= INT13PL) || (INT14PL == 0) +#define MINT13_14PL ~(1 << 13) +#else +#define MINT13_14PL 0xFFFF +#endif + +#if (INT15PL >= INT13PL) || (INT15PL == 0) +#define MINT13_15PL ~(1 << 14) +#else +#define MINT13_15PL 0xFFFF +#endif + +#if (INT16PL >= INT13PL) || (INT16PL == 0) +#define MINT13_16PL ~(1 << 15) +#else +#define MINT13_16PL 0xFFFF +#endif + +#define MINT13 (MINT13_1PL & MINT13_2PL & MINT13_3PL & MINT13_4PL & \ + MINT13_5PL & MINT13_6PL & MINT13_7PL & MINT13_8PL & \ + MINT13_9PL & MINT13_10PL & MINT13_11PL & MINT13_12PL & \ + MINT13_13PL & MINT13_14PL & MINT13_15PL & MINT13_16PL) +// End Of MINT13. + +// Beginning of MINT14: +#if (INT1PL >= INT14PL) || (INT1PL == 0) +#define MINT14_1PL ~(1 << 0) +#else +#define MINT14_1PL 0xFFFF +#endif + +#if (INT2PL >= INT14PL) || (INT2PL == 0) +#define MINT14_2PL ~(1 << 1) +#else +#define MINT14_2PL 0xFFFF +#endif + +#if (INT3PL >= INT14PL) || (INT3PL == 0) +#define MINT14_3PL ~(1 << 2) +#else +#define MINT14_3PL 0xFFFF +#endif + +#if (INT4PL >= INT14PL) || (INT4PL == 0) +#define MINT14_4PL ~(1 << 3) +#else +#define MINT14_4PL 0xFFFF +#endif + +#if (INT5PL >= INT14PL) || (INT5PL == 0) +#define MINT14_5PL ~(1 << 4) +#else +#define MINT14_5PL 0xFFFF +#endif + +#if (INT6PL >= INT14PL) || (INT6PL == 0) +#define MINT14_6PL ~(1 << 5) +#else +#define MINT14_6PL 0xFFFF +#endif + +#if (INT7PL >= INT14PL) || (INT7PL == 0) +#define MINT14_7PL ~(1 << 6) +#else +#define MINT14_7PL 0xFFFF +#endif + +#if (INT8PL >= INT14PL) || (INT8PL == 0) +#define MINT14_8PL ~(1 << 7) +#else +#define MINT14_8PL 0xFFFF +#endif + +#if (INT9PL >= INT14PL) || (INT9PL == 0) +#define MINT14_9PL ~(1 << 8) +#else +#define MINT14_9PL 0xFFFF +#endif + +#if (INT10PL >= INT14PL) || (INT10PL == 0) +#define MINT14_10PL ~(1 << 9) +#else +#define MINT14_10PL 0xFFFF +#endif + +#if (INT11PL >= INT14PL) || (INT11PL == 0) +#define MINT14_11PL ~(1 << 10) +#else +#define MINT14_11PL 0xFFFF +#endif + +#if (INT12PL >= INT14PL) || (INT12PL == 0) +#define MINT14_12PL ~(1 << 11) +#else +#define MINT14_12PL 0xFFFF +#endif + +#if (INT13PL >= INT14PL) || (INT13PL == 0) +#define MINT14_13PL ~(1 << 12) +#else +#define MINT14_13PL 0xFFFF +#endif + +#define MINT14_14PL ~(1 << 13) + +#if (INT15PL >= INT14PL) || (INT15PL == 0) +#define MINT14_15PL ~(1 << 14) +#else +#define MINT14_15PL 0xFFFF +#endif + +#if (INT16PL >= INT14PL) || (INT16PL == 0) +#define MINT14_16PL ~(1 << 15) +#else +#define MINT14_16PL 0xFFFF +#endif + +#define MINT14 (MINT14_1PL & MINT14_2PL & MINT14_3PL & MINT14_4PL & \ + MINT14_5PL & MINT14_6PL & MINT14_7PL & MINT14_8PL & \ + MINT14_9PL & MINT14_10PL & MINT14_11PL & MINT14_12PL & \ + MINT14_13PL & MINT14_14PL & MINT14_15PL & MINT14_16PL) +// End Of MINT14. + +// Beginning of MINT15: +#if (INT1PL >= INT15PL) || (INT1PL == 0) +#define MINT15_1PL ~(1 << 0) +#else +#define MINT15_1PL 0xFFFF +#endif + +#if (INT2PL >= INT15PL) || (INT2PL == 0) +#define MINT15_2PL ~(1 << 1) +#else +#define MINT15_2PL 0xFFFF +#endif + +#if (INT3PL >= INT15PL) || (INT3PL == 0) +#define MINT15_3PL ~(1 << 2) +#else +#define MINT15_3PL 0xFFFF +#endif + +#if (INT4PL >= INT15PL) || (INT4PL == 0) +#define MINT15_4PL ~(1 << 3) +#else +#define MINT15_4PL 0xFFFF +#endif + +#if (INT5PL >= INT15PL) || (INT5PL == 0) +#define MINT15_5PL ~(1 << 4) +#else +#define MINT15_5PL 0xFFFF +#endif + +#if (INT6PL >= INT15PL) || (INT6PL == 0) +#define MINT15_6PL ~(1 << 5) +#else +#define MINT15_6PL 0xFFFF +#endif + +#if (INT7PL >= INT15PL) || (INT7PL == 0) +#define MINT15_7PL ~(1 << 6) +#else +#define MINT15_7PL 0xFFFF +#endif + +#if (INT8PL >= INT15PL) || (INT8PL == 0) +#define MINT15_8PL ~(1 << 7) +#else +#define MINT15_8PL 0xFFFF +#endif + +#if (INT9PL >= INT15PL) || (INT9PL == 0) +#define MINT15_9PL ~(1 << 8) +#else +#define MINT15_9PL 0xFFFF +#endif + +#if (INT10PL >= INT15PL) || (INT10PL == 0) +#define MINT15_10PL ~(1 << 9) +#else +#define MINT15_10PL 0xFFFF +#endif + +#if (INT11PL >= INT15PL) || (INT11PL == 0) +#define MINT15_11PL ~(1 << 10) +#else +#define MINT15_11PL 0xFFFF +#endif + +#if (INT12PL >= INT15PL) || (INT12PL == 0) +#define MINT15_12PL ~(1 << 11) +#else +#define MINT15_12PL 0xFFFF +#endif + +#if (INT13PL >= INT15PL) || (INT13PL == 0) +#define MINT15_13PL ~(1 << 12) +#else +#define MINT15_13PL 0xFFFF +#endif + +#if (INT14PL >= INT15PL) || (INT14PL == 0) +#define MINT15_14PL ~(1 << 13) +#else +#define MINT15_14PL 0xFFFF +#endif + +#define MINT15_15PL ~(1 << 14) + +#if (INT16PL >= INT15PL) || (INT16PL == 0) +#define MINT15_16PL ~(1 << 15) +#else +#define MINT15_16PL 0xFFFF +#endif + +#define MINT15 (MINT15_1PL & MINT15_2PL & MINT15_3PL & MINT15_4PL & \ + MINT15_5PL & MINT15_6PL & MINT15_7PL & MINT15_8PL & \ + MINT15_9PL & MINT15_10PL & MINT15_11PL & MINT15_12PL & \ + MINT15_13PL & MINT15_14PL & MINT15_15PL & MINT15_16PL) +// End Of MINT15. + +// Beginning of MINT16: +#if (INT1PL >= INT16PL) || (INT1PL == 0) +#define MINT16_1PL ~(1 << 0) +#else +#define MINT16_1PL 0xFFFF +#endif + +#if (INT2PL >= INT16PL) || (INT2PL == 0) +#define MINT16_2PL ~(1 << 1) +#else +#define MINT16_2PL 0xFFFF +#endif + +#if (INT3PL >= INT16PL) || (INT3PL == 0) +#define MINT16_3PL ~(1 << 2) +#else +#define MINT16_3PL 0xFFFF +#endif + +#if (INT4PL >= INT16PL) || (INT4PL == 0) +#define MINT16_4PL ~(1 << 3) +#else +#define MINT16_4PL 0xFFFF +#endif + +#if (INT5PL >= INT16PL) || (INT5PL == 0) +#define MINT16_5PL ~(1 << 4) +#else +#define MINT16_5PL 0xFFFF +#endif + +#if (INT6PL >= INT16PL) || (INT6PL == 0) +#define MINT16_6PL ~(1 << 5) +#else +#define MINT16_6PL 0xFFFF +#endif + +#if (INT7PL >= INT16PL) || (INT7PL == 0) +#define MINT16_7PL ~(1 << 6) +#else +#define MINT16_7PL 0xFFFF +#endif + +#if (INT8PL >= INT16PL) || (INT8PL == 0) +#define MINT16_8PL ~(1 << 7) +#else +#define MINT16_8PL 0xFFFF +#endif + +#if (INT9PL >= INT16PL) || (INT9PL == 0) +#define MINT16_9PL ~(1 << 8) +#else +#define MINT16_9PL 0xFFFF +#endif + +#if (INT10PL >= INT16PL) || (INT10PL == 0) +#define MINT16_10PL ~(1 << 9) +#else +#define MINT16_10PL 0xFFFF +#endif + +#if (INT11PL >= INT16PL) || (INT11PL == 0) +#define MINT16_11PL ~(1 << 10) +#else +#define MINT16_11PL 0xFFFF +#endif + +#if (INT12PL >= INT16PL) || (INT12PL == 0) +#define MINT16_12PL ~(1 << 11) +#else +#define MINT16_12PL 0xFFFF +#endif + +#if (INT13PL >= INT16PL) || (INT13PL == 0) +#define MINT16_13PL ~(1 << 12) +#else +#define MINT16_13PL 0xFFFF +#endif + +#if (INT14PL >= INT16PL) || (INT14PL == 0) +#define MINT16_14PL ~(1 << 13) +#else +#define MINT16_14PL 0xFFFF +#endif + +#if (INT15PL >= INT16PL) || (INT15PL == 0) +#define MINT16_15PL ~(1 << 14) +#else +#define MINT16_15PL 0xFFFF +#endif + +#define MINT16_16PL ~(1 << 15) + +#define MINT16 (MINT16_1PL & MINT16_2PL & MINT16_3PL & MINT16_4PL & \ + MINT16_5PL & MINT16_6PL & MINT16_7PL & MINT16_8PL & \ + MINT16_9PL & MINT16_10PL & MINT16_11PL & MINT16_12PL & \ + MINT16_13PL & MINT16_14PL & MINT16_15PL & MINT16_16PL) +// End Of MINT16. + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG11 to MG18: + +// Beginning of MG11: +#if (G12PL >= G11PL) || (G12PL == 0) +#define MG11_12PL ~(1 << 1) +#else +#define MG11_12PL 0xFFFF +#endif + +#if (G13PL >= G11PL) || (G13PL == 0) +#define MG11_13PL ~(1 << 2) +#else +#define MG11_13PL 0xFFFF +#endif + +#if (G14PL >= G11PL) || (G14PL == 0) +#define MG11_14PL ~(1 << 3) +#else +#define MG11_14PL 0xFFFF +#endif + +#if (G15PL >= G11PL) || (G15PL == 0) +#define MG11_15PL ~(1 << 4) +#else +#define MG11_15PL 0xFFFF +#endif + +#if (G16PL >= G11PL) || (G16PL == 0) +#define MG11_16PL ~(1 << 5) +#else +#define MG11_16PL 0xFFFF +#endif + +#if (G17PL >= G11PL) || (G17PL == 0) +#define MG11_17PL ~(1 << 6) +#else +#define MG11_17PL 0xFFFF +#endif + +#if (G18PL >= G11PL) || (G18PL == 0) +#define MG11_18PL ~(1 << 7) +#else +#define MG11_18PL 0xFFFF +#endif + +#define MG11_11PL 0x00FE +#define MG11 (MG11_11PL & MG11_12PL & MG11_13PL & MG11_14PL & \ + MG11_15PL & MG11_16PL & MG11_17PL & MG11_18PL) +// End of MG11: + +// Beginning of MG12: +#if (G11PL >= G12PL) || (G11PL == 0) +#define MG12_11PL ~(1) +#else +#define MG12_11PL 0xFFFF +#endif +#if (G13PL >= G12PL) || (G13PL == 0) +#define MG12_13PL ~(1 << 2) +#else +#define MG12_13PL 0xFFFF +#endif +#if (G14PL >= G12PL) || (G14PL == 0) +#define MG12_14PL ~(1 << 3) +#else +#define MG12_14PL 0xFFFF +#endif +#if (G15PL >= G12PL) || (G15PL == 0) +#define MG12_15PL ~(1 << 4) +#else +#define MG12_15PL 0xFFFF +#endif +#if (G16PL >= G12PL) || (G16PL == 0) +#define MG12_16PL ~(1 << 5) +#else +#define MG12_16PL 0xFFFF +#endif +#if (G17PL >= G12PL) || (G17PL == 0) +#define MG12_17PL ~(1 << 6) +#else +#define MG12_17PL 0xFFFF +#endif +#if (G18PL >= G12PL) || (G18PL == 0) +#define MG12_18PL ~(1 << 7) +#else +#define MG12_18PL 0xFFFF +#endif +#define MG12_12PL 0x00FD +#define MG12 (MG12_11PL & MG12_12PL & MG12_13PL & MG12_14PL & \ + MG12_15PL & MG12_16PL & MG12_17PL & MG12_18PL) +// End of MG12: + +// Beginning of MG13: +#if (G11PL >= G13PL) || (G11PL == 0) +#define MG13_11PL ~(1) +#else +#define MG13_11PL 0xFFFF +#endif +#if (G12PL >= G13PL) || (G12PL == 0) +#define MG13_12PL ~(1 << 1) +#else +#define MG13_12PL 0xFFFF +#endif +#if (G14PL >= G13PL) || (G14PL == 0) +#define MG13_14PL ~(1 << 3) +#else +#define MG13_14PL 0xFFFF +#endif +#if (G15PL >= G13PL) || (G15PL == 0) +#define MG13_15PL ~(1 << 4) +#else +#define MG13_15PL 0xFFFF +#endif +#if (G16PL >= G13PL) || (G16PL == 0) +#define MG13_16PL ~(1 << 5) +#else +#define MG13_16PL 0xFFFF +#endif +#if (G17PL >= G13PL) || (G17PL == 0) +#define MG13_17PL ~(1 << 6) +#else +#define MG13_17PL 0xFFFF +#endif +#if (G18PL >= G13PL) || (G18PL == 0) +#define MG13_18PL ~(1 << 7) +#else +#define MG13_18PL 0xFFFF +#endif +#define MG13_13PL 0x00FB +#define MG13 (MG13_11PL & MG13_12PL & MG13_13PL & MG13_14PL & \ + MG13_15PL & MG13_16PL & MG13_17PL & MG13_18PL) +// End of MG13: + +// Beginning of MG14: +#if (G11PL >= G14PL) || (G11PL == 0) +#define MG14_11PL ~(1) +#else +#define MG14_11PL 0xFFFF +#endif +#if (G12PL >= G14PL) || (G12PL == 0) +#define MG14_12PL ~(1 << 1) +#else +#define MG14_12PL 0xFFFF +#endif +#if (G13PL >= G14PL) || (G13PL == 0) +#define MG14_13PL ~(1 << 2) +#else +#define MG14_13PL 0xFFFF +#endif +#if (G15PL >= G14PL) || (G15PL == 0) +#define MG14_15PL ~(1 << 4) +#else +#define MG14_15PL 0xFFFF +#endif +#if (G16PL >= G14PL) || (G16PL == 0) +#define MG14_16PL ~(1 << 5) +#else +#define MG14_16PL 0xFFFF +#endif +#if (G17PL >= G14PL) || (G17PL == 0) +#define MG14_17PL ~(1 << 6) +#else +#define MG14_17PL 0xFFFF +#endif +#if (G18PL >= G14PL) || (G18PL == 0) +#define MG14_18PL ~(1 << 7) +#else +#define MG14_18PL 0xFFFF +#endif +#define MG14_14PL 0x00F7 +#define MG14 (MG14_11PL & MG14_12PL & MG14_13PL & MG14_14PL & \ + MG14_15PL & MG14_16PL & MG14_17PL & MG14_18PL) +// End of MG14: + +// Beginning of MG15: +#if (G11PL >= G15PL) || (G11PL == 0) +#define MG15_11PL ~(1) +#else +#define MG15_11PL 0xFFFF +#endif +#if (G12PL >= G15PL) || (G12PL == 0) +#define MG15_12PL ~(1 << 1) +#else +#define MG15_12PL 0xFFFF +#endif +#if (G13PL >= G15PL) || (G13PL == 0) +#define MG15_13PL ~(1 << 2) +#else +#define MG15_13PL 0xFFFF +#endif +#if (G14PL >= G15PL) || (G14PL == 0) +#define MG15_14PL ~(1 << 3) +#else +#define MG15_14PL 0xFFFF +#endif +#if (G16PL >= G15PL) || (G16PL == 0) +#define MG15_16PL ~(1 << 5) +#else +#define MG15_16PL 0xFFFF +#endif +#if (G17PL >= G15PL) || (G17PL == 0) +#define MG15_17PL ~(1 << 6) +#else +#define MG15_17PL 0xFFFF +#endif +#if (G18PL >= G15PL) || (G18PL == 0) +#define MG15_18PL ~(1 << 7) +#else +#define MG15_18PL 0xFFFF +#endif +#define MG15_15PL 0x00EF +#define MG15 (MG15_11PL & MG15_12PL & MG15_13PL & MG15_14PL & \ + MG15_15PL & MG15_16PL & MG15_17PL & MG15_18PL) +// End of MG15: + +// Beginning of MG16: +#if (G11PL >= G16PL) || (G11PL == 0) +#define MG16_11PL ~(1) +#else +#define MG16_11PL 0xFFFF +#endif +#if (G12PL >= G16PL) || (G12PL == 0) +#define MG16_12PL ~(1 << 1) +#else +#define MG16_12PL 0xFFFF +#endif +#if (G13PL >= G16PL) || (G13PL == 0) +#define MG16_13PL ~(1 << 2) +#else +#define MG16_13PL 0xFFFF +#endif +#if (G14PL >= G16PL) || (G14PL == 0) +#define MG16_14PL ~(1 << 3) +#else +#define MG16_14PL 0xFFFF +#endif +#if (G15PL >= G16PL) || (G15PL == 0) +#define MG16_15PL ~(1 << 4) +#else +#define MG16_15PL 0xFFFF +#endif +#if (G17PL >= G16PL) || (G17PL == 0) +#define MG16_17PL ~(1 << 6) +#else +#define MG16_17PL 0xFFFF +#endif +#if (G18PL >= G16PL) || (G18PL == 0) +#define MG16_18PL ~(1 << 7) +#else +#define MG16_18PL 0xFFFF +#endif +#define MG16_16PL 0x00DF +#define MG16 (MG16_11PL & MG16_12PL & MG16_13PL & MG16_14PL & \ + MG16_15PL & MG16_16PL & MG16_17PL & MG16_18PL) +// End of MG16: + +// Beginning of MG17: +#if (G11PL >= G17PL) || (G11PL == 0) +#define MG17_11PL ~(1) +#else +#define MG17_11PL 0xFFFF +#endif +#if (G12PL >= G17PL) || (G12PL == 0) +#define MG17_12PL ~(1 << 1) +#else +#define MG17_12PL 0xFFFF +#endif +#if (G13PL >= G17PL) || (G13PL == 0) +#define MG17_13PL ~(1 << 2) +#else +#define MG17_13PL 0xFFFF +#endif +#if (G14PL >= G17PL) || (G14PL == 0) +#define MG17_14PL ~(1 << 3) +#else +#define MG17_14PL 0xFFFF +#endif +#if (G15PL >= G17PL) || (G15PL == 0) +#define MG17_15PL ~(1 << 4) +#else +#define MG17_15PL 0xFFFF +#endif +#if (G16PL >= G17PL) || (G16PL == 0) +#define MG17_16PL ~(1 << 5) +#else +#define MG17_16PL 0xFFFF +#endif +#if (G18PL >= G17PL) || (G18PL == 0) +#define MG17_18PL ~(1 << 7) +#else +#define MG17_18PL 0xFFFF +#endif +#define MG17_17PL 0x00BF +#define MG17 (MG17_11PL & MG17_12PL & MG17_13PL & MG17_14PL & \ + MG17_15PL & MG17_16PL & MG17_17PL & MG17_18PL) +// End of MG17: + +// Beginning of MG18: +#if (G11PL >= G18PL) || (G11PL == 0) +#define MG18_11PL ~(1) +#else +#define MG18_11PL 0xFFFF +#endif +#if (G12PL >= G18PL) || (G12PL == 0) +#define MG18_12PL ~(1 << 1) +#else +#define MG18_12PL 0xFFFF +#endif +#if (G13PL >= G18PL) || (G13PL == 0) +#define MG18_13PL ~(1 << 2) +#else +#define MG18_13PL 0xFFFF +#endif +#if (G14PL >= G18PL) || (G14PL == 0) +#define MG18_14PL ~(1 << 3) +#else +#define MG18_14PL 0xFFFF +#endif +#if (G15PL >= G18PL) || (G15PL == 0) +#define MG18_15PL ~(1 << 4) +#else +#define MG18_15PL 0xFFFF +#endif +#if (G16PL >= G18PL) || (G16PL == 0) +#define MG18_16PL ~(1 << 5) +#else +#define MG18_16PL 0xFFFF +#endif +#if (G17PL >= G18PL) || (G17PL == 0) +#define MG18_17PL ~(1 << 6) +#else +#define MG18_17PL 0xFFFF +#endif +#define MG18_18PL 0x007F +#define MG18 (MG18_11PL & MG18_12PL & MG18_13PL & MG18_14PL & \ + MG18_15PL & MG18_16PL & MG18_17PL & MG18_18PL) +// End of MG18: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG21 to MG28: +// + +// Beginning of MG21: +#if (G22PL >= G21PL) || (G22PL == 0) +#define MG21_12PL ~(1 << 1) +#else +#define MG21_12PL 0xFFFF +#endif +#if (G23PL >= G21PL) || (G23PL == 0) +#define MG21_13PL ~(1 << 2) +#else +#define MG21_13PL 0xFFFF +#endif +#if (G24PL >= G21PL) || (G24PL == 0) +#define MG21_14PL ~(1 << 3) +#else +#define MG21_14PL 0xFFFF +#endif +#if (G25PL >= G21PL) || (G25PL == 0) +#define MG21_15PL ~(1 << 4) +#else +#define MG21_15PL 0xFFFF +#endif +#if (G26PL >= G21PL) || (G26PL == 0) +#define MG21_16PL ~(1 << 5) +#else +#define MG21_16PL 0xFFFF +#endif +#if (G27PL >= G21PL) || (G27PL == 0) +#define MG21_17PL ~(1 << 6) +#else +#define MG21_17PL 0xFFFF +#endif +#if (G28PL >= G21PL) || (G28PL == 0) +#define MG21_18PL ~(1 << 7) +#else +#define MG21_18PL 0xFFFF +#endif +#define MG21_11PL 0x00FE +#define MG21 (MG21_11PL & MG21_12PL & MG21_13PL & MG21_14PL & \ + MG21_15PL & MG21_16PL & MG21_17PL & MG21_18PL) +// End of MG21: + +// Beginning of MG22: +#if (G21PL >= G22PL) || (G21PL == 0) +#define MG22_11PL ~(1) +#else +#define MG22_11PL 0xFFFF +#endif +#if (G23PL >= G22PL) || (G23PL == 0) +#define MG22_13PL ~(1 << 2) +#else +#define MG22_13PL 0xFFFF +#endif +#if (G24PL >= G22PL) || (G24PL == 0) +#define MG22_14PL ~(1 << 3) +#else +#define MG22_14PL 0xFFFF +#endif +#if (G25PL >= G22PL) || (G25PL == 0) +#define MG22_15PL ~(1 << 4) +#else +#define MG22_15PL 0xFFFF +#endif +#if (G26PL >= G22PL) || (G26PL == 0) +#define MG22_16PL ~(1 << 5) +#else +#define MG22_16PL 0xFFFF +#endif +#if (G27PL >= G22PL) || (G27PL == 0) +#define MG22_17PL ~(1 << 6) +#else +#define MG22_17PL 0xFFFF +#endif +#if (G28PL >= G22PL) || (G28PL == 0) +#define MG22_18PL ~(1 << 7) +#else +#define MG22_18PL 0xFFFF +#endif +#define MG22_12PL 0x00FD +#define MG22 (MG22_11PL & MG22_12PL & MG22_13PL & MG22_14PL & \ + MG22_15PL & MG22_16PL & MG22_17PL & MG22_18PL) +// End of MG22: + +// Beginning of MG23: +#if (G21PL >= G23PL) || (G21PL == 0) +#define MG23_11PL ~(1) +#else +#define MG23_11PL 0xFFFF +#endif +#if (G22PL >= G23PL) || (G22PL == 0) +#define MG23_12PL ~(1 << 1) +#else +#define MG23_12PL 0xFFFF +#endif +#if (G24PL >= G23PL) || (G24PL == 0) +#define MG23_14PL ~(1 << 3) +#else +#define MG23_14PL 0xFFFF +#endif +#if (G25PL >= G23PL) || (G25PL == 0) +#define MG23_15PL ~(1 << 4) +#else +#define MG23_15PL 0xFFFF +#endif +#if (G26PL >= G23PL) || (G26PL == 0) +#define MG23_16PL ~(1 << 5) +#else +#define MG23_16PL 0xFFFF +#endif +#if (G27PL >= G23PL) || (G27PL == 0) +#define MG23_17PL ~(1 << 6) +#else +#define MG23_17PL 0xFFFF +#endif +#if (G28PL >= G23PL) || (G28PL == 0) +#define MG23_18PL ~(1 << 7) +#else +#define MG23_18PL 0xFFFF +#endif +#define MG23_13PL 0x00FB +#define MG23 (MG23_11PL & MG23_12PL & MG23_13PL & MG23_14PL & \ + MG23_15PL & MG23_16PL & MG23_17PL & MG23_18PL) +// End of MG23: + +// Beginning of MG24: +#if (G21PL >= G24PL) || (G21PL == 0) +#define MG24_11PL ~(1) +#else +#define MG24_11PL 0xFFFF +#endif +#if (G22PL >= G24PL) || (G22PL == 0) +#define MG24_12PL ~(1 << 1) +#else +#define MG24_12PL 0xFFFF +#endif +#if (G23PL >= G24PL) || (G23PL == 0) +#define MG24_13PL ~(1 << 2) +#else +#define MG24_13PL 0xFFFF +#endif +#if (G25PL >= G24PL) || (G25PL == 0) +#define MG24_15PL ~(1 << 4) +#else +#define MG24_15PL 0xFFFF +#endif +#if (G26PL >= G24PL) || (G26PL == 0) +#define MG24_16PL ~(1 << 5) +#else +#define MG24_16PL 0xFFFF +#endif +#if (G27PL >= G24PL) || (G27PL == 0) +#define MG24_17PL ~(1 << 6) +#else +#define MG24_17PL 0xFFFF +#endif +#if (G28PL >= G24PL) || (G28PL == 0) +#define MG24_18PL ~(1 << 7) +#else +#define MG24_18PL 0xFFFF +#endif +#define MG24_14PL 0x00F7 +#define MG24 (MG24_11PL & MG24_12PL & MG24_13PL & MG24_14PL & \ + MG24_15PL & MG24_16PL & MG24_17PL & MG24_18PL) +// End of MG24: + +// Beginning of MG25: +#if (G21PL >= G25PL) || (G21PL == 0) +#define MG25_11PL ~(1) +#else +#define MG25_11PL 0xFFFF +#endif +#if (G22PL >= G25PL) || (G22PL == 0) +#define MG25_12PL ~(1 << 1) +#else +#define MG25_12PL 0xFFFF +#endif +#if (G23PL >= G25PL) || (G23PL == 0) +#define MG25_13PL ~(1 << 2) +#else +#define MG25_13PL 0xFFFF +#endif +#if (G24PL >= G25PL) || (G24PL == 0) +#define MG25_14PL ~(1 << 3) +#else +#define MG25_14PL 0xFFFF +#endif +#if (G26PL >= G25PL) || (G26PL == 0) +#define MG25_16PL ~(1 << 5) +#else +#define MG25_16PL 0xFFFF +#endif +#if (G27PL >= G25PL) || (G27PL == 0) +#define MG25_17PL ~(1 << 6) +#else +#define MG25_17PL 0xFFFF +#endif +#if (G28PL >= G25PL) || (G28PL == 0) +#define MG25_18PL ~(1 << 7) +#else +#define MG25_18PL 0xFFFF +#endif +#define MG25_15PL 0x00EF +#define MG25 (MG25_11PL & MG25_12PL & MG25_13PL & MG25_14PL & \ + MG25_15PL & MG25_16PL & MG25_17PL & MG25_18PL) +// End of MG25: + +// Beginning of MG26: +#if (G21PL >= G26PL) || (G21PL == 0) +#define MG26_11PL ~(1) +#else +#define MG26_11PL 0xFFFF +#endif +#if (G22PL >= G26PL) || (G22PL == 0) +#define MG26_12PL ~(1 << 1) +#else +#define MG26_12PL 0xFFFF +#endif +#if (G23PL >= G26PL) || (G23PL == 0) +#define MG26_13PL ~(1 << 2) +#else +#define MG26_13PL 0xFFFF +#endif +#if (G24PL >= G26PL) || (G24PL == 0) +#define MG26_14PL ~(1 << 3) +#else +#define MG26_14PL 0xFFFF +#endif +#if (G25PL >= G26PL) || (G25PL == 0) +#define MG26_15PL ~(1 << 4) +#else +#define MG26_15PL 0xFFFF +#endif +#if (G27PL >= G26PL) || (G27PL == 0) +#define MG26_17PL ~(1 << 6) +#else +#define MG26_17PL 0xFFFF +#endif +#if (G28PL >= G26PL) || (G28PL == 0) +#define MG26_18PL ~(1 << 7) +#else +#define MG26_18PL 0xFFFF +#endif +#define MG26_16PL 0x00DF +#define MG26 (MG26_11PL & MG26_12PL & MG26_13PL & MG26_14PL & \ + MG26_15PL & MG26_16PL & MG26_17PL & MG26_18PL) +// End of MG26: + +// Beginning of MG27: +#if (G21PL >= G27PL) || (G21PL == 0) +#define MG27_11PL ~(1) +#else +#define MG27_11PL 0xFFFF +#endif +#if (G22PL >= G27PL) || (G22PL == 0) +#define MG27_12PL ~(1 << 1) +#else +#define MG27_12PL 0xFFFF +#endif +#if (G23PL >= G27PL) || (G23PL == 0) +#define MG27_13PL ~(1 << 2) +#else +#define MG27_13PL 0xFFFF +#endif +#if (G24PL >= G27PL) || (G24PL == 0) +#define MG27_14PL ~(1 << 3) +#else +#define MG27_14PL 0xFFFF +#endif +#if (G25PL >= G27PL) || (G25PL == 0) +#define MG27_15PL ~(1 << 4) +#else +#define MG27_15PL 0xFFFF +#endif +#if (G26PL >= G27PL) || (G26PL == 0) +#define MG27_16PL ~(1 << 5) +#else +#define MG27_16PL 0xFFFF +#endif +#if (G28PL >= G27PL) || (G28PL == 0) +#define MG27_18PL ~(1 << 7) +#else +#define MG27_18PL 0xFFFF +#endif +#define MG27_17PL 0x00BF +#define MG27 (MG27_11PL & MG27_12PL & MG27_13PL & MG27_14PL & \ + MG27_15PL & MG27_16PL & MG27_17PL & MG27_18PL) +// End of MG27: + +// Beginning of MG28: +#if (G21PL >= G28PL) || (G21PL == 0) +#define MG28_11PL ~(1) +#else +#define MG28_11PL 0xFFFF +#endif +#if (G22PL >= G28PL) || (G22PL == 0) +#define MG28_12PL ~(1 << 1) +#else +#define MG28_12PL 0xFFFF +#endif +#if (G23PL >= G28PL) || (G23PL == 0) +#define MG28_13PL ~(1 << 2) +#else +#define MG28_13PL 0xFFFF +#endif +#if (G24PL >= G28PL) || (G24PL == 0) +#define MG28_14PL ~(1 << 3) +#else +#define MG28_14PL 0xFFFF +#endif +#if (G25PL >= G28PL) || (G25PL == 0) +#define MG28_15PL ~(1 << 4) +#else +#define MG28_15PL 0xFFFF +#endif +#if (G26PL >= G28PL) || (G26PL == 0) +#define MG28_16PL ~(1 << 5) +#else +#define MG28_16PL 0xFFFF +#endif +#if (G27PL >= G28PL) || (G27PL == 0) +#define MG28_17PL ~(1 << 6) +#else +#define MG28_17PL 0xFFFF +#endif +#define MG28_18PL 0x007F +#define MG28 (MG28_11PL & MG28_12PL & MG28_13PL & MG28_14PL & \ + MG28_15PL & MG28_16PL & MG28_17PL & MG28_18PL) +// End of MG28: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG31 to MG38: +// + +// Beginning of MG31: +#if (G32PL >= G31PL) || (G32PL == 0) +#define MG31_12PL ~(1 << 1) +#else +#define MG31_12PL 0xFFFF +#endif +#if (G33PL >= G31PL) || (G33PL == 0) +#define MG31_13PL ~(1 << 2) +#else +#define MG31_13PL 0xFFFF +#endif +#if (G34PL >= G31PL) || (G34PL == 0) +#define MG31_14PL ~(1 << 3) +#else +#define MG31_14PL 0xFFFF +#endif +#if (G35PL >= G31PL) || (G35PL == 0) +#define MG31_15PL ~(1 << 4) +#else +#define MG31_15PL 0xFFFF +#endif +#if (G36PL >= G31PL) || (G36PL == 0) +#define MG31_16PL ~(1 << 5) +#else +#define MG31_16PL 0xFFFF +#endif +#if (G37PL >= G31PL) || (G37PL == 0) +#define MG31_17PL ~(1 << 6) +#else +#define MG31_17PL 0xFFFF +#endif +#if (G38PL >= G31PL) || (G38PL == 0) +#define MG31_18PL ~(1 << 7) +#else +#define MG31_18PL 0xFFFF +#endif +#define MG31_11PL 0x00FE +#define MG31 (MG31_11PL & MG31_12PL & MG31_13PL & MG31_14PL & \ + MG31_15PL & MG31_16PL & MG31_17PL & MG31_18PL) +// End of MG31: + +// Beginning of MG32: +#if (G31PL >= G32PL) || (G31PL == 0) +#define MG32_11PL ~(1) +#else +#define MG32_11PL 0xFFFF +#endif +#if (G33PL >= G32PL) || (G33PL == 0) +#define MG32_13PL ~(1 << 2) +#else +#define MG32_13PL 0xFFFF +#endif +#if (G34PL >= G32PL) || (G34PL == 0) +#define MG32_14PL ~(1 << 3) +#else +#define MG32_14PL 0xFFFF +#endif +#if (G35PL >= G32PL) || (G35PL == 0) +#define MG32_15PL ~(1 << 4) +#else +#define MG32_15PL 0xFFFF +#endif +#if (G36PL >= G32PL) || (G36PL == 0) +#define MG32_16PL ~(1 << 5) +#else +#define MG32_16PL 0xFFFF +#endif +#if (G37PL >= G32PL) || (G37PL == 0) +#define MG32_17PL ~(1 << 6) +#else +#define MG32_17PL 0xFFFF +#endif +#if (G38PL >= G32PL) || (G38PL == 0) +#define MG32_18PL ~(1 << 7) +#else +#define MG32_18PL 0xFFFF +#endif +#define MG32_12PL 0x00FD +#define MG32 (MG32_11PL & MG32_12PL & MG32_13PL & MG32_14PL & \ + MG32_15PL & MG32_16PL & MG32_17PL & MG32_18PL) +// End of MG32: + +// Beginning of MG33: +#if (G31PL >= G33PL) || (G31PL == 0) +#define MG33_11PL ~(1) +#else +#define MG33_11PL 0xFFFF +#endif +#if (G32PL >= G33PL) || (G32PL == 0) +#define MG33_12PL ~(1 << 1) +#else +#define MG33_12PL 0xFFFF +#endif +#if (G34PL >= G33PL) || (G34PL == 0) +#define MG33_14PL ~(1 << 3) +#else +#define MG33_14PL 0xFFFF +#endif +#if (G35PL >= G33PL) || (G35PL == 0) +#define MG33_15PL ~(1 << 4) +#else +#define MG33_15PL 0xFFFF +#endif +#if (G36PL >= G33PL) || (G36PL == 0) +#define MG33_16PL ~(1 << 5) +#else +#define MG33_16PL 0xFFFF +#endif +#if (G37PL >= G33PL) || (G37PL == 0) +#define MG33_17PL ~(1 << 6) +#else +#define MG33_17PL 0xFFFF +#endif +#if (G38PL >= G33PL) || (G38PL == 0) +#define MG33_18PL ~(1 << 7) +#else +#define MG33_18PL 0xFFFF +#endif +#define MG33_13PL 0x00FB +#define MG33 (MG33_11PL & MG33_12PL & MG33_13PL & MG33_14PL & \ + MG33_15PL & MG33_16PL & MG33_17PL & MG33_18PL) +// End of MG33: + +// Beginning of MG34: +#if (G31PL >= G34PL) || (G31PL == 0) +#define MG34_11PL ~(1) +#else +#define MG34_11PL 0xFFFF +#endif +#if (G32PL >= G34PL) || (G32PL == 0) +#define MG34_12PL ~(1 << 1) +#else +#define MG34_12PL 0xFFFF +#endif +#if (G33PL >= G34PL) || (G33PL == 0) +#define MG34_13PL ~(1 << 2) +#else +#define MG34_13PL 0xFFFF +#endif +#if (G35PL >= G34PL) || (G35PL == 0) +#define MG34_15PL ~(1 << 4) +#else +#define MG34_15PL 0xFFFF +#endif +#if (G36PL >= G34PL) || (G36PL == 0) +#define MG34_16PL ~(1 << 5) +#else +#define MG34_16PL 0xFFFF +#endif +#if (G37PL >= G34PL) || (G37PL == 0) +#define MG34_17PL ~(1 << 6) +#else +#define MG34_17PL 0xFFFF +#endif +#if (G38PL >= G34PL) || (G38PL == 0) +#define MG34_18PL ~(1 << 7) +#else +#define MG34_18PL 0xFFFF +#endif +#define MG34_14PL 0x00F7 +#define MG34 (MG34_11PL & MG34_12PL & MG34_13PL & MG34_14PL & \ + MG34_15PL & MG34_16PL & MG34_17PL & MG34_18PL) +// End of MG34: + +// Beginning of MG35: +#if (G31PL >= G35PL) || (G31PL == 0) +#define MG35_11PL ~(1) +#else +#define MG35_11PL 0xFFFF +#endif +#if (G32PL >= G35PL) || (G32PL == 0) +#define MG35_12PL ~(1 << 1) +#else +#define MG35_12PL 0xFFFF +#endif +#if (G33PL >= G35PL) || (G33PL == 0) +#define MG35_13PL ~(1 << 2) +#else +#define MG35_13PL 0xFFFF +#endif +#if (G34PL >= G35PL) || (G34PL == 0) +#define MG35_14PL ~(1 << 3) +#else +#define MG35_14PL 0xFFFF +#endif +#if (G36PL >= G35PL) || (G36PL == 0) +#define MG35_16PL ~(1 << 5) +#else +#define MG35_16PL 0xFFFF +#endif +#if (G37PL >= G35PL) || (G37PL == 0) +#define MG35_17PL ~(1 << 6) +#else +#define MG35_17PL 0xFFFF +#endif +#if (G38PL >= G35PL) || (G38PL == 0) +#define MG35_18PL ~(1 << 7) +#else +#define MG35_18PL 0xFFFF +#endif +#define MG35_15PL 0x00EF +#define MG35 (MG35_11PL & MG35_12PL & MG35_13PL & MG35_14PL & \ + MG35_15PL & MG35_16PL & MG35_17PL & MG35_18PL) +// End of MG35: + +// Beginning of MG36: +#if (G31PL >= G36PL) || (G31PL == 0) +#define MG36_11PL ~(1) +#else +#define MG36_11PL 0xFFFF +#endif +#if (G32PL >= G36PL) || (G32PL == 0) +#define MG36_12PL ~(1 << 1) +#else +#define MG36_12PL 0xFFFF +#endif +#if (G33PL >= G36PL) || (G33PL == 0) +#define MG36_13PL ~(1 << 2) +#else +#define MG36_13PL 0xFFFF +#endif +#if (G34PL >= G36PL) || (G34PL == 0) +#define MG36_14PL ~(1 << 3) +#else +#define MG36_14PL 0xFFFF +#endif +#if (G35PL >= G36PL) || (G35PL == 0) +#define MG36_15PL ~(1 << 4) +#else +#define MG36_15PL 0xFFFF +#endif +#if (G37PL >= G36PL) || (G37PL == 0) +#define MG36_17PL ~(1 << 6) +#else +#define MG36_17PL 0xFFFF +#endif +#if (G38PL >= G36PL) || (G38PL == 0) +#define MG36_18PL ~(1 << 7) +#else +#define MG36_18PL 0xFFFF +#endif +#define MG36_16PL 0x00DF +#define MG36 (MG36_11PL & MG36_12PL & MG36_13PL & MG36_14PL & \ + MG36_15PL & MG36_16PL & MG36_17PL & MG36_18PL) +// End of MG36: + +// Beginning of MG37: +#if (G31PL >= G37PL) || (G31PL == 0) +#define MG37_11PL ~(1) +#else +#define MG37_11PL 0xFFFF +#endif +#if (G32PL >= G37PL) || (G32PL == 0) +#define MG37_12PL ~(1 << 1) +#else +#define MG37_12PL 0xFFFF +#endif +#if (G33PL >= G37PL) || (G33PL == 0) +#define MG37_13PL ~(1 << 2) +#else +#define MG37_13PL 0xFFFF +#endif +#if (G34PL >= G37PL) || (G34PL == 0) +#define MG37_14PL ~(1 << 3) +#else +#define MG37_14PL 0xFFFF +#endif +#if (G35PL >= G37PL) || (G35PL == 0) +#define MG37_15PL ~(1 << 4) +#else +#define MG37_15PL 0xFFFF +#endif +#if (G36PL >= G37PL) || (G36PL == 0) +#define MG37_16PL ~(1 << 5) +#else +#define MG37_16PL 0xFFFF +#endif +#if (G38PL >= G37PL) || (G38PL == 0) +#define MG37_18PL ~(1 << 7) +#else +#define MG37_18PL 0xFFFF +#endif +#define MG37_17PL 0x00BF +#define MG37 (MG37_11PL & MG37_12PL & MG37_13PL & MG37_14PL & \ + MG37_15PL & MG37_16PL & MG37_17PL & MG37_18PL) +// End of MG37: + +// Beginning of MG38: +#if (G31PL >= G38PL) || (G31PL == 0) +#define MG38_11PL ~(1) +#else +#define MG38_11PL 0xFFFF +#endif +#if (G32PL >= G38PL) || (G32PL == 0) +#define MG38_12PL ~(1 << 1) +#else +#define MG38_12PL 0xFFFF +#endif +#if (G33PL >= G38PL) || (G33PL == 0) +#define MG38_13PL ~(1 << 2) +#else +#define MG38_13PL 0xFFFF +#endif +#if (G34PL >= G38PL) || (G34PL == 0) +#define MG38_14PL ~(1 << 3) +#else +#define MG38_14PL 0xFFFF +#endif +#if (G35PL >= G38PL) || (G35PL == 0) +#define MG38_15PL ~(1 << 4) +#else +#define MG38_15PL 0xFFFF +#endif +#if (G36PL >= G38PL) || (G36PL == 0) +#define MG38_16PL ~(1 << 5) +#else +#define MG38_16PL 0xFFFF +#endif +#if (G37PL >= G38PL) || (G37PL == 0) +#define MG38_17PL ~(1 << 6) +#else +#define MG38_17PL 0xFFFF +#endif +#define MG38_18PL 0x007F +#define MG38 (MG38_11PL & MG38_12PL & MG38_13PL & MG38_14PL & \ + MG38_15PL & MG38_16PL & MG38_17PL & MG38_18PL) +// End of MG38: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG41 to MG48: +// + +// Beginning of MG41: +#if (G42PL >= G41PL) || (G42PL == 0) +#define MG41_12PL ~(1 << 1) +#else +#define MG41_12PL 0xFFFF +#endif +#if (G43PL >= G41PL) || (G43PL == 0) +#define MG41_13PL ~(1 << 2) +#else +#define MG41_13PL 0xFFFF +#endif +#if (G44PL >= G41PL) || (G44PL == 0) +#define MG41_14PL ~(1 << 3) +#else +#define MG41_14PL 0xFFFF +#endif +#if (G45PL >= G41PL) || (G45PL == 0) +#define MG41_15PL ~(1 << 4) +#else +#define MG41_15PL 0xFFFF +#endif +#if (G46PL >= G41PL) || (G46PL == 0) +#define MG41_16PL ~(1 << 5) +#else +#define MG41_16PL 0xFFFF +#endif +#if (G47PL >= G41PL) || (G47PL == 0) +#define MG41_17PL ~(1 << 6) +#else +#define MG41_17PL 0xFFFF +#endif +#if (G48PL >= G41PL) || (G48PL == 0) +#define MG41_18PL ~(1 << 7) +#else +#define MG41_18PL 0xFFFF +#endif +#define MG41_11PL 0x00FE +#define MG41 (MG41_11PL & MG41_12PL & MG41_13PL & MG41_14PL & \ + MG41_15PL & MG41_16PL & MG41_17PL & MG41_18PL) +// End of MG41: + +// Beginning of MG42: +#if (G41PL >= G42PL) || (G41PL == 0) +#define MG42_11PL ~(1) +#else +#define MG42_11PL 0xFFFF +#endif +#if (G43PL >= G42PL) || (G43PL == 0) +#define MG42_13PL ~(1 << 2) +#else +#define MG42_13PL 0xFFFF +#endif +#if (G44PL >= G42PL) || (G44PL == 0) +#define MG42_14PL ~(1 << 3) +#else +#define MG42_14PL 0xFFFF +#endif +#if (G45PL >= G42PL) || (G45PL == 0) +#define MG42_15PL ~(1 << 4) +#else +#define MG42_15PL 0xFFFF +#endif +#if (G46PL >= G42PL) || (G46PL == 0) +#define MG42_16PL ~(1 << 5) +#else +#define MG42_16PL 0xFFFF +#endif +#if (G47PL >= G42PL) || (G47PL == 0) +#define MG42_17PL ~(1 << 6) +#else +#define MG42_17PL 0xFFFF +#endif +#if (G48PL >= G42PL) || (G48PL == 0) +#define MG42_18PL ~(1 << 7) +#else +#define MG42_18PL 0xFFFF +#endif +#define MG42_12PL 0x00FD +#define MG42 (MG42_11PL & MG42_12PL & MG42_13PL & MG42_14PL & \ + MG42_15PL & MG42_16PL & MG42_17PL & MG42_18PL) +// End of MG42: + +// Beginning of MG43: +#if (G41PL >= G43PL) || (G41PL == 0) +#define MG43_11PL ~(1) +#else +#define MG43_11PL 0xFFFF +#endif +#if (G42PL >= G43PL) || (G42PL == 0) +#define MG43_12PL ~(1 << 1) +#else +#define MG43_12PL 0xFFFF +#endif +#if (G44PL >= G43PL) || (G44PL == 0) +#define MG43_14PL ~(1 << 3) +#else +#define MG43_14PL 0xFFFF +#endif +#if (G45PL >= G43PL) || (G45PL == 0) +#define MG43_15PL ~(1 << 4) +#else +#define MG43_15PL 0xFFFF +#endif +#if (G46PL >= G43PL) || (G46PL == 0) +#define MG43_16PL ~(1 << 5) +#else +#define MG43_16PL 0xFFFF +#endif +#if (G47PL >= G43PL) || (G47PL == 0) +#define MG43_17PL ~(1 << 6) +#else +#define MG43_17PL 0xFFFF +#endif +#if (G48PL >= G43PL) || (G48PL == 0) +#define MG43_18PL ~(1 << 7) +#else +#define MG43_18PL 0xFFFF +#endif +#define MG43_13PL 0x00FB +#define MG43 (MG43_11PL & MG43_12PL & MG43_13PL & MG43_14PL & \ + MG43_15PL & MG43_16PL & MG43_17PL & MG43_18PL) +// End of MG43: + +// Beginning of MG44: +#if (G41PL >= G44PL) || (G41PL == 0) +#define MG44_11PL ~(1) +#else +#define MG44_11PL 0xFFFF +#endif +#if (G42PL >= G44PL) || (G42PL == 0) +#define MG44_12PL ~(1 << 1) +#else +#define MG44_12PL 0xFFFF +#endif +#if (G43PL >= G44PL) || (G43PL == 0) +#define MG44_13PL ~(1 << 2) +#else +#define MG44_13PL 0xFFFF +#endif +#if (G45PL >= G44PL) || (G45PL == 0) +#define MG44_15PL ~(1 << 4) +#else +#define MG44_15PL 0xFFFF +#endif +#if (G46PL >= G44PL) || (G46PL == 0) +#define MG44_16PL ~(1 << 5) +#else +#define MG44_16PL 0xFFFF +#endif +#if (G47PL >= G44PL) || (G47PL == 0) +#define MG44_17PL ~(1 << 6) +#else +#define MG44_17PL 0xFFFF +#endif +#if (G48PL >= G44PL) || (G48PL == 0) +#define MG44_18PL ~(1 << 7) +#else +#define MG44_18PL 0xFFFF +#endif +#define MG44_14PL 0x00F7 +#define MG44 (MG44_11PL & MG44_12PL & MG44_13PL & MG44_14PL & \ + MG44_15PL & MG44_16PL & MG44_17PL & MG44_18PL) +// End of MG44: + +// Beginning of MG45: +#if (G41PL >= G45PL) || (G41PL == 0) +#define MG45_11PL ~(1) +#else +#define MG45_11PL 0xFFFF +#endif +#if (G42PL >= G45PL) || (G42PL == 0) +#define MG45_12PL ~(1 << 1) +#else +#define MG45_12PL 0xFFFF +#endif +#if (G43PL >= G45PL) || (G43PL == 0) +#define MG45_13PL ~(1 << 2) +#else +#define MG45_13PL 0xFFFF +#endif +#if (G44PL >= G45PL) || (G44PL == 0) +#define MG45_14PL ~(1 << 3) +#else +#define MG45_14PL 0xFFFF +#endif +#if (G46PL >= G45PL) || (G46PL == 0) +#define MG45_16PL ~(1 << 5) +#else +#define MG45_16PL 0xFFFF +#endif +#if (G47PL >= G45PL) || (G47PL == 0) +#define MG45_17PL ~(1 << 6) +#else +#define MG45_17PL 0xFFFF +#endif +#if (G48PL >= G45PL) || (G48PL == 0) +#define MG45_18PL ~(1 << 7) +#else +#define MG45_18PL 0xFFFF +#endif +#define MG45_15PL 0x00EF +#define MG45 (MG45_11PL & MG45_12PL & MG45_13PL & MG45_14PL & \ + MG45_15PL & MG45_16PL & MG45_17PL & MG45_18PL) +// End of MG45: + +// Beginning of MG46: +#if (G41PL >= G46PL) || (G41PL == 0) +#define MG46_11PL ~(1) +#else +#define MG46_11PL 0xFFFF +#endif +#if (G42PL >= G46PL) || (G42PL == 0) +#define MG46_12PL ~(1 << 1) +#else +#define MG46_12PL 0xFFFF +#endif +#if (G43PL >= G46PL) || (G43PL == 0) +#define MG46_13PL ~(1 << 2) +#else +#define MG46_13PL 0xFFFF +#endif +#if (G44PL >= G46PL) || (G44PL == 0) +#define MG46_14PL ~(1 << 3) +#else +#define MG46_14PL 0xFFFF +#endif +#if (G45PL >= G46PL) || (G45PL == 0) +#define MG46_15PL ~(1 << 4) +#else +#define MG46_15PL 0xFFFF +#endif +#if (G47PL >= G46PL) || (G47PL == 0) +#define MG46_17PL ~(1 << 6) +#else +#define MG46_17PL 0xFFFF +#endif +#if (G48PL >= G46PL) || (G48PL == 0) +#define MG46_18PL ~(1 << 7) +#else +#define MG46_18PL 0xFFFF +#endif +#define MG46_16PL 0x00DF +#define MG46 (MG46_11PL & MG46_12PL & MG46_13PL & MG46_14PL & \ + MG46_15PL & MG46_16PL & MG46_17PL & MG46_18PL) +// End of MG46: + +// Beginning of MG47: +#if (G41PL >= G47PL) || (G41PL == 0) +#define MG47_11PL ~(1) +#else +#define MG47_11PL 0xFFFF +#endif +#if (G42PL >= G47PL) || (G42PL == 0) +#define MG47_12PL ~(1 << 1) +#else +#define MG47_12PL 0xFFFF +#endif +#if (G43PL >= G47PL) || (G43PL == 0) +#define MG47_13PL ~(1 << 2) +#else +#define MG47_13PL 0xFFFF +#endif +#if (G44PL >= G47PL) || (G44PL == 0) +#define MG47_14PL ~(1 << 3) +#else +#define MG47_14PL 0xFFFF +#endif +#if (G45PL >= G47PL) || (G45PL == 0) +#define MG47_15PL ~(1 << 4) +#else +#define MG47_15PL 0xFFFF +#endif +#if (G46PL >= G47PL) || (G46PL == 0) +#define MG47_16PL ~(1 << 5) +#else +#define MG47_16PL 0xFFFF +#endif +#if (G48PL >= G47PL) || (G48PL == 0) +#define MG47_18PL ~(1 << 7) +#else +#define MG47_18PL 0xFFFF +#endif +#define MG47_17PL 0x00BF +#define MG47 (MG47_11PL & MG47_12PL & MG47_13PL & MG47_14PL & \ + MG47_15PL & MG47_16PL & MG47_17PL & MG47_18PL) +// End of MG47: + +// Beginning of MG48: +#if (G41PL >= G48PL) || (G41PL == 0) +#define MG48_11PL ~(1) +#else +#define MG48_11PL 0xFFFF +#endif +#if (G42PL >= G48PL) || (G42PL == 0) +#define MG48_12PL ~(1 << 1) +#else +#define MG48_12PL 0xFFFF +#endif +#if (G43PL >= G48PL) || (G43PL == 0) +#define MG48_13PL ~(1 << 2) +#else +#define MG48_13PL 0xFFFF +#endif +#if (G44PL >= G48PL) || (G44PL == 0) +#define MG48_14PL ~(1 << 3) +#else +#define MG48_14PL 0xFFFF +#endif +#if (G45PL >= G48PL) || (G45PL == 0) +#define MG48_15PL ~(1 << 4) +#else +#define MG48_15PL 0xFFFF +#endif +#if (G46PL >= G48PL) || (G46PL == 0) +#define MG48_16PL ~(1 << 5) +#else +#define MG48_16PL 0xFFFF +#endif +#if (G47PL >= G48PL) || (G47PL == 0) +#define MG48_17PL ~(1 << 6) +#else +#define MG48_17PL 0xFFFF +#endif +#define MG48_18PL 0x007F +#define MG48 (MG48_11PL & MG48_12PL & MG48_13PL & MG48_14PL & \ + MG48_15PL & MG48_16PL & MG48_17PL & MG48_18PL) +// End of MG48: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG51 to MG58: +// + +// Beginning of MG51: +#if (G52PL >= G51PL) || (G52PL == 0) +#define MG51_12PL ~(1 << 1) +#else +#define MG51_12PL 0xFFFF +#endif +#if (G53PL >= G51PL) || (G53PL == 0) +#define MG51_13PL ~(1 << 2) +#else +#define MG51_13PL 0xFFFF +#endif +#if (G54PL >= G51PL) || (G54PL == 0) +#define MG51_14PL ~(1 << 3) +#else +#define MG51_14PL 0xFFFF +#endif +#if (G55PL >= G51PL) || (G55PL == 0) +#define MG51_15PL ~(1 << 4) +#else +#define MG51_15PL 0xFFFF +#endif +#if (G56PL >= G51PL) || (G56PL == 0) +#define MG51_16PL ~(1 << 5) +#else +#define MG51_16PL 0xFFFF +#endif +#if (G57PL >= G51PL) || (G57PL == 0) +#define MG51_17PL ~(1 << 6) +#else +#define MG51_17PL 0xFFFF +#endif +#if (G58PL >= G51PL) || (G58PL == 0) +#define MG51_18PL ~(1 << 7) +#else +#define MG51_18PL 0xFFFF +#endif +#define MG51_11PL 0x00FE +#define MG51 (MG51_11PL & MG51_12PL & MG51_13PL & MG51_14PL & \ + MG51_15PL & MG51_16PL & MG51_17PL & MG51_18PL) +// End of MG51: + +// Beginning of MG52: +#if (G51PL >= G52PL) || (G51PL == 0) +#define MG52_11PL ~(1) +#else +#define MG52_11PL 0xFFFF +#endif +#if (G53PL >= G52PL) || (G53PL == 0) +#define MG52_13PL ~(1 << 2) +#else +#define MG52_13PL 0xFFFF +#endif +#if (G54PL >= G52PL) || (G54PL == 0) +#define MG52_14PL ~(1 << 3) +#else +#define MG52_14PL 0xFFFF +#endif +#if (G55PL >= G52PL) || (G55PL == 0) +#define MG52_15PL ~(1 << 4) +#else +#define MG52_15PL 0xFFFF +#endif +#if (G56PL >= G52PL) || (G56PL == 0) +#define MG52_16PL ~(1 << 5) +#else +#define MG52_16PL 0xFFFF +#endif +#if (G57PL >= G52PL) || (G57PL == 0) +#define MG52_17PL ~(1 << 6) +#else +#define MG52_17PL 0xFFFF +#endif +#if (G58PL >= G52PL) || (G58PL == 0) +#define MG52_18PL ~(1 << 7) +#else +#define MG52_18PL 0xFFFF +#endif +#define MG52_12PL 0x00FD +#define MG52 (MG52_11PL & MG52_12PL & MG52_13PL & MG52_14PL & \ + MG52_15PL & MG52_16PL & MG52_17PL & MG52_18PL) +// End of MG52: + +// Beginning of MG53: +#if (G51PL >= G53PL) || (G51PL == 0) +#define MG53_11PL ~(1) +#else +#define MG53_11PL 0xFFFF +#endif +#if (G52PL >= G53PL) || (G52PL == 0) +#define MG53_12PL ~(1 << 1) +#else +#define MG53_12PL 0xFFFF +#endif +#if (G54PL >= G53PL) || (G54PL == 0) +#define MG53_14PL ~(1 << 3) +#else +#define MG53_14PL 0xFFFF +#endif +#if (G55PL >= G53PL) || (G55PL == 0) +#define MG53_15PL ~(1 << 4) +#else +#define MG53_15PL 0xFFFF +#endif +#if (G56PL >= G53PL) || (G56PL == 0) +#define MG53_16PL ~(1 << 5) +#else +#define MG53_16PL 0xFFFF +#endif +#if (G57PL >= G53PL) || (G57PL == 0) +#define MG53_17PL ~(1 << 6) +#else +#define MG53_17PL 0xFFFF +#endif +#if (G58PL >= G53PL) || (G58PL == 0) +#define MG53_18PL ~(1 << 7) +#else +#define MG53_18PL 0xFFFF +#endif +#define MG53_13PL 0x00FB +#define MG53 (MG53_11PL & MG53_12PL & MG53_13PL & MG53_14PL & \ + MG53_15PL & MG53_16PL & MG53_17PL & MG53_18PL) +// End of MG53: + +// Beginning of MG54: +#if (G51PL >= G54PL) || (G51PL == 0) +#define MG54_11PL ~(1) +#else +#define MG54_11PL 0xFFFF +#endif +#if (G52PL >= G54PL) || (G52PL == 0) +#define MG54_12PL ~(1 << 1) +#else +#define MG54_12PL 0xFFFF +#endif +#if (G53PL >= G54PL) || (G53PL == 0) +#define MG54_13PL ~(1 << 2) +#else +#define MG54_13PL 0xFFFF +#endif +#if (G55PL >= G54PL) || (G55PL == 0) +#define MG54_15PL ~(1 << 4) +#else +#define MG54_15PL 0xFFFF +#endif +#if (G56PL >= G54PL) || (G56PL == 0) +#define MG54_16PL ~(1 << 5) +#else +#define MG54_16PL 0xFFFF +#endif +#if (G57PL >= G54PL) || (G57PL == 0) +#define MG54_17PL ~(1 << 6) +#else +#define MG54_17PL 0xFFFF +#endif +#if (G58PL >= G54PL) || (G58PL == 0) +#define MG54_18PL ~(1 << 7) +#else +#define MG54_18PL 0xFFFF +#endif +#define MG54_14PL 0x00F7 +#define MG54 (MG54_11PL & MG54_12PL & MG54_13PL & MG54_14PL & \ + MG54_15PL & MG54_16PL & MG54_17PL & MG54_18PL) +// End of MG54: + +// Beginning of MG55: +#if (G51PL >= G55PL) || (G51PL == 0) +#define MG55_11PL ~(1) +#else +#define MG55_11PL 0xFFFF +#endif +#if (G52PL >= G55PL) || (G52PL == 0) +#define MG55_12PL ~(1 << 1) +#else +#define MG55_12PL 0xFFFF +#endif +#if (G53PL >= G55PL) || (G53PL == 0) +#define MG55_13PL ~(1 << 2) +#else +#define MG55_13PL 0xFFFF +#endif +#if (G54PL >= G55PL) || (G54PL == 0) +#define MG55_14PL ~(1 << 3) +#else +#define MG55_14PL 0xFFFF +#endif +#if (G56PL >= G55PL) || (G56PL == 0) +#define MG55_16PL ~(1 << 5) +#else +#define MG55_16PL 0xFFFF +#endif +#if (G57PL >= G55PL) || (G57PL == 0) +#define MG55_17PL ~(1 << 6) +#else +#define MG55_17PL 0xFFFF +#endif +#if (G58PL >= G55PL) || (G58PL == 0) +#define MG55_18PL ~(1 << 7) +#else +#define MG55_18PL 0xFFFF +#endif +#define MG55_15PL 0x00EF +#define MG55 (MG55_11PL & MG55_12PL & MG55_13PL & MG55_14PL & \ + MG55_15PL & MG55_16PL & MG55_17PL & MG55_18PL) +// End of MG55: + +// Beginning of MG56: +#if (G51PL >= G56PL) || (G51PL == 0) +#define MG56_11PL ~(1) +#else +#define MG56_11PL 0xFFFF +#endif +#if (G52PL >= G56PL) || (G52PL == 0) +#define MG56_12PL ~(1 << 1) +#else +#define MG56_12PL 0xFFFF +#endif +#if (G53PL >= G56PL) || (G53PL == 0) +#define MG56_13PL ~(1 << 2) +#else +#define MG56_13PL 0xFFFF +#endif +#if (G54PL >= G56PL) || (G54PL == 0) +#define MG56_14PL ~(1 << 3) +#else +#define MG56_14PL 0xFFFF +#endif +#if (G55PL >= G56PL) || (G55PL == 0) +#define MG56_15PL ~(1 << 4) +#else +#define MG56_15PL 0xFFFF +#endif +#if (G57PL >= G56PL) || (G57PL == 0) +#define MG56_17PL ~(1 << 6) +#else +#define MG56_17PL 0xFFFF +#endif +#if (G58PL >= G56PL) || (G58PL == 0) +#define MG56_18PL ~(1 << 7) +#else +#define MG56_18PL 0xFFFF +#endif +#define MG56_16PL 0x00DF +#define MG56 (MG56_11PL & MG56_12PL & MG56_13PL & MG56_14PL & \ + MG56_15PL & MG56_16PL & MG56_17PL & MG56_18PL) +// End of MG56: + +// Beginning of MG57: +#if (G51PL >= G57PL) || (G51PL == 0) +#define MG57_11PL ~(1) +#else +#define MG57_11PL 0xFFFF +#endif +#if (G52PL >= G57PL) || (G52PL == 0) +#define MG57_12PL ~(1 << 1) +#else +#define MG57_12PL 0xFFFF +#endif +#if (G53PL >= G57PL) || (G53PL == 0) +#define MG57_13PL ~(1 << 2) +#else +#define MG57_13PL 0xFFFF +#endif +#if (G54PL >= G57PL) || (G54PL == 0) +#define MG57_14PL ~(1 << 3) +#else +#define MG57_14PL 0xFFFF +#endif +#if (G55PL >= G57PL) || (G55PL == 0) +#define MG57_15PL ~(1 << 4) +#else +#define MG57_15PL 0xFFFF +#endif +#if (G56PL >= G57PL) || (G56PL == 0) +#define MG57_16PL ~(1 << 5) +#else +#define MG57_16PL 0xFFFF +#endif +#if (G58PL >= G57PL) || (G58PL == 0) +#define MG57_18PL ~(1 << 7) +#else +#define MG57_18PL 0xFFFF +#endif +#define MG57_17PL 0x00BF +#define MG57 (MG57_11PL & MG57_12PL & MG57_13PL & MG57_14PL & \ + MG57_15PL & MG57_16PL & MG57_17PL & MG57_18PL) +// End of MG57: + +// Beginning of MG58: +#if (G51PL >= G58PL) || (G51PL == 0) +#define MG58_11PL ~(1) +#else +#define MG58_11PL 0xFFFF +#endif +#if (G52PL >= G58PL) || (G52PL == 0) +#define MG58_12PL ~(1 << 1) +#else +#define MG58_12PL 0xFFFF +#endif +#if (G53PL >= G58PL) || (G53PL == 0) +#define MG58_13PL ~(1 << 2) +#else +#define MG58_13PL 0xFFFF +#endif +#if (G54PL >= G58PL) || (G54PL == 0) +#define MG58_14PL ~(1 << 3) +#else +#define MG58_14PL 0xFFFF +#endif +#if (G55PL >= G58PL) || (G55PL == 0) +#define MG58_15PL ~(1 << 4) +#else +#define MG58_15PL 0xFFFF +#endif +#if (G56PL >= G58PL) || (G56PL == 0) +#define MG58_16PL ~(1 << 5) +#else +#define MG58_16PL 0xFFFF +#endif +#if (G57PL >= G58PL) || (G57PL == 0) +#define MG58_17PL ~(1 << 6) +#else +#define MG58_17PL 0xFFFF +#endif +#define MG58_18PL 0x007F +#define MG58 (MG58_11PL & MG58_12PL & MG58_13PL & MG58_14PL & \ + MG58_15PL & MG58_16PL & MG58_17PL & MG58_18PL) +// End of MG58: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG61 to MG68: +// + +// Beginning of MG61: +#if (G62PL >= G61PL) || (G62PL == 0) +#define MG61_12PL ~(1 << 1) +#else +#define MG61_12PL 0xFFFF +#endif +#if (G63PL >= G61PL) || (G63PL == 0) +#define MG61_13PL ~(1 << 2) +#else +#define MG61_13PL 0xFFFF +#endif +#if (G64PL >= G61PL) || (G64PL == 0) +#define MG61_14PL ~(1 << 3) +#else +#define MG61_14PL 0xFFFF +#endif +#if (G65PL >= G61PL) || (G65PL == 0) +#define MG61_15PL ~(1 << 4) +#else +#define MG61_15PL 0xFFFF +#endif +#if (G66PL >= G61PL) || (G66PL == 0) +#define MG61_16PL ~(1 << 5) +#else +#define MG61_16PL 0xFFFF +#endif +#if (G67PL >= G61PL) || (G67PL == 0) +#define MG61_17PL ~(1 << 6) +#else +#define MG61_17PL 0xFFFF +#endif +#if (G68PL >= G61PL) || (G68PL == 0) +#define MG61_18PL ~(1 << 7) +#else +#define MG61_18PL 0xFFFF +#endif +#define MG61_11PL 0x00FE +#define MG61 (MG61_11PL & MG61_12PL & MG61_13PL & MG61_14PL & \ + MG61_15PL & MG61_16PL & MG61_17PL & MG61_18PL) +// End of MG61: + +// Beginning of MG62: +#if (G61PL >= G62PL) || (G61PL == 0) +#define MG62_11PL ~(1) +#else +#define MG62_11PL 0xFFFF +#endif +#if (G63PL >= G62PL) || (G63PL == 0) +#define MG62_13PL ~(1 << 2) +#else +#define MG62_13PL 0xFFFF +#endif +#if (G64PL >= G62PL) || (G64PL == 0) +#define MG62_14PL ~(1 << 3) +#else +#define MG62_14PL 0xFFFF +#endif +#if (G65PL >= G62PL) || (G65PL == 0) +#define MG62_15PL ~(1 << 4) +#else +#define MG62_15PL 0xFFFF +#endif +#if (G66PL >= G62PL) || (G66PL == 0) +#define MG62_16PL ~(1 << 5) +#else +#define MG62_16PL 0xFFFF +#endif +#if (G67PL >= G62PL) || (G67PL == 0) +#define MG62_17PL ~(1 << 6) +#else +#define MG62_17PL 0xFFFF +#endif +#if (G68PL >= G62PL) || (G68PL == 0) +#define MG62_18PL ~(1 << 7) +#else +#define MG62_18PL 0xFFFF +#endif +#define MG62_12PL 0x00FD +#define MG62 (MG62_11PL & MG62_12PL & MG62_13PL & MG62_14PL & \ + MG62_15PL & MG62_16PL & MG62_17PL & MG62_18PL) +// End of MG62: + +// Beginning of MG63: +#if (G61PL >= G63PL) || (G61PL == 0) +#define MG63_11PL ~(1) +#else +#define MG63_11PL 0xFFFF +#endif +#if (G62PL >= G63PL) || (G62PL == 0) +#define MG63_12PL ~(1 << 1) +#else +#define MG63_12PL 0xFFFF +#endif +#if (G64PL >= G63PL) || (G64PL == 0) +#define MG63_14PL ~(1 << 3) +#else +#define MG63_14PL 0xFFFF +#endif +#if (G65PL >= G63PL) || (G65PL == 0) +#define MG63_15PL ~(1 << 4) +#else +#define MG63_15PL 0xFFFF +#endif +#if (G66PL >= G63PL) || (G66PL == 0) +#define MG63_16PL ~(1 << 5) +#else +#define MG63_16PL 0xFFFF +#endif +#if (G67PL >= G63PL) || (G67PL == 0) +#define MG63_17PL ~(1 << 6) +#else +#define MG63_17PL 0xFFFF +#endif +#if (G68PL >= G63PL) || (G68PL == 0) +#define MG63_18PL ~(1 << 7) +#else +#define MG63_18PL 0xFFFF +#endif +#define MG63_13PL 0x00FB +#define MG63 (MG63_11PL & MG63_12PL & MG63_13PL & MG63_14PL & \ + MG63_15PL & MG63_16PL & MG63_17PL & MG63_18PL) +// End of MG63: + +// Beginning of MG64: +#if (G61PL >= G64PL) || (G61PL == 0) +#define MG64_11PL ~(1) +#else +#define MG64_11PL 0xFFFF +#endif +#if (G62PL >= G64PL) || (G62PL == 0) +#define MG64_12PL ~(1 << 1) +#else +#define MG64_12PL 0xFFFF +#endif +#if (G63PL >= G64PL) || (G63PL == 0) +#define MG64_13PL ~(1 << 2) +#else +#define MG64_13PL 0xFFFF +#endif +#if (G65PL >= G64PL) || (G65PL == 0) +#define MG64_15PL ~(1 << 4) +#else +#define MG64_15PL 0xFFFF +#endif +#if (G66PL >= G64PL) || (G66PL == 0) +#define MG64_16PL ~(1 << 5) +#else +#define MG64_16PL 0xFFFF +#endif +#if (G67PL >= G64PL) || (G67PL == 0) +#define MG64_17PL ~(1 << 6) +#else +#define MG64_17PL 0xFFFF +#endif +#if (G68PL >= G64PL) || (G68PL == 0) +#define MG64_18PL ~(1 << 7) +#else +#define MG64_18PL 0xFFFF +#endif +#define MG64_14PL 0x00F7 +#define MG64 (MG64_11PL & MG64_12PL & MG64_13PL & MG64_14PL & \ + MG64_15PL & MG64_16PL & MG64_17PL & MG64_18PL) +// End of MG64: + +// Beginning of MG65: +#if (G61PL >= G65PL) || (G61PL == 0) +#define MG65_11PL ~(1) +#else +#define MG65_11PL 0xFFFF +#endif +#if (G62PL >= G65PL) || (G62PL == 0) +#define MG65_12PL ~(1 << 1) +#else +#define MG65_12PL 0xFFFF +#endif +#if (G63PL >= G65PL) || (G63PL == 0) +#define MG65_13PL ~(1 << 2) +#else +#define MG65_13PL 0xFFFF +#endif +#if (G64PL >= G65PL) || (G64PL == 0) +#define MG65_14PL ~(1 << 3) +#else +#define MG65_14PL 0xFFFF +#endif +#if (G66PL >= G65PL) || (G66PL == 0) +#define MG65_16PL ~(1 << 5) +#else +#define MG65_16PL 0xFFFF +#endif +#if (G67PL >= G65PL) || (G67PL == 0) +#define MG65_17PL ~(1 << 6) +#else +#define MG65_17PL 0xFFFF +#endif +#if (G68PL >= G65PL) || (G68PL == 0) +#define MG65_18PL ~(1 << 7) +#else +#define MG65_18PL 0xFFFF +#endif +#define MG65_15PL 0x00EF +#define MG65 (MG65_11PL & MG65_12PL & MG65_13PL & MG65_14PL & \ + MG65_15PL & MG65_16PL & MG65_17PL & MG65_18PL) +// End of MG65: + +// Beginning of MG66: +#if (G61PL >= G66PL) || (G61PL == 0) +#define MG66_11PL ~(1) +#else +#define MG66_11PL 0xFFFF +#endif +#if (G62PL >= G66PL) || (G62PL == 0) +#define MG66_12PL ~(1 << 1) +#else +#define MG66_12PL 0xFFFF +#endif +#if (G63PL >= G66PL) || (G63PL == 0) +#define MG66_13PL ~(1 << 2) +#else +#define MG66_13PL 0xFFFF +#endif +#if (G64PL >= G66PL) || (G64PL == 0) +#define MG66_14PL ~(1 << 3) +#else +#define MG66_14PL 0xFFFF +#endif +#if (G65PL >= G66PL) || (G65PL == 0) +#define MG66_15PL ~(1 << 4) +#else +#define MG66_15PL 0xFFFF +#endif +#if (G67PL >= G66PL) || (G67PL == 0) +#define MG66_17PL ~(1 << 6) +#else +#define MG66_17PL 0xFFFF +#endif +#if (G68PL >= G66PL) || (G68PL == 0) +#define MG66_18PL ~(1 << 7) +#else +#define MG66_18PL 0xFFFF +#endif +#define MG66_16PL 0x00DF +#define MG66 (MG66_11PL & MG66_12PL & MG66_13PL & MG66_14PL & \ + MG66_15PL & MG66_16PL & MG66_17PL & MG66_18PL) +// End of MG66: + +// Beginning of MG67: +#if (G61PL >= G67PL) || (G61PL == 0) +#define MG67_11PL ~(1) +#else +#define MG67_11PL 0xFFFF +#endif +#if (G62PL >= G67PL) || (G62PL == 0) +#define MG67_12PL ~(1 << 1) +#else +#define MG67_12PL 0xFFFF +#endif +#if (G63PL >= G67PL) || (G63PL == 0) +#define MG67_13PL ~(1 << 2) +#else +#define MG67_13PL 0xFFFF +#endif +#if (G64PL >= G67PL) || (G64PL == 0) +#define MG67_14PL ~(1 << 3) +#else +#define MG67_14PL 0xFFFF +#endif +#if (G65PL >= G67PL) || (G65PL == 0) +#define MG67_15PL ~(1 << 4) +#else +#define MG67_15PL 0xFFFF +#endif +#if (G66PL >= G67PL) || (G66PL == 0) +#define MG67_16PL ~(1 << 5) +#else +#define MG67_16PL 0xFFFF +#endif +#if (G68PL >= G67PL) || (G68PL == 0) +#define MG67_18PL ~(1 << 7) +#else +#define MG67_18PL 0xFFFF +#endif +#define MG67_17PL 0x00BF +#define MG67 (MG67_11PL & MG67_12PL & MG67_13PL & MG67_14PL & \ + MG67_15PL & MG67_16PL & MG67_17PL & MG67_18PL) +// End of MG67: + +// Beginning of MG68: +#if (G61PL >= G68PL) || (G61PL == 0) +#define MG68_11PL ~(1) +#else +#define MG68_11PL 0xFFFF +#endif +#if (G62PL >= G68PL) || (G62PL == 0) +#define MG68_12PL ~(1 << 1) +#else +#define MG68_12PL 0xFFFF +#endif +#if (G63PL >= G68PL) || (G63PL == 0) +#define MG68_13PL ~(1 << 2) +#else +#define MG68_13PL 0xFFFF +#endif +#if (G64PL >= G68PL) || (G64PL == 0) +#define MG68_14PL ~(1 << 3) +#else +#define MG68_14PL 0xFFFF +#endif +#if (G65PL >= G68PL) || (G65PL == 0) +#define MG68_15PL ~(1 << 4) +#else +#define MG68_15PL 0xFFFF +#endif +#if (G66PL >= G68PL) || (G66PL == 0) +#define MG68_16PL ~(1 << 5) +#else +#define MG68_16PL 0xFFFF +#endif +#if (G67PL >= G68PL) || (G67PL == 0) +#define MG68_17PL ~(1 << 6) +#else +#define MG68_17PL 0xFFFF +#endif +#define MG68_18PL 0x007F +#define MG68 (MG68_11PL & MG68_12PL & MG68_13PL & MG68_14PL & \ + MG68_15PL & MG68_16PL & MG68_17PL & MG68_18PL) +// End of MG68: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG71 to MG78: +// + +// Beginning of MG71: +#if (G72PL >= G71PL) || (G72PL == 0) +#define MG71_12PL ~(1 << 1) +#else +#define MG71_12PL 0xFFFF +#endif +#if (G73PL >= G71PL) || (G73PL == 0) +#define MG71_13PL ~(1 << 2) +#else +#define MG71_13PL 0xFFFF +#endif +#if (G74PL >= G71PL) || (G74PL == 0) +#define MG71_14PL ~(1 << 3) +#else +#define MG71_14PL 0xFFFF +#endif +#if (G75PL >= G71PL) || (G75PL == 0) +#define MG71_15PL ~(1 << 4) +#else +#define MG71_15PL 0xFFFF +#endif +#if (G76PL >= G71PL) || (G76PL == 0) +#define MG71_16PL ~(1 << 5) +#else +#define MG71_16PL 0xFFFF +#endif +#if (G77PL >= G71PL) || (G77PL == 0) +#define MG71_17PL ~(1 << 6) +#else +#define MG71_17PL 0xFFFF +#endif +#if (G78PL >= G71PL) || (G78PL == 0) +#define MG71_18PL ~(1 << 7) +#else +#define MG71_18PL 0xFFFF +#endif +#define MG71_11PL 0x00FE +#define MG71 (MG71_11PL & MG71_12PL & MG71_13PL & MG71_14PL & \ + MG71_15PL & MG71_16PL & MG71_17PL & MG71_18PL) +// End of MG71: + +// Beginning of MG72: +#if (G71PL >= G72PL) || (G71PL == 0) +#define MG72_11PL ~(1) +#else +#define MG72_11PL 0xFFFF +#endif +#if (G73PL >= G72PL) || (G73PL == 0) +#define MG72_13PL ~(1 << 2) +#else +#define MG72_13PL 0xFFFF +#endif +#if (G74PL >= G72PL) || (G74PL == 0) +#define MG72_14PL ~(1 << 3) +#else +#define MG72_14PL 0xFFFF +#endif +#if (G75PL >= G72PL) || (G75PL == 0) +#define MG72_15PL ~(1 << 4) +#else +#define MG72_15PL 0xFFFF +#endif +#if (G76PL >= G72PL) || (G76PL == 0) +#define MG72_16PL ~(1 << 5) +#else +#define MG72_16PL 0xFFFF +#endif +#if (G77PL >= G72PL) || (G77PL == 0) +#define MG72_17PL ~(1 << 6) +#else +#define MG72_17PL 0xFFFF +#endif +#if (G78PL >= G72PL) || (G78PL == 0) +#define MG72_18PL ~(1 << 7) +#else +#define MG72_18PL 0xFFFF +#endif +#define MG72_12PL 0x00FD +#define MG72 (MG72_11PL & MG72_12PL & MG72_13PL & MG72_14PL & \ + MG72_15PL & MG72_16PL & MG72_17PL & MG72_18PL) +// End of MG72: + +// Beginning of MG73: +#if (G71PL >= G73PL) || (G71PL == 0) +#define MG73_11PL ~(1) +#else +#define MG73_11PL 0xFFFF +#endif +#if (G72PL >= G73PL) || (G72PL == 0) +#define MG73_12PL ~(1 << 1) +#else +#define MG73_12PL 0xFFFF +#endif +#if (G74PL >= G73PL) || (G74PL == 0) +#define MG73_14PL ~(1 << 3) +#else +#define MG73_14PL 0xFFFF +#endif +#if (G75PL >= G73PL) || (G75PL == 0) +#define MG73_15PL ~(1 << 4) +#else +#define MG73_15PL 0xFFFF +#endif +#if (G76PL >= G73PL) || (G76PL == 0) +#define MG73_16PL ~(1 << 5) +#else +#define MG73_16PL 0xFFFF +#endif +#if (G77PL >= G73PL) || (G77PL == 0) +#define MG73_17PL ~(1 << 6) +#else +#define MG73_17PL 0xFFFF +#endif +#if (G78PL >= G73PL) || (G78PL == 0) +#define MG73_18PL ~(1 << 7) +#else +#define MG73_18PL 0xFFFF +#endif +#define MG73_13PL 0x00FB +#define MG73 (MG73_11PL & MG73_12PL & MG73_13PL & MG73_14PL & \ + MG73_15PL & MG73_16PL & MG73_17PL & MG73_18PL) +// End of MG73: + +// Beginning of MG74: +#if (G71PL >= G74PL) || (G71PL == 0) +#define MG74_11PL ~(1) +#else +#define MG74_11PL 0xFFFF +#endif +#if (G72PL >= G74PL) || (G72PL == 0) +#define MG74_12PL ~(1 << 1) +#else +#define MG74_12PL 0xFFFF +#endif +#if (G73PL >= G74PL) || (G73PL == 0) +#define MG74_13PL ~(1 << 2) +#else +#define MG74_13PL 0xFFFF +#endif +#if (G75PL >= G74PL) || (G75PL == 0) +#define MG74_15PL ~(1 << 4) +#else +#define MG74_15PL 0xFFFF +#endif +#if (G76PL >= G74PL) || (G76PL == 0) +#define MG74_16PL ~(1 << 5) +#else +#define MG74_16PL 0xFFFF +#endif +#if (G77PL >= G74PL) || (G77PL == 0) +#define MG74_17PL ~(1 << 6) +#else +#define MG74_17PL 0xFFFF +#endif +#if (G78PL >= G74PL) || (G78PL == 0) +#define MG74_18PL ~(1 << 7) +#else +#define MG74_18PL 0xFFFF +#endif +#define MG74_14PL 0x00F7 +#define MG74 (MG74_11PL & MG74_12PL & MG74_13PL & MG74_14PL & \ + MG74_15PL & MG74_16PL & MG74_17PL & MG74_18PL) +// End of MG74: + +// Beginning of MG75: +#if (G71PL >= G75PL) || (G71PL == 0) +#define MG75_11PL ~(1) +#else +#define MG75_11PL 0xFFFF +#endif +#if (G72PL >= G75PL) || (G72PL == 0) +#define MG75_12PL ~(1 << 1) +#else +#define MG75_12PL 0xFFFF +#endif +#if (G73PL >= G75PL) || (G73PL == 0) +#define MG75_13PL ~(1 << 2) +#else +#define MG75_13PL 0xFFFF +#endif +#if (G74PL >= G75PL) || (G74PL == 0) +#define MG75_14PL ~(1 << 3) +#else +#define MG75_14PL 0xFFFF +#endif +#if (G76PL >= G75PL) || (G76PL == 0) +#define MG75_16PL ~(1 << 5) +#else +#define MG75_16PL 0xFFFF +#endif +#if (G77PL >= G75PL) || (G77PL == 0) +#define MG75_17PL ~(1 << 6) +#else +#define MG75_17PL 0xFFFF +#endif +#if (G78PL >= G75PL) || (G78PL == 0) +#define MG75_18PL ~(1 << 7) +#else +#define MG75_18PL 0xFFFF +#endif +#define MG75_15PL 0x00EF +#define MG75 (MG75_11PL & MG75_12PL & MG75_13PL & MG75_14PL & \ + MG75_15PL & MG75_16PL & MG75_17PL & MG75_18PL) +// End of MG75: + +// Beginning of MG76: +#if (G71PL >= G76PL) || (G71PL == 0) +#define MG76_11PL ~(1) +#else +#define MG76_11PL 0xFFFF +#endif +#if (G72PL >= G76PL) || (G72PL == 0) +#define MG76_12PL ~(1 << 1) +#else +#define MG76_12PL 0xFFFF +#endif +#if (G73PL >= G76PL) || (G73PL == 0) +#define MG76_13PL ~(1 << 2) +#else +#define MG76_13PL 0xFFFF +#endif +#if (G74PL >= G76PL) || (G74PL == 0) +#define MG76_14PL ~(1 << 3) +#else +#define MG76_14PL 0xFFFF +#endif +#if (G75PL >= G76PL) || (G75PL == 0) +#define MG76_15PL ~(1 << 4) +#else +#define MG76_15PL 0xFFFF +#endif +#if (G77PL >= G76PL) || (G77PL == 0) +#define MG76_17PL ~(1 << 6) +#else +#define MG76_17PL 0xFFFF +#endif +#if (G78PL >= G76PL) || (G78PL == 0) +#define MG76_18PL ~(1 << 7) +#else +#define MG76_18PL 0xFFFF +#endif +#define MG76_16PL 0x00DF +#define MG76 (MG76_11PL & MG76_12PL & MG76_13PL & MG76_14PL & \ + MG76_15PL & MG76_16PL & MG76_17PL & MG76_18PL) +// End of MG76: + +// Beginning of MG77: +#if (G71PL >= G77PL) || (G71PL == 0) +#define MG77_11PL ~(1) +#else +#define MG77_11PL 0xFFFF +#endif +#if (G72PL >= G77PL) || (G72PL == 0) +#define MG77_12PL ~(1 << 1) +#else +#define MG77_12PL 0xFFFF +#endif +#if (G73PL >= G77PL) || (G73PL == 0) +#define MG77_13PL ~(1 << 2) +#else +#define MG77_13PL 0xFFFF +#endif +#if (G74PL >= G77PL) || (G74PL == 0) +#define MG77_14PL ~(1 << 3) +#else +#define MG77_14PL 0xFFFF +#endif +#if (G75PL >= G77PL) || (G75PL == 0) +#define MG77_15PL ~(1 << 4) +#else +#define MG77_15PL 0xFFFF +#endif +#if (G76PL >= G77PL) || (G76PL == 0) +#define MG77_16PL ~(1 << 5) +#else +#define MG77_16PL 0xFFFF +#endif +#if (G78PL >= G77PL) || (G78PL == 0) +#define MG77_18PL ~(1 << 7) +#else +#define MG77_18PL 0xFFFF +#endif +#define MG77_17PL 0x00BF +#define MG77 (MG77_11PL & MG77_12PL & MG77_13PL & MG77_14PL & \ + MG77_15PL & MG77_16PL & MG77_17PL & MG77_18PL) +// End of MG77: + +// Beginning of MG78: +#if (G71PL >= G78PL) || (G71PL == 0) +#define MG78_11PL ~(1) +#else +#define MG78_11PL 0xFFFF +#endif +#if (G72PL >= G78PL) || (G72PL == 0) +#define MG78_12PL ~(1 << 1) +#else +#define MG78_12PL 0xFFFF +#endif +#if (G73PL >= G78PL) || (G73PL == 0) +#define MG78_13PL ~(1 << 2) +#else +#define MG78_13PL 0xFFFF +#endif +#if (G74PL >= G78PL) || (G74PL == 0) +#define MG78_14PL ~(1 << 3) +#else +#define MG78_14PL 0xFFFF +#endif +#if (G75PL >= G78PL) || (G75PL == 0) +#define MG78_15PL ~(1 << 4) +#else +#define MG78_15PL 0xFFFF +#endif +#if (G76PL >= G78PL) || (G76PL == 0) +#define MG78_16PL ~(1 << 5) +#else +#define MG78_16PL 0xFFFF +#endif +#if (G77PL >= G78PL) || (G77PL == 0) +#define MG78_17PL ~(1 << 6) +#else +#define MG78_17PL 0xFFFF +#endif +#define MG78_18PL 0x007F +#define MG78 (MG78_11PL & MG78_12PL & MG78_13PL & MG78_14PL & \ + MG78_15PL & MG78_16PL & MG78_17PL & MG78_18PL) +// End of MG78: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG81 to MG88: +// + +// Beginning of MG81: +#if (G82PL >= G81PL) || (G82PL == 0) +#define MG81_12PL ~(1 << 1) +#else +#define MG81_12PL 0xFFFF +#endif +#if (G83PL >= G81PL) || (G83PL == 0) +#define MG81_13PL ~(1 << 2) +#else +#define MG81_13PL 0xFFFF +#endif +#if (G84PL >= G81PL) || (G84PL == 0) +#define MG81_14PL ~(1 << 3) +#else +#define MG81_14PL 0xFFFF +#endif +#if (G85PL >= G81PL) || (G85PL == 0) +#define MG81_15PL ~(1 << 4) +#else +#define MG81_15PL 0xFFFF +#endif +#if (G86PL >= G81PL) || (G86PL == 0) +#define MG81_16PL ~(1 << 5) +#else +#define MG81_16PL 0xFFFF +#endif +#if (G87PL >= G81PL) || (G87PL == 0) +#define MG81_17PL ~(1 << 6) +#else +#define MG81_17PL 0xFFFF +#endif +#if (G88PL >= G81PL) || (G88PL == 0) +#define MG81_18PL ~(1 << 7) +#else +#define MG81_18PL 0xFFFF +#endif +#define MG81_11PL 0x00FE +#define MG81 (MG81_11PL & MG81_12PL & MG81_13PL & MG81_14PL & \ + MG81_15PL & MG81_16PL & MG81_17PL & MG81_18PL) +// End of MG81: + +// Beginning of MG82: +#if (G81PL >= G82PL) || (G81PL == 0) +#define MG82_11PL ~(1) +#else +#define MG82_11PL 0xFFFF +#endif +#if (G83PL >= G82PL) || (G83PL == 0) +#define MG82_13PL ~(1 << 2) +#else +#define MG82_13PL 0xFFFF +#endif +#if (G84PL >= G82PL) || (G84PL == 0) +#define MG82_14PL ~(1 << 3) +#else +#define MG82_14PL 0xFFFF +#endif +#if (G85PL >= G82PL) || (G85PL == 0) +#define MG82_15PL ~(1 << 4) +#else +#define MG82_15PL 0xFFFF +#endif +#if (G86PL >= G82PL) || (G86PL == 0) +#define MG82_16PL ~(1 << 5) +#else +#define MG82_16PL 0xFFFF +#endif +#if (G87PL >= G82PL) || (G87PL == 0) +#define MG82_17PL ~(1 << 6) +#else +#define MG82_17PL 0xFFFF +#endif +#if (G88PL >= G82PL) || (G88PL == 0) +#define MG82_18PL ~(1 << 7) +#else +#define MG82_18PL 0xFFFF +#endif +#define MG82_12PL 0x00FD +#define MG82 (MG82_11PL & MG82_12PL & MG82_13PL & MG82_14PL & \ + MG82_15PL & MG82_16PL & MG82_17PL & MG82_18PL) +// End of MG82: + +// Beginning of MG83: +#if (G81PL >= G83PL) || (G81PL == 0) +#define MG83_11PL ~(1) +#else +#define MG83_11PL 0xFFFF +#endif +#if (G82PL >= G83PL) || (G82PL == 0) +#define MG83_12PL ~(1 << 1) +#else +#define MG83_12PL 0xFFFF +#endif +#if (G84PL >= G83PL) || (G84PL == 0) +#define MG83_14PL ~(1 << 3) +#else +#define MG83_14PL 0xFFFF +#endif +#if (G85PL >= G83PL) || (G85PL == 0) +#define MG83_15PL ~(1 << 4) +#else +#define MG83_15PL 0xFFFF +#endif +#if (G86PL >= G83PL) || (G86PL == 0) +#define MG83_16PL ~(1 << 5) +#else +#define MG83_16PL 0xFFFF +#endif +#if (G87PL >= G83PL) || (G87PL == 0) +#define MG83_17PL ~(1 << 6) +#else +#define MG83_17PL 0xFFFF +#endif +#if (G88PL >= G83PL) || (G88PL == 0) +#define MG83_18PL ~(1 << 7) +#else +#define MG83_18PL 0xFFFF +#endif +#define MG83_13PL 0x00FB +#define MG83 (MG83_11PL & MG83_12PL & MG83_13PL & MG83_14PL & \ + MG83_15PL & MG83_16PL & MG83_17PL & MG83_18PL) +// End of MG83: + +// Beginning of MG84: +#if (G81PL >= G84PL) || (G81PL == 0) +#define MG84_11PL ~(1) +#else +#define MG84_11PL 0xFFFF +#endif +#if (G82PL >= G84PL) || (G82PL == 0) +#define MG84_12PL ~(1 << 1) +#else +#define MG84_12PL 0xFFFF +#endif +#if (G83PL >= G84PL) || (G83PL == 0) +#define MG84_13PL ~(1 << 2) +#else +#define MG84_13PL 0xFFFF +#endif +#if (G85PL >= G84PL) || (G85PL == 0) +#define MG84_15PL ~(1 << 4) +#else +#define MG84_15PL 0xFFFF +#endif +#if (G86PL >= G84PL) || (G86PL == 0) +#define MG84_16PL ~(1 << 5) +#else +#define MG84_16PL 0xFFFF +#endif +#if (G87PL >= G84PL) || (G87PL == 0) +#define MG84_17PL ~(1 << 6) +#else +#define MG84_17PL 0xFFFF +#endif +#if (G88PL >= G84PL) || (G88PL == 0) +#define MG84_18PL ~(1 << 7) +#else +#define MG84_18PL 0xFFFF +#endif +#define MG84_14PL 0x00F7 +#define MG84 (MG84_11PL & MG84_12PL & MG84_13PL & MG84_14PL & \ + MG84_15PL & MG84_16PL & MG84_17PL & MG84_18PL) +// End of MG84: + +// Beginning of MG85: +#if (G81PL >= G85PL) || (G81PL == 0) +#define MG85_11PL ~(1) +#else +#define MG85_11PL 0xFFFF +#endif +#if (G82PL >= G85PL) || (G82PL == 0) +#define MG85_12PL ~(1 << 1) +#else +#define MG85_12PL 0xFFFF +#endif +#if (G83PL >= G85PL) || (G83PL == 0) +#define MG85_13PL ~(1 << 2) +#else +#define MG85_13PL 0xFFFF +#endif +#if (G84PL >= G85PL) || (G84PL == 0) +#define MG85_14PL ~(1 << 3) +#else +#define MG85_14PL 0xFFFF +#endif +#if (G86PL >= G85PL) || (G86PL == 0) +#define MG85_16PL ~(1 << 5) +#else +#define MG85_16PL 0xFFFF +#endif +#if (G87PL >= G85PL) || (G87PL == 0) +#define MG85_17PL ~(1 << 6) +#else +#define MG85_17PL 0xFFFF +#endif +#if (G88PL >= G85PL) || (G88PL == 0) +#define MG85_18PL ~(1 << 7) +#else +#define MG85_18PL 0xFFFF +#endif +#define MG85_15PL 0x00EF +#define MG85 (MG85_11PL & MG85_12PL & MG85_13PL & MG85_14PL & \ + MG85_15PL & MG85_16PL & MG85_17PL & MG85_18PL) +// End of MG85: + +// Beginning of MG86: +#if (G81PL >= G86PL) || (G81PL == 0) +#define MG86_11PL ~(1) +#else +#define MG86_11PL 0xFFFF +#endif +#if (G82PL >= G86PL) || (G82PL == 0) +#define MG86_12PL ~(1 << 1) +#else +#define MG86_12PL 0xFFFF +#endif +#if (G83PL >= G86PL) || (G83PL == 0) +#define MG86_13PL ~(1 << 2) +#else +#define MG86_13PL 0xFFFF +#endif +#if (G84PL >= G86PL) || (G84PL == 0) +#define MG86_14PL ~(1 << 3) +#else +#define MG86_14PL 0xFFFF +#endif +#if (G85PL >= G86PL) || (G85PL == 0) +#define MG86_15PL ~(1 << 4) +#else +#define MG86_15PL 0xFFFF +#endif +#if (G87PL >= G86PL) || (G87PL == 0) +#define MG86_17PL ~(1 << 6) +#else +#define MG86_17PL 0xFFFF +#endif +#if (G88PL >= G86PL) || (G88PL == 0) +#define MG86_18PL ~(1 << 7) +#else +#define MG86_18PL 0xFFFF +#endif +#define MG86_16PL 0x00DF +#define MG86 (MG86_11PL & MG86_12PL & MG86_13PL & MG86_14PL & \ + MG86_15PL & MG86_16PL & MG86_17PL & MG86_18PL) +// End of MG86: + +// Beginning of MG87: +#if (G81PL >= G87PL) || (G81PL == 0) +#define MG87_11PL ~(1) +#else +#define MG87_11PL 0xFFFF +#endif +#if (G82PL >= G87PL) || (G82PL == 0) +#define MG87_12PL ~(1 << 1) +#else +#define MG87_12PL 0xFFFF +#endif +#if (G83PL >= G87PL) || (G83PL == 0) +#define MG87_13PL ~(1 << 2) +#else +#define MG87_13PL 0xFFFF +#endif +#if (G84PL >= G87PL) || (G84PL == 0) +#define MG87_14PL ~(1 << 3) +#else +#define MG87_14PL 0xFFFF +#endif +#if (G85PL >= G87PL) || (G85PL == 0) +#define MG87_15PL ~(1 << 4) +#else +#define MG87_15PL 0xFFFF +#endif +#if (G86PL >= G87PL) || (G86PL == 0) +#define MG87_16PL ~(1 << 5) +#else +#define MG87_16PL 0xFFFF +#endif +#if (G88PL >= G87PL) || (G88PL == 0) +#define MG87_18PL ~(1 << 7) +#else +#define MG87_18PL 0xFFFF +#endif +#define MG87_17PL 0x00BF +#define MG87 (MG87_11PL & MG87_12PL & MG87_13PL & MG87_14PL & \ + MG87_15PL & MG87_16PL & MG87_17PL & MG87_18PL) +// End of MG87: + +// Beginning of MG88: +#if (G81PL >= G88PL) || (G81PL == 0) +#define MG88_11PL ~(1) +#else +#define MG88_11PL 0xFFFF +#endif +#if (G82PL >= G88PL) || (G82PL == 0) +#define MG88_12PL ~(1 << 1) +#else +#define MG88_12PL 0xFFFF +#endif +#if (G83PL >= G88PL) || (G83PL == 0) +#define MG88_13PL ~(1 << 2) +#else +#define MG88_13PL 0xFFFF +#endif +#if (G84PL >= G88PL) || (G84PL == 0) +#define MG88_14PL ~(1 << 3) +#else +#define MG88_14PL 0xFFFF +#endif +#if (G85PL >= G88PL) || (G85PL == 0) +#define MG88_15PL ~(1 << 4) +#else +#define MG88_15PL 0xFFFF +#endif +#if (G86PL >= G88PL) || (G86PL == 0) +#define MG88_16PL ~(1 << 5) +#else +#define MG88_16PL 0xFFFF +#endif +#if (G87PL >= G88PL) || (G87PL == 0) +#define MG88_17PL ~(1 << 6) +#else +#define MG88_17PL 0xFFFF +#endif +#define MG88_18PL 0x007F +#define MG88 (MG88_11PL & MG88_12PL & MG88_13PL & MG88_14PL & \ + MG88_15PL & MG88_16PL & MG88_17PL & MG88_18PL) +// End of MG88: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG91 to MG98: +// + +// Beginning of MG91: +#if (G92PL >= G91PL) || (G92PL == 0) +#define MG91_12PL ~(1 << 1) +#else +#define MG91_12PL 0xFFFF +#endif +#if (G93PL >= G91PL) || (G93PL == 0) +#define MG91_13PL ~(1 << 2) +#else +#define MG91_13PL 0xFFFF +#endif +#if (G94PL >= G91PL) || (G94PL == 0) +#define MG91_14PL ~(1 << 3) +#else +#define MG91_14PL 0xFFFF +#endif +#if (G95PL >= G91PL) || (G95PL == 0) +#define MG91_15PL ~(1 << 4) +#else +#define MG91_15PL 0xFFFF +#endif +#if (G96PL >= G91PL) || (G96PL == 0) +#define MG91_16PL ~(1 << 5) +#else +#define MG91_16PL 0xFFFF +#endif +#if (G97PL >= G91PL) || (G97PL == 0) +#define MG91_17PL ~(1 << 6) +#else +#define MG91_17PL 0xFFFF +#endif +#if (G98PL >= G91PL) || (G98PL == 0) +#define MG91_18PL ~(1 << 7) +#else +#define MG91_18PL 0xFFFF +#endif +#define MG91_11PL 0x00FE +#define MG91 (MG91_11PL & MG91_12PL & MG91_13PL & MG91_14PL & \ + MG91_15PL & MG91_16PL & MG91_17PL & MG91_18PL) +// End of MG91: + +// Beginning of MG92: +#if (G91PL >= G92PL) || (G91PL == 0) +#define MG92_11PL ~(1) +#else +#define MG92_11PL 0xFFFF +#endif +#if (G93PL >= G92PL) || (G93PL == 0) +#define MG92_13PL ~(1 << 2) +#else +#define MG92_13PL 0xFFFF +#endif +#if (G94PL >= G92PL) || (G94PL == 0) +#define MG92_14PL ~(1 << 3) +#else +#define MG92_14PL 0xFFFF +#endif +#if (G95PL >= G92PL) || (G95PL == 0) +#define MG92_15PL ~(1 << 4) +#else +#define MG92_15PL 0xFFFF +#endif +#if (G96PL >= G92PL) || (G96PL == 0) +#define MG92_16PL ~(1 << 5) +#else +#define MG92_16PL 0xFFFF +#endif +#if (G97PL >= G92PL) || (G97PL == 0) +#define MG92_17PL ~(1 << 6) +#else +#define MG92_17PL 0xFFFF +#endif +#if (G98PL >= G92PL) || (G98PL == 0) +#define MG92_18PL ~(1 << 7) +#else +#define MG92_18PL 0xFFFF +#endif +#define MG92_12PL 0x00FD +#define MG92 (MG92_11PL & MG92_12PL & MG92_13PL & MG92_14PL & \ + MG92_15PL & MG92_16PL & MG92_17PL & MG92_18PL) +// End of MG92: + +// Beginning of MG93: +#if (G91PL >= G93PL) || (G91PL == 0) +#define MG93_11PL ~(1) +#else +#define MG93_11PL 0xFFFF +#endif +#if (G92PL >= G93PL) || (G92PL == 0) +#define MG93_12PL ~(1 << 1) +#else +#define MG93_12PL 0xFFFF +#endif +#if (G94PL >= G93PL) || (G94PL == 0) +#define MG93_14PL ~(1 << 3) +#else +#define MG93_14PL 0xFFFF +#endif +#if (G95PL >= G93PL) || (G95PL == 0) +#define MG93_15PL ~(1 << 4) +#else +#define MG93_15PL 0xFFFF +#endif +#if (G96PL >= G93PL) || (G96PL == 0) +#define MG93_16PL ~(1 << 5) +#else +#define MG93_16PL 0xFFFF +#endif +#if (G97PL >= G93PL) || (G97PL == 0) +#define MG93_17PL ~(1 << 6) +#else +#define MG93_17PL 0xFFFF +#endif +#if (G98PL >= G93PL) || (G98PL == 0) +#define MG93_18PL ~(1 << 7) +#else +#define MG93_18PL 0xFFFF +#endif +#define MG93_13PL 0x00FB +#define MG93 (MG93_11PL & MG93_12PL & MG93_13PL & MG93_14PL & \ + MG93_15PL & MG93_16PL & MG93_17PL & MG93_18PL) +// End of MG93: + +// Beginning of MG94: +#if (G91PL >= G94PL) || (G91PL == 0) +#define MG94_11PL ~(1) +#else +#define MG94_11PL 0xFFFF +#endif +#if (G92PL >= G94PL) || (G92PL == 0) +#define MG94_12PL ~(1 << 1) +#else +#define MG94_12PL 0xFFFF +#endif +#if (G93PL >= G94PL) || (G93PL == 0) +#define MG94_13PL ~(1 << 2) +#else +#define MG94_13PL 0xFFFF +#endif +#if (G95PL >= G94PL) || (G95PL == 0) +#define MG94_15PL ~(1 << 4) +#else +#define MG94_15PL 0xFFFF +#endif +#if (G96PL >= G94PL) || (G96PL == 0) +#define MG94_16PL ~(1 << 5) +#else +#define MG94_16PL 0xFFFF +#endif +#if (G97PL >= G94PL) || (G97PL == 0) +#define MG94_17PL ~(1 << 6) +#else +#define MG94_17PL 0xFFFF +#endif +#if (G98PL >= G94PL) || (G98PL == 0) +#define MG94_18PL ~(1 << 7) +#else +#define MG94_18PL 0xFFFF +#endif +#define MG94_14PL 0x00F7 +#define MG94 (MG94_11PL & MG94_12PL & MG94_13PL & MG94_14PL & \ + MG94_15PL & MG94_16PL & MG94_17PL & MG94_18PL) +// End of MG94: + +// Beginning of MG95: +#if (G91PL >= G95PL) || (G91PL == 0) +#define MG95_11PL ~(1) +#else +#define MG95_11PL 0xFFFF +#endif +#if (G92PL >= G95PL) || (G92PL == 0) +#define MG95_12PL ~(1 << 1) +#else +#define MG95_12PL 0xFFFF +#endif +#if (G93PL >= G95PL) || (G93PL == 0) +#define MG95_13PL ~(1 << 2) +#else +#define MG95_13PL 0xFFFF +#endif +#if (G94PL >= G95PL) || (G94PL == 0) +#define MG95_14PL ~(1 << 3) +#else +#define MG95_14PL 0xFFFF +#endif +#if (G96PL >= G95PL) || (G96PL == 0) +#define MG95_16PL ~(1 << 5) +#else +#define MG95_16PL 0xFFFF +#endif +#if (G97PL >= G95PL) || (G97PL == 0) +#define MG95_17PL ~(1 << 6) +#else +#define MG95_17PL 0xFFFF +#endif +#if (G98PL >= G95PL) || (G98PL == 0) +#define MG95_18PL ~(1 << 7) +#else +#define MG95_18PL 0xFFFF +#endif +#define MG95_15PL 0x00EF +#define MG95 (MG95_11PL & MG95_12PL & MG95_13PL & MG95_14PL & \ + MG95_15PL & MG95_16PL & MG95_17PL & MG95_18PL) +// End of MG95: + +// Beginning of MG96: +#if (G91PL >= G96PL) || (G91PL == 0) +#define MG96_11PL ~(1) +#else +#define MG96_11PL 0xFFFF +#endif +#if (G92PL >= G96PL) || (G92PL == 0) +#define MG96_12PL ~(1 << 1) +#else +#define MG96_12PL 0xFFFF +#endif +#if (G93PL >= G96PL) || (G93PL == 0) +#define MG96_13PL ~(1 << 2) +#else +#define MG96_13PL 0xFFFF +#endif +#if (G94PL >= G96PL) || (G94PL == 0) +#define MG96_14PL ~(1 << 3) +#else +#define MG96_14PL 0xFFFF +#endif +#if (G95PL >= G96PL) || (G95PL == 0) +#define MG96_15PL ~(1 << 4) +#else +#define MG96_15PL 0xFFFF +#endif +#if (G97PL >= G96PL) || (G97PL == 0) +#define MG96_17PL ~(1 << 6) +#else +#define MG96_17PL 0xFFFF +#endif +#if (G98PL >= G96PL) || (G98PL == 0) +#define MG96_18PL ~(1 << 7) +#else +#define MG96_18PL 0xFFFF +#endif +#define MG96_16PL 0x00DF +#define MG96 (MG96_11PL & MG96_12PL & MG96_13PL & MG96_14PL & \ + MG96_15PL & MG96_16PL & MG96_17PL & MG96_18PL) +// End of MG96: + +// Beginning of MG97: +#if (G91PL >= G97PL) || (G91PL == 0) +#define MG97_11PL ~(1) +#else +#define MG97_11PL 0xFFFF +#endif +#if (G92PL >= G97PL) || (G92PL == 0) +#define MG97_12PL ~(1 << 1) +#else +#define MG97_12PL 0xFFFF +#endif +#if (G93PL >= G97PL) || (G93PL == 0) +#define MG97_13PL ~(1 << 2) +#else +#define MG97_13PL 0xFFFF +#endif +#if (G94PL >= G97PL) || (G94PL == 0) +#define MG97_14PL ~(1 << 3) +#else +#define MG97_14PL 0xFFFF +#endif +#if (G95PL >= G97PL) || (G95PL == 0) +#define MG97_15PL ~(1 << 4) +#else +#define MG97_15PL 0xFFFF +#endif +#if (G96PL >= G97PL) || (G96PL == 0) +#define MG97_16PL ~(1 << 5) +#else +#define MG97_16PL 0xFFFF +#endif +#if (G98PL >= G97PL) || (G98PL == 0) +#define MG97_18PL ~(1 << 7) +#else +#define MG97_18PL 0xFFFF +#endif +#define MG97_17PL 0x00BF +#define MG97 (MG97_11PL & MG97_12PL & MG97_13PL & MG97_14PL & \ + MG97_15PL & MG97_16PL & MG97_17PL & MG97_18PL) +// End of MG97: + +// Beginning of MG98: +#if (G91PL >= G98PL) || (G91PL == 0) +#define MG98_11PL ~(1) +#else +#define MG98_11PL 0xFFFF +#endif +#if (G92PL >= G98PL) || (G92PL == 0) +#define MG98_12PL ~(1 << 1) +#else +#define MG98_12PL 0xFFFF +#endif +#if (G93PL >= G98PL) || (G93PL == 0) +#define MG98_13PL ~(1 << 2) +#else +#define MG98_13PL 0xFFFF +#endif +#if (G94PL >= G98PL) || (G94PL == 0) +#define MG98_14PL ~(1 << 3) +#else +#define MG98_14PL 0xFFFF +#endif +#if (G95PL >= G98PL) || (G95PL == 0) +#define MG98_15PL ~(1 << 4) +#else +#define MG98_15PL 0xFFFF +#endif +#if (G96PL >= G98PL) || (G96PL == 0) +#define MG98_16PL ~(1 << 5) +#else +#define MG98_16PL 0xFFFF +#endif +#if (G97PL >= G98PL) || (G97PL == 0) +#define MG98_17PL ~(1 << 6) +#else +#define MG98_17PL 0xFFFF +#endif +#define MG98_18PL 0x007F +#define MG98 (MG98_11PL & MG98_12PL & MG98_13PL & MG98_14PL & \ + MG98_15PL & MG98_16PL & MG98_17PL & MG98_18PL) +// End of MG98: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG101 to MG108: +// + +// Beginning of MG101: +#if (G102PL >= G101PL) || (G102PL == 0) +#define MG101_12PL ~(1 << 1) +#else +#define MG101_12PL 0xFFFF +#endif +#if (G103PL >= G101PL) || (G103PL == 0) +#define MG101_13PL ~(1 << 2) +#else +#define MG101_13PL 0xFFFF +#endif +#if (G104PL >= G101PL) || (G104PL == 0) +#define MG101_14PL ~(1 << 3) +#else +#define MG101_14PL 0xFFFF +#endif +#if (G105PL >= G101PL) || (G105PL == 0) +#define MG101_15PL ~(1 << 4) +#else +#define MG101_15PL 0xFFFF +#endif +#if (G106PL >= G101PL) || (G106PL == 0) +#define MG101_16PL ~(1 << 5) +#else +#define MG101_16PL 0xFFFF +#endif +#if (G107PL >= G101PL) || (G107PL == 0) +#define MG101_17PL ~(1 << 6) +#else +#define MG101_17PL 0xFFFF +#endif +#if (G108PL >= G101PL) || (G108PL == 0) +#define MG101_18PL ~(1 << 7) +#else +#define MG101_18PL 0xFFFF +#endif +#define MG101_11PL 0x00FE +#define MG101 (MG101_11PL & MG101_12PL & MG101_13PL & MG101_14PL & \ + MG101_15PL & MG101_16PL & MG101_17PL & MG101_18PL) +// End of MG101: + +// Beginning of MG102: +#if (G101PL >= G102PL) || (G101PL == 0) +#define MG102_11PL ~(1) +#else +#define MG102_11PL 0xFFFF +#endif +#if (G103PL >= G102PL) || (G103PL == 0) +#define MG102_13PL ~(1 << 2) +#else +#define MG102_13PL 0xFFFF +#endif +#if (G104PL >= G102PL) || (G104PL == 0) +#define MG102_14PL ~(1 << 3) +#else +#define MG102_14PL 0xFFFF +#endif +#if (G105PL >= G102PL) || (G105PL == 0) +#define MG102_15PL ~(1 << 4) +#else +#define MG102_15PL 0xFFFF +#endif +#if (G106PL >= G102PL) || (G106PL == 0) +#define MG102_16PL ~(1 << 5) +#else +#define MG102_16PL 0xFFFF +#endif +#if (G107PL >= G102PL) || (G107PL == 0) +#define MG102_17PL ~(1 << 6) +#else +#define MG102_17PL 0xFFFF +#endif +#if (G108PL >= G102PL) || (G108PL == 0) +#define MG102_18PL ~(1 << 7) +#else +#define MG102_18PL 0xFFFF +#endif +#define MG102_12PL 0x00FD +#define MG102 (MG102_11PL & MG102_12PL & MG102_13PL & MG102_14PL & \ + MG102_15PL & MG102_16PL & MG102_17PL & MG102_18PL) +// End of MG102: + +// Beginning of MG103: +#if (G101PL >= G103PL) || (G101PL == 0) +#define MG103_11PL ~(1) +#else +#define MG103_11PL 0xFFFF +#endif +#if (G102PL >= G103PL) || (G102PL == 0) +#define MG103_12PL ~(1 << 1) +#else +#define MG103_12PL 0xFFFF +#endif +#if (G104PL >= G103PL) || (G104PL == 0) +#define MG103_14PL ~(1 << 3) +#else +#define MG103_14PL 0xFFFF +#endif +#if (G105PL >= G103PL) || (G105PL == 0) +#define MG103_15PL ~(1 << 4) +#else +#define MG103_15PL 0xFFFF +#endif +#if (G106PL >= G103PL) || (G106PL == 0) +#define MG103_16PL ~(1 << 5) +#else +#define MG103_16PL 0xFFFF +#endif +#if (G107PL >= G103PL) || (G107PL == 0) +#define MG103_17PL ~(1 << 6) +#else +#define MG103_17PL 0xFFFF +#endif +#if (G108PL >= G103PL) || (G108PL == 0) +#define MG103_18PL ~(1 << 7) +#else +#define MG103_18PL 0xFFFF +#endif +#define MG103_13PL 0x00FB +#define MG103 (MG103_11PL & MG103_12PL & MG103_13PL & MG103_14PL & \ + MG103_15PL & MG103_16PL & MG103_17PL & MG103_18PL) +// End of MG103: + +// Beginning of MG104: +#if (G101PL >= G104PL) || (G101PL == 0) +#define MG104_11PL ~(1) +#else +#define MG104_11PL 0xFFFF +#endif +#if (G102PL >= G104PL) || (G102PL == 0) +#define MG104_12PL ~(1 << 1) +#else +#define MG104_12PL 0xFFFF +#endif +#if (G103PL >= G104PL) || (G103PL == 0) +#define MG104_13PL ~(1 << 2) +#else +#define MG104_13PL 0xFFFF +#endif +#if (G105PL >= G104PL) || (G105PL == 0) +#define MG104_15PL ~(1 << 4) +#else +#define MG104_15PL 0xFFFF +#endif +#if (G106PL >= G104PL) || (G106PL == 0) +#define MG104_16PL ~(1 << 5) +#else +#define MG104_16PL 0xFFFF +#endif +#if (G107PL >= G104PL) || (G107PL == 0) +#define MG104_17PL ~(1 << 6) +#else +#define MG104_17PL 0xFFFF +#endif +#if (G108PL >= G104PL) || (G108PL == 0) +#define MG104_18PL ~(1 << 7) +#else +#define MG104_18PL 0xFFFF +#endif +#define MG104_14PL 0x00F7 +#define MG104 (MG104_11PL & MG104_12PL & MG104_13PL & MG104_14PL & \ + MG104_15PL & MG104_16PL & MG104_17PL & MG104_18PL) +// End of MG104: + +// Beginning of MG105: +#if (G101PL >= G105PL) || (G101PL == 0) +#define MG105_11PL ~(1) +#else +#define MG105_11PL 0xFFFF +#endif +#if (G102PL >= G105PL) || (G102PL == 0) +#define MG105_12PL ~(1 << 1) +#else +#define MG105_12PL 0xFFFF +#endif +#if (G103PL >= G105PL) || (G103PL == 0) +#define MG105_13PL ~(1 << 2) +#else +#define MG105_13PL 0xFFFF +#endif +#if (G104PL >= G105PL) || (G104PL == 0) +#define MG105_14PL ~(1 << 3) +#else +#define MG105_14PL 0xFFFF +#endif +#if (G106PL >= G105PL) || (G106PL == 0) +#define MG105_16PL ~(1 << 5) +#else +#define MG105_16PL 0xFFFF +#endif +#if (G107PL >= G105PL) || (G107PL == 0) +#define MG105_17PL ~(1 << 6) +#else +#define MG105_17PL 0xFFFF +#endif +#if (G108PL >= G105PL) || (G108PL == 0) +#define MG105_18PL ~(1 << 7) +#else +#define MG105_18PL 0xFFFF +#endif +#define MG105_15PL 0x00EF +#define MG105 (MG105_11PL & MG105_12PL & MG105_13PL & MG105_14PL & \ + MG105_15PL & MG105_16PL & MG105_17PL & MG105_18PL) +// End of MG105: + +// Beginning of MG106: +#if (G101PL >= G106PL) || (G101PL == 0) +#define MG106_11PL ~(1) +#else +#define MG106_11PL 0xFFFF +#endif +#if (G102PL >= G106PL) || (G102PL == 0) +#define MG106_12PL ~(1 << 1) +#else +#define MG106_12PL 0xFFFF +#endif +#if (G103PL >= G106PL) || (G103PL == 0) +#define MG106_13PL ~(1 << 2) +#else +#define MG106_13PL 0xFFFF +#endif +#if (G104PL >= G106PL) || (G104PL == 0) +#define MG106_14PL ~(1 << 3) +#else +#define MG106_14PL 0xFFFF +#endif +#if (G105PL >= G106PL) || (G105PL == 0) +#define MG106_15PL ~(1 << 4) +#else +#define MG106_15PL 0xFFFF +#endif +#if (G107PL >= G106PL) || (G107PL == 0) +#define MG106_17PL ~(1 << 6) +#else +#define MG106_17PL 0xFFFF +#endif +#if (G108PL >= G106PL) || (G108PL == 0) +#define MG106_18PL ~(1 << 7) +#else +#define MG106_18PL 0xFFFF +#endif +#define MG106_16PL 0x00DF +#define MG106 (MG106_11PL & MG106_12PL & MG106_13PL & MG106_14PL & \ + MG106_15PL & MG106_16PL & MG106_17PL & MG106_18PL) +// End of MG106: + +// Beginning of MG107: +#if (G101PL >= G107PL) || (G101PL == 0) +#define MG107_11PL ~(1) +#else +#define MG107_11PL 0xFFFF +#endif +#if (G102PL >= G107PL) || (G102PL == 0) +#define MG107_12PL ~(1 << 1) +#else +#define MG107_12PL 0xFFFF +#endif +#if (G103PL >= G107PL) || (G103PL == 0) +#define MG107_13PL ~(1 << 2) +#else +#define MG107_13PL 0xFFFF +#endif +#if (G104PL >= G107PL) || (G104PL == 0) +#define MG107_14PL ~(1 << 3) +#else +#define MG107_14PL 0xFFFF +#endif +#if (G105PL >= G107PL) || (G105PL == 0) +#define MG107_15PL ~(1 << 4) +#else +#define MG107_15PL 0xFFFF +#endif +#if (G106PL >= G107PL) || (G106PL == 0) +#define MG107_16PL ~(1 << 5) +#else +#define MG107_16PL 0xFFFF +#endif +#if (G108PL >= G107PL) || (G108PL == 0) +#define MG107_18PL ~(1 << 7) +#else +#define MG107_18PL 0xFFFF +#endif +#define MG107_17PL 0x00BF +#define MG107 (MG107_11PL & MG107_12PL & MG107_13PL & MG107_14PL & \ + MG107_15PL & MG107_16PL & MG107_17PL & MG107_18PL) +// End of MG107: + +// Beginning of MG108: +#if (G101PL >= G108PL) || (G101PL == 0) +#define MG108_11PL ~(1) +#else +#define MG108_11PL 0xFFFF +#endif +#if (G102PL >= G108PL) || (G102PL == 0) +#define MG108_12PL ~(1 << 1) +#else +#define MG108_12PL 0xFFFF +#endif +#if (G103PL >= G108PL) || (G103PL == 0) +#define MG108_13PL ~(1 << 2) +#else +#define MG108_13PL 0xFFFF +#endif +#if (G104PL >= G108PL) || (G104PL == 0) +#define MG108_14PL ~(1 << 3) +#else +#define MG108_14PL 0xFFFF +#endif +#if (G105PL >= G108PL) || (G105PL == 0) +#define MG108_15PL ~(1 << 4) +#else +#define MG108_15PL 0xFFFF +#endif +#if (G106PL >= G108PL) || (G106PL == 0) +#define MG108_16PL ~(1 << 5) +#else +#define MG108_16PL 0xFFFF +#endif +#if (G107PL >= G108PL) || (G107PL == 0) +#define MG108_17PL ~(1 << 6) +#else +#define MG108_17PL 0xFFFF +#endif +#define MG108_18PL 0x007F +#define MG108 (MG108_11PL & MG108_12PL & MG108_13PL & MG108_14PL & \ + MG108_15PL & MG108_16PL & MG108_17PL & MG108_18PL) +// End of MG108: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG111 to MG118: +// + +// Beginning of MG111: +#if (G112PL >= G111PL) || (G112PL == 0) +#define MG111_12PL ~(1 << 1) +#else +#define MG111_12PL 0xFFFF +#endif +#if (G113PL >= G111PL) || (G113PL == 0) +#define MG111_13PL ~(1 << 2) +#else +#define MG111_13PL 0xFFFF +#endif +#if (G114PL >= G111PL) || (G114PL == 0) +#define MG111_14PL ~(1 << 3) +#else +#define MG111_14PL 0xFFFF +#endif +#if (G115PL >= G111PL) || (G115PL == 0) +#define MG111_15PL ~(1 << 4) +#else +#define MG111_15PL 0xFFFF +#endif +#if (G116PL >= G111PL) || (G116PL == 0) +#define MG111_16PL ~(1 << 5) +#else +#define MG111_16PL 0xFFFF +#endif +#if (G117PL >= G111PL) || (G117PL == 0) +#define MG111_17PL ~(1 << 6) +#else +#define MG111_17PL 0xFFFF +#endif +#if (G118PL >= G111PL) || (G118PL == 0) +#define MG111_18PL ~(1 << 7) +#else +#define MG111_18PL 0xFFFF +#endif +#define MG111_11PL 0x00FE +#define MG111 (MG111_11PL & MG111_12PL & MG111_13PL & MG111_14PL & \ + MG111_15PL & MG111_16PL & MG111_17PL & MG111_18PL) +// End of MG111: + +// Beginning of MG112: +#if (G111PL >= G112PL) || (G111PL == 0) +#define MG112_11PL ~(1) +#else +#define MG112_11PL 0xFFFF +#endif +#if (G113PL >= G112PL) || (G113PL == 0) +#define MG112_13PL ~(1 << 2) +#else +#define MG112_13PL 0xFFFF +#endif +#if (G114PL >= G112PL) || (G114PL == 0) +#define MG112_14PL ~(1 << 3) +#else +#define MG112_14PL 0xFFFF +#endif +#if (G115PL >= G112PL) || (G115PL == 0) +#define MG112_15PL ~(1 << 4) +#else +#define MG112_15PL 0xFFFF +#endif +#if (G116PL >= G112PL) || (G116PL == 0) +#define MG112_16PL ~(1 << 5) +#else +#define MG112_16PL 0xFFFF +#endif +#if (G117PL >= G112PL) || (G117PL == 0) +#define MG112_17PL ~(1 << 6) +#else +#define MG112_17PL 0xFFFF +#endif +#if (G118PL >= G112PL) || (G118PL == 0) +#define MG112_18PL ~(1 << 7) +#else +#define MG112_18PL 0xFFFF +#endif +#define MG112_12PL 0x00FD +#define MG112 (MG112_11PL & MG112_12PL & MG112_13PL & MG112_14PL & \ + MG112_15PL & MG112_16PL & MG112_17PL & MG112_18PL) +// End of MG112: + +// Beginning of MG113: +#if (G111PL >= G113PL) || (G111PL == 0) +#define MG113_11PL ~(1) +#else +#define MG113_11PL 0xFFFF +#endif +#if (G112PL >= G113PL) || (G112PL == 0) +#define MG113_12PL ~(1 << 1) +#else +#define MG113_12PL 0xFFFF +#endif +#if (G114PL >= G113PL) || (G114PL == 0) +#define MG113_14PL ~(1 << 3) +#else +#define MG113_14PL 0xFFFF +#endif +#if (G115PL >= G113PL) || (G115PL == 0) +#define MG113_15PL ~(1 << 4) +#else +#define MG113_15PL 0xFFFF +#endif +#if (G116PL >= G113PL) || (G116PL == 0) +#define MG113_16PL ~(1 << 5) +#else +#define MG113_16PL 0xFFFF +#endif +#if (G117PL >= G113PL) || (G117PL == 0) +#define MG113_17PL ~(1 << 6) +#else +#define MG113_17PL 0xFFFF +#endif +#if (G118PL >= G113PL) || (G118PL == 0) +#define MG113_18PL ~(1 << 7) +#else +#define MG113_18PL 0xFFFF +#endif +#define MG113_13PL 0x00FB +#define MG113 (MG113_11PL & MG113_12PL & MG113_13PL & MG113_14PL & \ + MG113_15PL & MG113_16PL & MG113_17PL & MG113_18PL) +// End of MG113: + +// Beginning of MG114: +#if (G111PL >= G114PL) || (G111PL == 0) +#define MG114_11PL ~(1) +#else +#define MG114_11PL 0xFFFF +#endif +#if (G112PL >= G114PL) || (G112PL == 0) +#define MG114_12PL ~(1 << 1) +#else +#define MG114_12PL 0xFFFF +#endif +#if (G113PL >= G114PL) || (G113PL == 0) +#define MG114_13PL ~(1 << 2) +#else +#define MG114_13PL 0xFFFF +#endif +#if (G115PL >= G114PL) || (G115PL == 0) +#define MG114_15PL ~(1 << 4) +#else +#define MG114_15PL 0xFFFF +#endif +#if (G116PL >= G114PL) || (G116PL == 0) +#define MG114_16PL ~(1 << 5) +#else +#define MG114_16PL 0xFFFF +#endif +#if (G117PL >= G114PL) || (G117PL == 0) +#define MG114_17PL ~(1 << 6) +#else +#define MG114_17PL 0xFFFF +#endif +#if (G118PL >= G114PL) || (G118PL == 0) +#define MG114_18PL ~(1 << 7) +#else +#define MG114_18PL 0xFFFF +#endif +#define MG114_14PL 0x00F7 +#define MG114 (MG114_11PL & MG114_12PL & MG114_13PL & MG114_14PL & \ + MG114_15PL & MG114_16PL & MG114_17PL & MG114_18PL) +// End of MG114: + +// Beginning of MG115: +#if (G111PL >= G115PL) || (G111PL == 0) +#define MG115_11PL ~(1) +#else +#define MG115_11PL 0xFFFF +#endif +#if (G112PL >= G115PL) || (G112PL == 0) +#define MG115_12PL ~(1 << 1) +#else +#define MG115_12PL 0xFFFF +#endif +#if (G113PL >= G115PL) || (G113PL == 0) +#define MG115_13PL ~(1 << 2) +#else +#define MG115_13PL 0xFFFF +#endif +#if (G114PL >= G115PL) || (G114PL == 0) +#define MG115_14PL ~(1 << 3) +#else +#define MG115_14PL 0xFFFF +#endif +#if (G116PL >= G115PL) || (G116PL == 0) +#define MG115_16PL ~(1 << 5) +#else +#define MG115_16PL 0xFFFF +#endif +#if (G117PL >= G115PL) || (G117PL == 0) +#define MG115_17PL ~(1 << 6) +#else +#define MG115_17PL 0xFFFF +#endif +#if (G118PL >= G115PL) || (G118PL == 0) +#define MG115_18PL ~(1 << 7) +#else +#define MG115_18PL 0xFFFF +#endif +#define MG115_15PL 0x00EF +#define MG115 (MG115_11PL & MG115_12PL & MG115_13PL & MG115_14PL & \ + MG115_15PL & MG115_16PL & MG115_17PL & MG115_18PL) +// End of MG115: + +// Beginning of MG116: +#if (G111PL >= G116PL) || (G111PL == 0) +#define MG116_11PL ~(1) +#else +#define MG116_11PL 0xFFFF +#endif +#if (G112PL >= G116PL) || (G112PL == 0) +#define MG116_12PL ~(1 << 1) +#else +#define MG116_12PL 0xFFFF +#endif +#if (G113PL >= G116PL) || (G113PL == 0) +#define MG116_13PL ~(1 << 2) +#else +#define MG116_13PL 0xFFFF +#endif +#if (G114PL >= G116PL) || (G114PL == 0) +#define MG116_14PL ~(1 << 3) +#else +#define MG116_14PL 0xFFFF +#endif +#if (G115PL >= G116PL) || (G115PL == 0) +#define MG116_15PL ~(1 << 4) +#else +#define MG116_15PL 0xFFFF +#endif +#if (G117PL >= G116PL) || (G117PL == 0) +#define MG116_17PL ~(1 << 6) +#else +#define MG116_17PL 0xFFFF +#endif +#if (G118PL >= G116PL) || (G118PL == 0) +#define MG116_18PL ~(1 << 7) +#else +#define MG116_18PL 0xFFFF +#endif +#define MG116_16PL 0x00DF +#define MG116 (MG116_11PL & MG116_12PL & MG116_13PL & MG116_14PL & \ + MG116_15PL & MG116_16PL & MG116_17PL & MG116_18PL) +// End of MG116: + +// Beginning of MG117: +#if (G111PL >= G117PL) || (G111PL == 0) +#define MG117_11PL ~(1) +#else +#define MG117_11PL 0xFFFF +#endif +#if (G112PL >= G117PL) || (G112PL == 0) +#define MG117_12PL ~(1 << 1) +#else +#define MG117_12PL 0xFFFF +#endif +#if (G113PL >= G117PL) || (G113PL == 0) +#define MG117_13PL ~(1 << 2) +#else +#define MG117_13PL 0xFFFF +#endif +#if (G114PL >= G117PL) || (G114PL == 0) +#define MG117_14PL ~(1 << 3) +#else +#define MG117_14PL 0xFFFF +#endif +#if (G115PL >= G117PL) || (G115PL == 0) +#define MG117_15PL ~(1 << 4) +#else +#define MG117_15PL 0xFFFF +#endif +#if (G116PL >= G117PL) || (G116PL == 0) +#define MG117_16PL ~(1 << 5) +#else +#define MG117_16PL 0xFFFF +#endif +#if (G118PL >= G117PL) || (G118PL == 0) +#define MG117_18PL ~(1 << 7) +#else +#define MG117_18PL 0xFFFF +#endif +#define MG117_17PL 0x00BF +#define MG117 (MG117_11PL & MG117_12PL & MG117_13PL & MG117_14PL & \ + MG117_15PL & MG117_16PL & MG117_17PL & MG117_18PL) +// End of MG117: + +// Beginning of MG118: +#if (G111PL >= G118PL) || (G111PL == 0) +#define MG118_11PL ~(1) +#else +#define MG118_11PL 0xFFFF +#endif +#if (G112PL >= G118PL) || (G112PL == 0) +#define MG118_12PL ~(1 << 1) +#else +#define MG118_12PL 0xFFFF +#endif +#if (G113PL >= G118PL) || (G113PL == 0) +#define MG118_13PL ~(1 << 2) +#else +#define MG118_13PL 0xFFFF +#endif +#if (G114PL >= G118PL) || (G114PL == 0) +#define MG118_14PL ~(1 << 3) +#else +#define MG118_14PL 0xFFFF +#endif +#if (G115PL >= G118PL) || (G115PL == 0) +#define MG118_15PL ~(1 << 4) +#else +#define MG118_15PL 0xFFFF +#endif +#if (G116PL >= G118PL) || (G116PL == 0) +#define MG118_16PL ~(1 << 5) +#else +#define MG118_16PL 0xFFFF +#endif +#if (G117PL >= G118PL) || (G117PL == 0) +#define MG118_17PL ~(1 << 6) +#else +#define MG118_17PL 0xFFFF +#endif +#define MG118_18PL 0x007F +#define MG118 (MG118_11PL & MG118_12PL & MG118_13PL & MG118_14PL & \ + MG118_15PL & MG118_16PL & MG118_17PL & MG118_18PL) +// End of MG118: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG121 to MG128: +// + +// Beginning of MG121: +#if (G122PL >= G121PL) || (G122PL == 0) +#define MG121_12PL ~(1 << 1) +#else +#define MG121_12PL 0xFFFF +#endif +#if (G123PL >= G121PL) || (G123PL == 0) +#define MG121_13PL ~(1 << 2) +#else +#define MG121_13PL 0xFFFF +#endif +#if (G124PL >= G121PL) || (G124PL == 0) +#define MG121_14PL ~(1 << 3) +#else +#define MG121_14PL 0xFFFF +#endif +#if (G125PL >= G121PL) || (G125PL == 0) +#define MG121_15PL ~(1 << 4) +#else +#define MG121_15PL 0xFFFF +#endif +#if (G126PL >= G121PL) || (G126PL == 0) +#define MG121_16PL ~(1 << 5) +#else +#define MG121_16PL 0xFFFF +#endif +#if (G127PL >= G121PL) || (G127PL == 0) +#define MG121_17PL ~(1 << 6) +#else +#define MG121_17PL 0xFFFF +#endif +#if (G128PL >= G121PL) || (G128PL == 0) +#define MG121_18PL ~(1 << 7) +#else +#define MG121_18PL 0xFFFF +#endif +#define MG121_11PL 0x00FE +#define MG121 (MG121_11PL & MG121_12PL & MG121_13PL & MG121_14PL & \ + MG121_15PL & MG121_16PL & MG121_17PL & MG121_18PL) +// End of MG121: + +// Beginning of MG121: +#if (G121PL >= G122PL) || (G121PL == 0) +#define MG122_11PL ~(1) +#else +#define MG122_11PL 0xFFFF +#endif +#if (G123PL >= G122PL) || (G123PL == 0) +#define MG122_13PL ~(1 << 2) +#else +#define MG122_13PL 0xFFFF +#endif +#if (G124PL >= G122PL) || (G124PL == 0) +#define MG122_14PL ~(1 << 3) +#else +#define MG122_14PL 0xFFFF +#endif +#if (G125PL >= G122PL) || (G125PL == 0) +#define MG122_15PL ~(1 << 4) +#else +#define MG122_15PL 0xFFFF +#endif +#if (G126PL >= G122PL) || (G126PL == 0) +#define MG122_16PL ~(1 << 5) +#else +#define MG122_16PL 0xFFFF +#endif +#if (G127PL >= G122PL) || (G127PL == 0) +#define MG122_17PL ~(1 << 6) +#else +#define MG122_17PL 0xFFFF +#endif +#if (G128PL >= G122PL) || (G128PL == 0) +#define MG122_18PL ~(1 << 7) +#else +#define MG122_18PL 0xFFFF +#endif +#define MG122_12PL 0x00FD +#define MG122 (MG122_11PL & MG122_12PL & MG122_13PL & MG122_14PL & \ + MG122_15PL & MG122_16PL & MG122_17PL & MG122_18PL) +// End of MG122: + +// Beginning of MG123: +#if (G121PL >= G123PL) || (G121PL == 0) +#define MG123_11PL ~(1) +#else +#define MG123_11PL 0xFFFF +#endif +#if (G122PL >= G123PL) || (G122PL == 0) +#define MG123_12PL ~(1 << 1) +#else +#define MG123_12PL 0xFFFF +#endif +#if (G124PL >= G123PL) || (G124PL == 0) +#define MG123_14PL ~(1 << 3) +#else +#define MG123_14PL 0xFFFF +#endif +#if (G125PL >= G123PL) || (G125PL == 0) +#define MG123_15PL ~(1 << 4) +#else +#define MG123_15PL 0xFFFF +#endif +#if (G126PL >= G123PL) || (G126PL == 0) +#define MG123_16PL ~(1 << 5) +#else +#define MG123_16PL 0xFFFF +#endif +#if (G127PL >= G123PL) || (G127PL == 0) +#define MG123_17PL ~(1 << 6) +#else +#define MG123_17PL 0xFFFF +#endif +#if (G128PL >= G123PL) || (G128PL == 0) +#define MG123_18PL ~(1 << 7) +#else +#define MG123_18PL 0xFFFF +#endif +#define MG123_13PL 0x00FB +#define MG123 (MG123_11PL & MG123_12PL & MG123_13PL & MG123_14PL & \ + MG123_15PL & MG123_16PL & MG123_17PL & MG123_18PL) +// End of MG123: + +// Beginning of MG124: +#if (G121PL >= G124PL) || (G121PL == 0) +#define MG124_11PL ~(1) +#else +#define MG124_11PL 0xFFFF +#endif +#if (G122PL >= G124PL) || (G122PL == 0) +#define MG124_12PL ~(1 << 1) +#else +#define MG124_12PL 0xFFFF +#endif +#if (G123PL >= G124PL) || (G123PL == 0) +#define MG124_13PL ~(1 << 2) +#else +#define MG124_13PL 0xFFFF +#endif +#if (G125PL >= G124PL) || (G125PL == 0) +#define MG124_15PL ~(1 << 4) +#else +#define MG124_15PL 0xFFFF +#endif +#if (G126PL >= G124PL) || (G126PL == 0) +#define MG124_16PL ~(1 << 5) +#else +#define MG124_16PL 0xFFFF +#endif +#if (G127PL >= G124PL) || (G127PL == 0) +#define MG124_17PL ~(1 << 6) +#else +#define MG124_17PL 0xFFFF +#endif +#if (G128PL >= G124PL) || (G128PL == 0) +#define MG124_18PL ~(1 << 7) +#else +#define MG124_18PL 0xFFFF +#endif +#define MG124_14PL 0x00F7 +#define MG124 (MG124_11PL & MG124_12PL & MG124_13PL & MG124_14PL & \ + MG124_15PL & MG124_16PL & MG124_17PL & MG124_18PL) +// End of MG124: + +// Beginning of MG125: +#if (G121PL >= G125PL) || (G121PL == 0) +#define MG125_11PL ~(1) +#else +#define MG125_11PL 0xFFFF +#endif +#if (G122PL >= G125PL) || (G122PL == 0) +#define MG125_12PL ~(1 << 1) +#else +#define MG125_12PL 0xFFFF +#endif +#if (G123PL >= G125PL) || (G123PL == 0) +#define MG125_13PL ~(1 << 2) +#else +#define MG125_13PL 0xFFFF +#endif +#if (G124PL >= G125PL) || (G124PL == 0) +#define MG125_14PL ~(1 << 3) +#else +#define MG125_14PL 0xFFFF +#endif +#if (G126PL >= G125PL) || (G126PL == 0) +#define MG125_16PL ~(1 << 5) +#else +#define MG125_16PL 0xFFFF +#endif +#if (G127PL >= G125PL) || (G127PL == 0) +#define MG125_17PL ~(1 << 6) +#else +#define MG125_17PL 0xFFFF +#endif +#if (G128PL >= G125PL) || (G128PL == 0) +#define MG125_18PL ~(1 << 7) +#else +#define MG125_18PL 0xFFFF +#endif +#define MG125_15PL 0x00EF +#define MG125 (MG125_11PL & MG125_12PL & MG125_13PL & MG125_14PL & \ + MG125_15PL & MG125_16PL & MG125_17PL & MG125_18PL) +// End of MG125: + +// Beginning of MG126: +#if (G121PL >= G126PL) || (G121PL == 0) +#define MG126_11PL ~(1) +#else +#define MG126_11PL 0xFFFF +#endif +#if (G122PL >= G126PL) || (G122PL == 0) +#define MG126_12PL ~(1 << 1) +#else +#define MG126_12PL 0xFFFF +#endif +#if (G123PL >= G126PL) || (G123PL == 0) +#define MG126_13PL ~(1 << 2) +#else +#define MG126_13PL 0xFFFF +#endif +#if (G124PL >= G126PL) || (G124PL == 0) +#define MG126_14PL ~(1 << 3) +#else +#define MG126_14PL 0xFFFF +#endif +#if (G125PL >= G126PL) || (G125PL == 0) +#define MG126_15PL ~(1 << 4) +#else +#define MG126_15PL 0xFFFF +#endif +#if (G127PL >= G126PL) || (G127PL == 0) +#define MG126_17PL ~(1 << 6) +#else +#define MG126_17PL 0xFFFF +#endif +#if (G128PL >= G126PL) || (G128PL == 0) +#define MG126_18PL ~(1 << 7) +#else +#define MG126_18PL 0xFFFF +#endif +#define MG126_16PL 0x00DF +#define MG126 (MG126_11PL & MG126_12PL & MG126_13PL & MG126_14PL & \ + MG126_15PL & MG126_16PL & MG126_17PL & MG126_18PL) +// End of MG126: + +// Beginning of MG127: +#if (G121PL >= G127PL) || (G121PL == 0) +#define MG127_11PL ~(1) +#else +#define MG127_11PL 0xFFFF +#endif +#if (G122PL >= G127PL) || (G122PL == 0) +#define MG127_12PL ~(1 << 1) +#else +#define MG127_12PL 0xFFFF +#endif +#if (G123PL >= G127PL) || (G123PL == 0) +#define MG127_13PL ~(1 << 2) +#else +#define MG127_13PL 0xFFFF +#endif +#if (G124PL >= G127PL) || (G124PL == 0) +#define MG127_14PL ~(1 << 3) +#else +#define MG127_14PL 0xFFFF +#endif +#if (G125PL >= G127PL) || (G125PL == 0) +#define MG127_15PL ~(1 << 4) +#else +#define MG127_15PL 0xFFFF +#endif +#if (G126PL >= G127PL) || (G126PL == 0) +#define MG127_16PL ~(1 << 5) +#else +#define MG127_16PL 0xFFFF +#endif +#if (G128PL >= G127PL) || (G128PL == 0) +#define MG127_18PL ~(1 << 7) +#else +#define MG127_18PL 0xFFFF +#endif +#define MG127_17PL 0x00BF +#define MG127 (MG127_11PL & MG127_12PL & MG127_13PL & MG127_14PL & \ + MG127_15PL & MG127_16PL & MG127_17PL & MG127_18PL) +// End of MG127: + +// Beginning of MG128: +#if (G121PL >= G128PL) || (G121PL == 0) +#define MG128_11PL ~(1) +#else +#define MG128_11PL 0xFFFF +#endif +#if (G122PL >= G128PL) || (G122PL == 0) +#define MG128_12PL ~(1 << 1) +#else +#define MG128_12PL 0xFFFF +#endif +#if (G123PL >= G128PL) || (G123PL == 0) +#define MG128_13PL ~(1 << 2) +#else +#define MG128_13PL 0xFFFF +#endif +#if (G124PL >= G128PL) || (G124PL == 0) +#define MG128_14PL ~(1 << 3) +#else +#define MG128_14PL 0xFFFF +#endif +#if (G125PL >= G128PL) || (G125PL == 0) +#define MG128_15PL ~(1 << 4) +#else +#define MG128_15PL 0xFFFF +#endif +#if (G126PL >= G128PL) || (G126PL == 0) +#define MG128_16PL ~(1 << 5) +#else +#define MG128_16PL 0xFFFF +#endif +#if (G127PL >= G128PL) || (G127PL == 0) +#define MG128_17PL ~(1 << 6) +#else +#define MG128_17PL 0xFFFF +#endif +#define MG128_18PL 0x007F +#define MG128 (MG128_11PL & MG128_12PL & MG128_13PL & MG128_14PL & \ + MG128_15PL & MG128_16PL & MG128_17PL & MG128_18PL) +// End of MG128: + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // eof + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Adc.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Adc.h new file mode 100644 index 0000000..e6b5e40 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Adc.h @@ -0,0 +1,224 @@ +// TI File $Revision: /main/3 $ +// Checkin $Date: March 19, 2007 15:09:18 $ +//########################################################################### +// +// FILE: DSP281x_Adc.h +// +// TITLE: DSP281x Device ADC Register Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + + +#ifndef DSP281x_ADC_H +#define DSP281x_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + + +//--------------------------------------------------------------------------- +// ADC Individual Register Bit Definitions: + +struct ADCTRL1_BITS { // bits description + Uint16 rsvd1:4; // 3:0 reserved + Uint16 SEQ_CASC:1; // 4 Cascaded sequencer mode + Uint16 SEQ_OVRD:1; // 5 Sequencer override + Uint16 CONT_RUN:1; // 6 Continuous run + Uint16 CPS:1; // 7 ADC core clock pre-scalar + Uint16 ACQ_PS:4; // 11:8 Acquisition window size + Uint16 SUSMOD:2; // 13:12 Emulation suspend mode + Uint16 RESET:1; // 14 ADC reset + Uint16 rsvd2:1; // 15 reserved +}; + + +union ADCTRL1_REG { + Uint16 all; + struct ADCTRL1_BITS bit; +}; + + +struct ADCTRL2_BITS { // bits description + Uint16 EVB_SOC_SEQ2:1; // 0 Event manager B SOC mask for SEQ2 + Uint16 rsvd1:1; // 1 reserved + Uint16 INT_MOD_SEQ2:1; // 2 SEQ2 Interrupt mode + Uint16 INT_ENA_SEQ2:1; // 3 SEQ2 Interrupt enable + Uint16 rsvd2:1; // 4 reserved + Uint16 SOC_SEQ2:1; // 5 Start of conversion for SEQ2 + Uint16 RST_SEQ2:1; // 6 Reset SEQ2 + Uint16 EXT_SOC_SEQ1:1; // 7 External start of conversion for SEQ1 + Uint16 EVA_SOC_SEQ1:1; // 8 Event manager A SOC mask for SEQ1 + Uint16 rsvd3:1; // 9 reserved + Uint16 INT_MOD_SEQ1:1; // 10 SEQ1 Interrupt mode + Uint16 INT_ENA_SEQ1:1; // 11 SEQ1 Interrupt enable + Uint16 rsvd4:1; // 12 reserved + Uint16 SOC_SEQ1:1; // 13 Start of conversion trigger for SEQ1 + Uint16 RST_SEQ1:1; // 14 Restart sequencer 1 + Uint16 EVB_SOC_SEQ:1; // 15 EVB SOC enable +}; + + +union ADCTRL2_REG { + Uint16 all; + struct ADCTRL2_BITS bit; +}; + + +struct ADCASEQSR_BITS { // bits description + Uint16 SEQ1_STATE:4; // 3:0 SEQ1 state + Uint16 SEQ2_STATE:3; // 6:4 SEQ2 state + Uint16 rsvd1:1; // 7 reserved + Uint16 SEQ_CNTR:4; // 11:8 Sequencing counter status + Uint16 rsvd2:4; // 15:12 reserved +}; + +union ADCASEQSR_REG { + Uint16 all; + struct ADCASEQSR_BITS bit; +}; + + +struct ADCMAXCONV_BITS { // bits description + Uint16 MAX_CONV1:4; // 3:0 Max number of conversions + Uint16 MAX_CONV2:3; // 6:4 Max number of conversions + Uint16 rsvd1:9; // 15:7 reserved +}; + +union ADCMAXCONV_REG { + Uint16 all; + struct ADCMAXCONV_BITS bit; +}; + + +struct ADCCHSELSEQ1_BITS { // bits description + Uint16 CONV00:4; // 3:0 Conversion selection 00 + Uint16 CONV01:4; // 7:4 Conversion selection 01 + Uint16 CONV02:4; // 11:8 Conversion selection 02 + Uint16 CONV03:4; // 15:12 Conversion selection 03 +}; + +union ADCCHSELSEQ1_REG{ + Uint16 all; + struct ADCCHSELSEQ1_BITS bit; +}; + +struct ADCCHSELSEQ2_BITS { // bits description + Uint16 CONV04:4; // 3:0 Conversion selection 04 + Uint16 CONV05:4; // 7:4 Conversion selection 05 + Uint16 CONV06:4; // 11:8 Conversion selection 06 + Uint16 CONV07:4; // 15:12 Conversion selection 07 +}; + +union ADCCHSELSEQ2_REG{ + Uint16 all; + struct ADCCHSELSEQ2_BITS bit; +}; + +struct ADCCHSELSEQ3_BITS { // bits description + Uint16 CONV08:4; // 3:0 Conversion selection 08 + Uint16 CONV09:4; // 7:4 Conversion selection 09 + Uint16 CONV10:4; // 11:8 Conversion selection 10 + Uint16 CONV11:4; // 15:12 Conversion selection 11 +}; + +union ADCCHSELSEQ3_REG{ + Uint16 all; + struct ADCCHSELSEQ3_BITS bit; +}; + +struct ADCCHSELSEQ4_BITS { // bits description + Uint16 CONV12:4; // 3:0 Conversion selection 12 + Uint16 CONV13:4; // 7:4 Conversion selection 13 + Uint16 CONV14:4; // 11:8 Conversion selection 14 + Uint16 CONV15:4; // 15:12 Conversion selection 15 +}; + +union ADCCHSELSEQ4_REG { + Uint16 all; + struct ADCCHSELSEQ4_BITS bit; +}; + +struct ADCTRL3_BITS { // bits description + Uint16 SMODE_SEL:1; // 0 Sampling mode select + Uint16 ADCCLKPS:4; // 4:1 ADC core clock divider + Uint16 ADCPWDN:1; // 5 ADC powerdown + Uint16 ADCBGRFDN:2; // 7:6 ADC bandgap/ref power down + Uint16 ADCEXTREF:1; // 8 ADC external reference + Uint16 rsvd1:7; // 15:9 reserved +}; + +union ADCTRL3_REG { + Uint16 all; + struct ADCTRL3_BITS bit; +}; + + +struct ADCST_BITS { // bits description + Uint16 INT_SEQ1:1; // 0 SEQ1 Interrupt flag + Uint16 INT_SEQ2:1; // 1 SEQ2 Interrupt flag + Uint16 SEQ1_BSY:1; // 2 SEQ1 busy status + Uint16 SEQ2_BSY:1; // 3 SEQ2 busy status + Uint16 INT_SEQ1_CLR:1; // 4 SEQ1 Interrupt clear + Uint16 INT_SEQ2_CLR:1; // 5 SEQ2 Interrupt clear + Uint16 EOS_BUF1:1; // 6 End of sequence buffer1 + Uint16 EOS_BUF2:1; // 7 End of sequence buffer2 + Uint16 rsvd1:8; // 15:8 reserved +}; + + +union ADCST_REG { + Uint16 all; + struct ADCST_BITS bit; +}; + + +struct ADC_REGS { + union ADCTRL1_REG ADCTRL1; // ADC Control 1 + union ADCTRL2_REG ADCTRL2; // ADC Control 2 + union ADCMAXCONV_REG ADCMAXCONV; // Max conversions + union ADCCHSELSEQ1_REG ADCCHSELSEQ1; // Channel select sequencing control 1 + union ADCCHSELSEQ2_REG ADCCHSELSEQ2; // Channel select sequencing control 2 + union ADCCHSELSEQ3_REG ADCCHSELSEQ3; // Channel select sequencing control 3 + union ADCCHSELSEQ4_REG ADCCHSELSEQ4; // Channel select sequencing control 4 + union ADCASEQSR_REG ADCASEQSR; // Autosequence status register + Uint16 ADCRESULT0; // Conversion Result Buffer 0 + Uint16 ADCRESULT1; // Conversion Result Buffer 1 + Uint16 ADCRESULT2; // Conversion Result Buffer 2 + Uint16 ADCRESULT3; // Conversion Result Buffer 3 + Uint16 ADCRESULT4; // Conversion Result Buffer 4 + Uint16 ADCRESULT5; // Conversion Result Buffer 5 + Uint16 ADCRESULT6; // Conversion Result Buffer 6 + Uint16 ADCRESULT7; // Conversion Result Buffer 7 + Uint16 ADCRESULT8; // Conversion Result Buffer 8 + Uint16 ADCRESULT9; // Conversion Result Buffer 9 + Uint16 ADCRESULT10; // Conversion Result Buffer 10 + Uint16 ADCRESULT11; // Conversion Result Buffer 11 + Uint16 ADCRESULT12; // Conversion Result Buffer 12 + Uint16 ADCRESULT13; // Conversion Result Buffer 13 + Uint16 ADCRESULT14; // Conversion Result Buffer 14 + Uint16 ADCRESULT15; // Conversion Result Buffer 15 + union ADCTRL3_REG ADCTRL3; // ADC Control 3 + union ADCST_REG ADCST; // ADC Status Register +}; + + +//--------------------------------------------------------------------------- +// ADC External References & Function Declarations: +// +extern volatile struct ADC_REGS AdcRegs; + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + + +#endif // end of DSP281x_ADC_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_CpuTimers.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_CpuTimers.h new file mode 100644 index 0000000..ffe1784 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_CpuTimers.h @@ -0,0 +1,184 @@ +// TI File $Revision: /main/3 $ +// Checkin $Date: July 9, 2009 17:08:54 $ +//########################################################################### +// +// FILE: DSP281x_CpuTimers.h +// +// TITLE: DSP281x CPU 32-bit Timers Register Definitions. +// +// NOTES: CpuTimer2 is reserved for use with DSP BIOS and +// other realtime operating systems. +// +// Do not use this timer in your application if you ever plan +// on integrating DSP-BIOS or another realtime OS. +// +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_CPU_TIMERS_H +#define DSP281x_CPU_TIMERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------------- +// CPU Timer Register Bit Definitions: +// +// +// TCR: Control register bit definitions: +struct TCR_BITS { // bits description + Uint16 rsvd1:4; // 3:0 reserved + Uint16 TSS:1; // 4 Timer Start/Stop + Uint16 TRB:1; // 5 Timer reload + Uint16 rsvd2:4; // 9:6 reserved + Uint16 SOFT:1; // 10 Emulation modes + Uint16 FREE:1; // 11 + Uint16 rsvd3:2; // 12:13 reserved + Uint16 TIE:1; // 14 Output enable + Uint16 TIF:1; // 15 Interrupt flag +}; + +union TCR_REG { + Uint16 all; + struct TCR_BITS bit; +}; + +// TPR: Pre-scale low bit definitions: +struct TPR_BITS { // bits description + Uint16 TDDR:8; // 7:0 Divide-down low + Uint16 PSC:8; // 15:8 Prescale counter low +}; + +union TPR_REG { + Uint16 all; + struct TPR_BITS bit; +}; + +// TPRH: Pre-scale high bit definitions: +struct TPRH_BITS { // bits description + Uint16 TDDRH:8; // 7:0 Divide-down high + Uint16 PSCH:8; // 15:8 Prescale counter high +}; + +union TPRH_REG { + Uint16 all; + struct TPRH_BITS bit; +}; + +// TIM, TIMH: Timer register definitions: +struct TIM_REG { + Uint16 LSW; + Uint16 MSW; +}; + +union TIM_GROUP { + Uint32 all; + struct TIM_REG half; +}; + +// PRD, PRDH: Period register definitions: +struct PRD_REG { + Uint16 LSW; + Uint16 MSW; +}; + +union PRD_GROUP { + Uint32 all; + struct PRD_REG half; +}; + +//--------------------------------------------------------------------------- +// CPU Timer Register File: +// +struct CPUTIMER_REGS { + union TIM_GROUP TIM; // Timer counter register + union PRD_GROUP PRD; // Period register + union TCR_REG TCR; // Timer control register + Uint16 rsvd1; // reserved + union TPR_REG TPR; // Timer pre-scale low + union TPRH_REG TPRH; // Timer pre-scale high +}; + +//--------------------------------------------------------------------------- +// CPU Timer Support Variables: +// +struct CPUTIMER_VARS { + volatile struct CPUTIMER_REGS *RegsAddr; + Uint32 InterruptCount; + float CPUFreqInMHz; + float PeriodInUSec; +}; + +//--------------------------------------------------------------------------- +// Function prototypes and external definitions: +// +void InitCpuTimers(void); +void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period); + +extern volatile struct CPUTIMER_REGS CpuTimer0Regs; +extern struct CPUTIMER_VARS CpuTimer0; + +// CpuTimer2 is reserved when using DSP BIOS & other RTOS +extern volatile struct CPUTIMER_REGS CpuTimer1Regs; +extern volatile struct CPUTIMER_REGS CpuTimer2Regs; + +extern struct CPUTIMER_VARS CpuTimer1; +extern struct CPUTIMER_VARS CpuTimer2; + +//--------------------------------------------------------------------------- +// Usefull Timer Operations: +// +// Start Timer: +#define StartCpuTimer0() CpuTimer0Regs.TCR.bit.TSS = 0 + +// Stop Timer: +#define StopCpuTimer0() CpuTimer0Regs.TCR.bit.TSS = 1 + +// Reload Timer With period Value: +#define ReloadCpuTimer0() CpuTimer0Regs.TCR.bit.TRB = 1 + +// Read 32-Bit Timer Value: +#define ReadCpuTimer0Counter() CpuTimer0Regs.TIM.all + +// Read 32-Bit Period Value: +#define ReadCpuTimer0Period() CpuTimer0Regs.PRD.all + +// CpuTimer2 is reserved by DSP BIOS & other RTOS +// Do not use this timer if you ever plan on integrating +// DSP-BIOS or another realtime OS. + +// Start Timer: +#define StartCpuTimer1() CpuTimer1Regs.TCR.bit.TSS = 0 +#define StartCpuTimer2() CpuTimer2Regs.TCR.bit.TSS = 0 + +// Stop Timer: +#define StopCpuTimer1() CpuTimer1Regs.TCR.bit.TSS = 1 +#define StopCpuTimer2() CpuTimer2Regs.TCR.bit.TSS = 1 + +// Reload Timer With period Value: +#define ReloadCpuTimer1() CpuTimer1Regs.TCR.bit.TRB = 1 +#define ReloadCpuTimer2() CpuTimer2Regs.TCR.bit.TRB = 1 + +// Read 32-Bit Timer Value: +#define ReadCpuTimer1Counter() CpuTimer1Regs.TIM.all +#define ReadCpuTimer2Counter() CpuTimer2Regs.TIM.all + +// Read 32-Bit Period Value: +#define ReadCpuTimer1Period() CpuTimer1Regs.PRD.all +#define ReadCpuTimer2Period() CpuTimer2Regs.PRD.all + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_CPU_TIMERS_H definition + + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_DefaultIsr.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_DefaultIsr.h new file mode 100644 index 0000000..e55f671 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_DefaultIsr.h @@ -0,0 +1,123 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 28, 2005 14:57:38 $ +//########################################################################### +// +// FILE: DSP281x_DefaultIsr.h +// +// TITLE: DSP281x Devices Default Interrupt Service Routines Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_DEFAULT_ISR_H +#define DSP281x_DEFAULT_ISR_H + +#ifdef __cplusplus +extern "C" { +#endif + + +//--------------------------------------------------------------------------- +// Default Interrupt Service Routine Declarations: +// +// The following function prototypes are for the +// default ISR routines used with the default PIE vector table. +// This default vector table is found in the DSP281x_PieVect.h +// file. +// + +// Non-Peripheral Interrupts: +interrupt void INT13_ISR(void); // XINT13 or CPU-Timer 1 +interrupt void INT14_ISR(void); // CPU-Timer2 +interrupt void DATALOG_ISR(void); // Datalogging interrupt +interrupt void RTOSINT_ISR(void); // RTOS interrupt +interrupt void EMUINT_ISR(void); // Emulation interrupt +interrupt void NMI_ISR(void); // Non-maskable interrupt +interrupt void ILLEGAL_ISR(void); // Illegal operation TRAP +interrupt void USER1_ISR(void); // User Defined trap 1 +interrupt void USER2_ISR(void); // User Defined trap 2 +interrupt void USER3_ISR(void); // User Defined trap 3 +interrupt void USER4_ISR(void); // User Defined trap 4 +interrupt void USER5_ISR(void); // User Defined trap 5 +interrupt void USER6_ISR(void); // User Defined trap 6 +interrupt void USER7_ISR(void); // User Defined trap 7 +interrupt void USER8_ISR(void); // User Defined trap 8 +interrupt void USER9_ISR(void); // User Defined trap 9 +interrupt void USER10_ISR(void); // User Defined trap 10 +interrupt void USER11_ISR(void); // User Defined trap 11 +interrupt void USER12_ISR(void); // User Defined trap 12 + +// Group 1 PIE Interrupt Service Routines: +interrupt void PDPINTA_ISR(void); // EV-A +interrupt void PDPINTB_ISR(void); // EV-B +interrupt void XINT1_ISR(void); +interrupt void XINT2_ISR(void); +interrupt void ADCINT_ISR(void); // ADC +interrupt void TINT0_ISR(void); // Timer 0 +interrupt void WAKEINT_ISR(void); // WD + +// Group 2 PIE Interrupt Service Routines: +interrupt void CMP1INT_ISR(void); // EV-A +interrupt void CMP2INT_ISR(void); // EV-A +interrupt void CMP3INT_ISR(void); // EV-A +interrupt void T1PINT_ISR(void); // EV-A +interrupt void T1CINT_ISR(void); // EV-A +interrupt void T1UFINT_ISR(void); // EV-A +interrupt void T1OFINT_ISR(void); // EV-A + +// Group 3 PIE Interrupt Service Routines: +interrupt void T2PINT_ISR(void); // EV-A +interrupt void T2CINT_ISR(void); // EV-A +interrupt void T2UFINT_ISR(void); // EV-A +interrupt void T2OFINT_ISR(void); // EV-A +interrupt void CAPINT1_ISR(void); // EV-A +interrupt void CAPINT2_ISR(void); // EV-A +interrupt void CAPINT3_ISR(void); // EV-A + +// Group 4 PIE Interrupt Service Routines: +interrupt void CMP4INT_ISR(void); // EV-B +interrupt void CMP5INT_ISR(void); // EV-B +interrupt void CMP6INT_ISR(void); // EV-B +interrupt void T3PINT_ISR(void); // EV-B +interrupt void T3CINT_ISR(void); // EV-B +interrupt void T3UFINT_ISR(void); // EV-B +interrupt void T3OFINT_ISR(void); // EV-B + +// Group 5 PIE Interrupt Service Routines: +interrupt void T4PINT_ISR(void); // EV-B +interrupt void T4CINT_ISR(void); // EV-B +interrupt void T4UFINT_ISR(void); // EV-B +interrupt void T4OFINT_ISR(void); // EV-B +interrupt void CAPINT4_ISR(void); // EV-B +interrupt void CAPINT5_ISR(void); // EV-B +interrupt void CAPINT6_ISR(void); // EV-B + +// Group 6 PIE Interrupt Service Routines: +interrupt void SPIRXINTA_ISR(void); // SPI +interrupt void SPITXINTA_ISR(void); // SPI +interrupt void MRINTA_ISR(void); // McBSP +interrupt void MXINTA_ISR(void); // McBSP + + +// Group 9 PIE Interrupt Service Routines: +interrupt void SCIRXINTA_ISR(void); // SCI-A +interrupt void SCITXINTA_ISR(void); // SCI-A +interrupt void SCIRXINTB_ISR(void); // SCI-B +interrupt void SCITXINTB_ISR(void); // SCI-B +interrupt void ECAN0INTA_ISR(void); // eCAN +interrupt void ECAN1INTA_ISR(void); // eCAN + + +// Catch-all for Reserved Locations For testing purposes: +interrupt void PIE_RESERVED(void); // Reserved for test +interrupt void rsvd_ISR(void); // for test + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_DEFAULT_ISR_H definition + diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_DevEmu.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_DevEmu.h new file mode 100644 index 0000000..af37f2e --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_DevEmu.h @@ -0,0 +1,103 @@ +//########################################################################### +// +// FILE: DSP281x_DevEmu.h +// +// TITLE: DSP281x Device Emulation Register Definitions. +// +//########################################################################### +// +// Ver | dd mmm yyyy | Who | Description of changes +// =====|=============|======|=============================================== +// 1.00| 11 Sep 2003 | L.H. | Changes since previous version (v.58 Alpha) +// | | | As of Rev C silicon, DEVICEID is a 16-bit +// | | | register +// | | | Commented out the DFT test registers. These +// | | | are not needed as of Rev C silicon. +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_DEV_EMU_H +#define DSP281x_DEV_EMU_H + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------------- +// Device Emulation Register Bit Definitions: +// +// Device Configuration Register Bit Definitions +struct DEVICECNF_BITS { // bits description + Uint16 rsvd1:3; // 2:0 reserved + Uint16 VMAPS:1; // 3 VMAP Status + Uint16 rsvd2:1; // 4 reserved + Uint16 XRSn:1; // 5 XRSn Signal Status + Uint16 rsvd3:10; // 15:6 + Uint16 rsvd4:3; // 18:6 + Uint16 ENPROT:1; // 19 Enable/Disable pipeline protection + Uint16 rsvd5:12; // 31:20 reserved +}; + +union DEVICECNF_REG { + Uint32 all; + struct DEVICECNF_BITS bit; +}; + + +// Device ID Register Bit Definitions +struct DEVICEID_BITS { // bits description + Uint16 REVID:16; // 15:0 Silicon revision +}; + +union DEVICEID_REG { + Uint16 all; + struct DEVICEID_BITS bit; +}; + +// PARTID Register Bit Definitions +struct PARTID_BITS { // bits description + Uint16 PARTNO:8; // 7:0 Part Number + Uint16 PARTTYPE:8; // 15:8 Part Type +}; + +union PARTID_REG { + Uint16 all; + struct PARTID_BITS bit; +}; + +struct DEV_EMU_REGS { + union DEVICECNF_REG DEVICECNF; // device configuration + union PARTID_REG PARTID; // Part ID + union DEVICEID_REG DEVICEID; // Device ID + Uint16 PROTSTART; // Write-Read protection start + Uint16 PROTRANGE; // Write-Read protection range + Uint16 rsvd2[202]; +// These registers are no longer needed for Rev C and beyond +// Uint16 M0RAMDFT; +// Uint16 M1RAMDFT; +// Uint16 L0RAMDFT; +// Uint16 L1RAMDFT; +// Uint16 H0RAMDFT; +}; + +#define REVID DEVICEID // REVID replaces DEVICEID starting 281x header files v1.10 + // use #define to maintain code compatibility with v1.00 and older + + + +//--------------------------------------------------------------------------- +// Device Emulation Register References & Function Declarations: +// +extern volatile struct DEV_EMU_REGS DevEmuRegs; + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_DEV_EMU_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Device.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Device.h new file mode 100644 index 0000000..e664028 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Device.h @@ -0,0 +1,144 @@ +// TI File $Revision: /main/5 $ +// Checkin $Date: December 17, 2007 13:36:09 $ +//########################################################################### +// +// FILE: DSP281x_Device.h +// +// TITLE: DSP281x Device Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_DEVICE_H +#define DSP281x_DEVICE_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define TARGET 1 +//--------------------------------------------------------------------------- +// User To Select Target Device: + +#define DSP28_F2812 TARGET +#define DSP28_F2811 0 +#define DSP28_F2810 0 + +//--------------------------------------------------------------------------- +// Common CPU Definitions: +// + +extern cregister volatile unsigned int IFR; +extern cregister volatile unsigned int IER; + +#define EINT asm(" clrc INTM") +#define DINT asm(" setc INTM") +#define ERTM asm(" clrc DBGM") +#define DRTM asm(" setc DBGM") +#define EALLOW asm(" EALLOW") +#define EDIS asm(" EDIS") +#define ESTOP0 asm(" ESTOP0") + +#define M_INT1 0x0001 +#define M_INT2 0x0002 +#define M_INT3 0x0004 +#define M_INT4 0x0008 +#define M_INT5 0x0010 +#define M_INT6 0x0020 +#define M_INT7 0x0040 +#define M_INT8 0x0080 +#define M_INT9 0x0100 +#define M_INT10 0x0200 +#define M_INT11 0x0400 +#define M_INT12 0x0800 +#define M_INT13 0x1000 +#define M_INT14 0x2000 +#define M_DLOG 0x4000 +#define M_RTOS 0x8000 + +#define BIT0 0x0001 +#define BIT1 0x0002 +#define BIT2 0x0004 +#define BIT3 0x0008 +#define BIT4 0x0010 +#define BIT5 0x0020 +#define BIT6 0x0040 +#define BIT7 0x0080 +#define BIT8 0x0100 +#define BIT9 0x0200 +#define BIT10 0x0400 +#define BIT11 0x0800 +#define BIT12 0x1000 +#define BIT13 0x2000 +#define BIT14 0x4000 +#define BIT15 0x8000 + +#ifndef NULL + #define NULL 0 +#endif + + +//--------------------------------------------------------------------------- +// For Portability, User Is Recommended To Use Following Data Type Size +// Definitions For 16-bit and 32-Bit Signed/Unsigned Integers: +// + +#ifndef DSP28_DATA_TYPES +#define DSP28_DATA_TYPES +typedef int int16; +typedef long int32; +typedef long long int64; +typedef unsigned int Uint16; +typedef unsigned long Uint32; +typedef unsigned long long Uint64; +typedef float float32; +typedef long double float64; +#endif + +#define LOWORD(l)((short int)( (long int)(l) &0xFFFF)) +#define HIWORD(l)((short int)(((long int)(l)>>16)&0xFFFF)) + +#define LOBYTE(w)((char)( (short int)(w) &0xFF)) +#define HIBYTE(w)((char)(((short int)(w)>>8)&0xFF)) + +#define BYTE3(l)((char)(((long int)(l)>>24)&0xFF)) +#define BYTE2(l)((char)(((long int)(l)>>16)&0xFF)) +#define BYTE1(l)((char)(((long int)(l)>> 8)&0xFF)) +#define BYTE0(l)((char)( (long int)(l) &0xFF)) + +//--------------------------------------------------------------------------- +// Include All Peripheral Header Files: +// + +#include "DSP281x_SysCtrl.h" // System Control/Power Modes +#include "DSP281x_DevEmu.h" // Device Emulation Registers +#include "DSP281x_Xintf.h" // External Interface Registers +#include "DSP281x_CpuTimers.h" // 32-bit CPU Timers +#include "DSP281x_PieCtrl.h" // PIE Control Registers +#include "DSP281x_PieVect.h" // PIE Vector Table +#include "DSP281x_Spi.h" // SPI Registers +#include "DSP281x_Sci.h" // SCI Registers +#include "DSP281x_Mcbsp.h" // McBSP Registers +#include "DSP281x_ECan.h" // Enhanced eCAN Registers +#include "DSP281x_Gpio.h" // General Purpose I/O Registers +#include "DSP281x_Ev.h" // Event Manager Registers +#include "DSP281x_Adc.h" // ADC Registers +#include "DSP281x_XIntrupt.h" // External Interrupts + +#define XCLKIN 24000000 // external oscillator frequency +extern float SYSCLKOUT, LSPCLK, HSPCLK; + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_DEVICE_H definition + + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_ECan.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_ECan.h new file mode 100644 index 0000000..7f26fc5 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_ECan.h @@ -0,0 +1,1163 @@ +//########################################################################### +// +// FILE: DSP281x_ECan.h +// +// TITLE: DSP281x Device eCAN Register Definitions. +// +//########################################################################### +// +// Ver | dd mmm yyyy | Who | Description of changes +// =====|=============|======|=============================================== +// 1.00a| 07/21/2004 | H.J. |(i) Support for errata (as explained in SPRZ193E and above) incorporated +// |(ii) Changed the byte ordering to make it easy to use with the +// | default value of DBO bit (0). + +//########################################################################### + +#ifndef DSP281x_ECAN_H +#define DSP281x_ECAN_H + +/* These 2 lines have been added to support the C callable assembly workaround */ +/* This is to support the workaround for errata (as explained in SPRZ193E and above) */ + +extern void CanDoubleRead(Uint32 *StorePtr, volatile Uint32 *RegPtr); +extern void CanDoubleWrite(volatile Uint32 *RegPtr, Uint32 *LoadPtr); + +#ifdef __cplusplus +extern "C" { +#endif + + +/* --------------------------------------------------- */ +/* eCAN Control & Status Registers */ +/* ----------------------------------------------------*/ + +/* eCAN Mailbox enable register (CANME) bit definitions */ +struct CANME_BITS { // bit description + Uint16 ME0:1; // 0 Enable Mailbox 0 + Uint16 ME1:1; // 1 Enable Mailbox 1 + Uint16 ME2:1; // 2 Enable Mailbox 2 + Uint16 ME3:1; // 3 Enable Mailbox 3 + Uint16 ME4:1; // 4 Enable Mailbox 4 + Uint16 ME5:1; // 5 Enable Mailbox 5 + Uint16 ME6:1; // 6 Enable Mailbox 6 + Uint16 ME7:1; // 7 Enable Mailbox 7 + Uint16 ME8:1; // 8 Enable Mailbox 8 + Uint16 ME9:1; // 9 Enable Mailbox 9 + Uint16 ME10:1; // 10 Enable Mailbox 10 + Uint16 ME11:1; // 11 Enable Mailbox 11 + Uint16 ME12:1; // 12 Enable Mailbox 12 + Uint16 ME13:1; // 13 Enable Mailbox 13 + Uint16 ME14:1; // 14 Enable Mailbox 14 + Uint16 ME15:1; // 15 Enable Mailbox 15 + Uint16 ME16:1; // 16 Enable Mailbox 16 + Uint16 ME17:1; // 17 Enable Mailbox 17 + Uint16 ME18:1; // 18 Enable Mailbox 18 + Uint16 ME19:1; // 19 Enable Mailbox 19 + Uint16 ME20:1; // 20 Enable Mailbox 20 + Uint16 ME21:1; // 21 Enable Mailbox 21 + Uint16 ME22:1; // 22 Enable Mailbox 22 + Uint16 ME23:1; // 23 Enable Mailbox 23 + Uint16 ME24:1; // 24 Enable Mailbox 24 + Uint16 ME25:1; // 25 Enable Mailbox 25 + Uint16 ME26:1; // 26 Enable Mailbox 26 + Uint16 ME27:1; // 27 Enable Mailbox 27 + Uint16 ME28:1; // 28 Enable Mailbox 28 + Uint16 ME29:1; // 29 Enable Mailbox 29 + Uint16 ME30:1; // 30 Enable Mailbox 30 + Uint16 ME31:1; // 31 Enable Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANME_REG { + Uint32 all; + struct CANME_BITS bit; +}; + +/* eCAN Mailbox direction register (CANMD) bit definitions */ +struct CANMD_BITS { // bit description + Uint16 MD0:1; // 0 0 -> Tx 1 -> Rx + Uint16 MD1:1; // 1 0 -> Tx 1 -> Rx + Uint16 MD2:1; // 2 0 -> Tx 1 -> Rx + Uint16 MD3:1; // 3 0 -> Tx 1 -> Rx + Uint16 MD4:1; // 4 0 -> Tx 1 -> Rx + Uint16 MD5:1; // 5 0 -> Tx 1 -> Rx + Uint16 MD6:1; // 6 0 -> Tx 1 -> Rx + Uint16 MD7:1; // 7 0 -> Tx 1 -> Rx + Uint16 MD8:1; // 8 0 -> Tx 1 -> Rx + Uint16 MD9:1; // 9 0 -> Tx 1 -> Rx + Uint16 MD10:1; // 10 0 -> Tx 1 -> Rx + Uint16 MD11:1; // 11 0 -> Tx 1 -> Rx + Uint16 MD12:1; // 12 0 -> Tx 1 -> Rx + Uint16 MD13:1; // 13 0 -> Tx 1 -> Rx + Uint16 MD14:1; // 14 0 -> Tx 1 -> Rx + Uint16 MD15:1; // 15 0 -> Tx 1 -> Rx + Uint16 MD16:1; // 16 0 -> Tx 1 -> Rx + Uint16 MD17:1; // 17 0 -> Tx 1 -> Rx + Uint16 MD18:1; // 18 0 -> Tx 1 -> Rx + Uint16 MD19:1; // 19 0 -> Tx 1 -> Rx + Uint16 MD20:1; // 20 0 -> Tx 1 -> Rx + Uint16 MD21:1; // 21 0 -> Tx 1 -> Rx + Uint16 MD22:1; // 22 0 -> Tx 1 -> Rx + Uint16 MD23:1; // 23 0 -> Tx 1 -> Rx + Uint16 MD24:1; // 24 0 -> Tx 1 -> Rx + Uint16 MD25:1; // 25 0 -> Tx 1 -> Rx + Uint16 MD26:1; // 26 0 -> Tx 1 -> Rx + Uint16 MD27:1; // 27 0 -> Tx 1 -> Rx + Uint16 MD28:1; // 28 0 -> Tx 1 -> Rx + Uint16 MD29:1; // 29 0 -> Tx 1 -> Rx + Uint16 MD30:1; // 30 0 -> Tx 1 -> Rx + Uint16 MD31:1; // 31 0 -> Tx 1 -> Rx + +}; + +/* Allow access to the bit fields or entire register */ +union CANMD_REG { + Uint32 all; + struct CANMD_BITS bit; +}; + +/* eCAN Transmit Request Set register (CANTRS) bit definitions */ +struct CANTRS_BITS { // bit description + Uint16 TRS0:1; // 0 TRS for Mailbox 0 + Uint16 TRS1:1; // 1 TRS for Mailbox 1 + Uint16 TRS2:1; // 2 TRS for Mailbox 2 + Uint16 TRS3:1; // 3 TRS for Mailbox 3 + Uint16 TRS4:1; // 4 TRS for Mailbox 4 + Uint16 TRS5:1; // 5 TRS for Mailbox 5 + Uint16 TRS6:1; // 6 TRS for Mailbox 6 + Uint16 TRS7:1; // 7 TRS for Mailbox 7 + Uint16 TRS8:1; // 8 TRS for Mailbox 8 + Uint16 TRS9:1; // 9 TRS for Mailbox 9 + Uint16 TRS10:1; // 10 TRS for Mailbox 10 + Uint16 TRS11:1; // 11 TRS for Mailbox 11 + Uint16 TRS12:1; // 12 TRS for Mailbox 12 + Uint16 TRS13:1; // 13 TRS for Mailbox 13 + Uint16 TRS14:1; // 14 TRS for Mailbox 14 + Uint16 TRS15:1; // 15 TRS for Mailbox 15 + Uint16 TRS16:1; // 16 TRS for Mailbox 16 + Uint16 TRS17:1; // 17 TRS for Mailbox 17 + Uint16 TRS18:1; // 18 TRS for Mailbox 18 + Uint16 TRS19:1; // 19 TRS for Mailbox 19 + Uint16 TRS20:1; // 20 TRS for Mailbox 20 + Uint16 TRS21:1; // 21 TRS for Mailbox 21 + Uint16 TRS22:1; // 22 TRS for Mailbox 22 + Uint16 TRS23:1; // 23 TRS for Mailbox 23 + Uint16 TRS24:1; // 24 TRS for Mailbox 24 + Uint16 TRS25:1; // 25 TRS for Mailbox 25 + Uint16 TRS26:1; // 26 TRS for Mailbox 26 + Uint16 TRS27:1; // 27 TRS for Mailbox 27 + Uint16 TRS28:1; // 28 TRS for Mailbox 28 + Uint16 TRS29:1; // 29 TRS for Mailbox 29 + Uint16 TRS30:1; // 30 TRS for Mailbox 30 + Uint16 TRS31:1; // 31 TRS for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANTRS_REG { + Uint32 all; + struct CANTRS_BITS bit; +}; + +/* eCAN Transmit Request Reset register (CANTRR) bit definitions */ +struct CANTRR_BITS { // bit description + Uint16 TRR0:1; // 0 TRR for Mailbox 0 + Uint16 TRR1:1; // 1 TRR for Mailbox 1 + Uint16 TRR2:1; // 2 TRR for Mailbox 2 + Uint16 TRR3:1; // 3 TRR for Mailbox 3 + Uint16 TRR4:1; // 4 TRR for Mailbox 4 + Uint16 TRR5:1; // 5 TRR for Mailbox 5 + Uint16 TRR6:1; // 6 TRR for Mailbox 6 + Uint16 TRR7:1; // 7 TRR for Mailbox 7 + Uint16 TRR8:1; // 8 TRR for Mailbox 8 + Uint16 TRR9:1; // 9 TRR for Mailbox 9 + Uint16 TRR10:1; // 10 TRR for Mailbox 10 + Uint16 TRR11:1; // 11 TRR for Mailbox 11 + Uint16 TRR12:1; // 12 TRR for Mailbox 12 + Uint16 TRR13:1; // 13 TRR for Mailbox 13 + Uint16 TRR14:1; // 14 TRR for Mailbox 14 + Uint16 TRR15:1; // 15 TRR for Mailbox 15 + Uint16 TRR16:1; // 16 TRR for Mailbox 16 + Uint16 TRR17:1; // 17 TRR for Mailbox 17 + Uint16 TRR18:1; // 18 TRR for Mailbox 18 + Uint16 TRR19:1; // 19 TRR for Mailbox 19 + Uint16 TRR20:1; // 20 TRR for Mailbox 20 + Uint16 TRR21:1; // 21 TRR for Mailbox 21 + Uint16 TRR22:1; // 22 TRR for Mailbox 22 + Uint16 TRR23:1; // 23 TRR for Mailbox 23 + Uint16 TRR24:1; // 24 TRR for Mailbox 24 + Uint16 TRR25:1; // 25 TRR for Mailbox 25 + Uint16 TRR26:1; // 26 TRR for Mailbox 26 + Uint16 TRR27:1; // 27 TRR for Mailbox 27 + Uint16 TRR28:1; // 28 TRR for Mailbox 28 + Uint16 TRR29:1; // 29 TRR for Mailbox 29 + Uint16 TRR30:1; // 30 TRR for Mailbox 30 + Uint16 TRR31:1; // 31 TRR for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANTRR_REG { + Uint32 all; + struct CANTRR_BITS bit; +}; + +/* eCAN Transmit Acknowledge register (CANTA) bit definitions */ +struct CANTA_BITS { // bit description + Uint16 TA0:1; // 0 TA for Mailbox 0 + Uint16 TA1:1; // 1 TA for Mailbox 1 + Uint16 TA2:1; // 2 TA for Mailbox 2 + Uint16 TA3:1; // 3 TA for Mailbox 3 + Uint16 TA4:1; // 4 TA for Mailbox 4 + Uint16 TA5:1; // 5 TA for Mailbox 5 + Uint16 TA6:1; // 6 TA for Mailbox 6 + Uint16 TA7:1; // 7 TA for Mailbox 7 + Uint16 TA8:1; // 8 TA for Mailbox 8 + Uint16 TA9:1; // 9 TA for Mailbox 9 + Uint16 TA10:1; // 10 TA for Mailbox 10 + Uint16 TA11:1; // 11 TA for Mailbox 11 + Uint16 TA12:1; // 12 TA for Mailbox 12 + Uint16 TA13:1; // 13 TA for Mailbox 13 + Uint16 TA14:1; // 14 TA for Mailbox 14 + Uint16 TA15:1; // 15 TA for Mailbox 15 + Uint16 TA16:1; // 16 TA for Mailbox 16 + Uint16 TA17:1; // 17 TA for Mailbox 17 + Uint16 TA18:1; // 18 TA for Mailbox 18 + Uint16 TA19:1; // 19 TA for Mailbox 19 + Uint16 TA20:1; // 20 TA for Mailbox 20 + Uint16 TA21:1; // 21 TA for Mailbox 21 + Uint16 TA22:1; // 22 TA for Mailbox 22 + Uint16 TA23:1; // 23 TA for Mailbox 23 + Uint16 TA24:1; // 24 TA for Mailbox 24 + Uint16 TA25:1; // 25 TA for Mailbox 25 + Uint16 TA26:1; // 26 TA for Mailbox 26 + Uint16 TA27:1; // 27 TA for Mailbox 27 + Uint16 TA28:1; // 28 TA for Mailbox 28 + Uint16 TA29:1; // 29 TA for Mailbox 29 + Uint16 TA30:1; // 30 TA for Mailbox 30 + Uint16 TA31:1; // 31 TA for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANTA_REG { + Uint32 all; + struct CANTA_BITS bit; +}; + +/* eCAN Transmit Abort Acknowledge register (CANAA) bit definitions */ +struct CANAA_BITS { // bit description + Uint16 AA0:1; // 0 AA for Mailbox 0 + Uint16 AA1:1; // 1 AA for Mailbox 1 + Uint16 AA2:1; // 2 AA for Mailbox 2 + Uint16 AA3:1; // 3 AA for Mailbox 3 + Uint16 AA4:1; // 4 AA for Mailbox 4 + Uint16 AA5:1; // 5 AA for Mailbox 5 + Uint16 AA6:1; // 6 AA for Mailbox 6 + Uint16 AA7:1; // 7 AA for Mailbox 7 + Uint16 AA8:1; // 8 AA for Mailbox 8 + Uint16 AA9:1; // 9 AA for Mailbox 9 + Uint16 AA10:1; // 10 AA for Mailbox 10 + Uint16 AA11:1; // 11 AA for Mailbox 11 + Uint16 AA12:1; // 12 AA for Mailbox 12 + Uint16 AA13:1; // 13 AA for Mailbox 13 + Uint16 AA14:1; // 14 AA for Mailbox 14 + Uint16 AA15:1; // 15 AA for Mailbox 15 + Uint16 AA16:1; // 16 AA for Mailbox 16 + Uint16 AA17:1; // 17 AA for Mailbox 17 + Uint16 AA18:1; // 18 AA for Mailbox 18 + Uint16 AA19:1; // 19 AA for Mailbox 19 + Uint16 AA20:1; // 20 AA for Mailbox 20 + Uint16 AA21:1; // 21 AA for Mailbox 21 + Uint16 AA22:1; // 22 AA for Mailbox 22 + Uint16 AA23:1; // 23 AA for Mailbox 23 + Uint16 AA24:1; // 24 AA for Mailbox 24 + Uint16 AA25:1; // 25 AA for Mailbox 25 + Uint16 AA26:1; // 26 AA for Mailbox 26 + Uint16 AA27:1; // 27 AA for Mailbox 27 + Uint16 AA28:1; // 28 AA for Mailbox 28 + Uint16 AA29:1; // 29 AA for Mailbox 29 + Uint16 AA30:1; // 30 AA for Mailbox 30 + Uint16 AA31:1; // 31 AA for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANAA_REG { + Uint32 all; + struct CANAA_BITS bit; +}; + +/* eCAN Received Message Pending register (CANRMP) bit definitions */ +struct CANRMP_BITS { // bit description + Uint16 RMP0:1; // 0 RMP for Mailbox 0 + Uint16 RMP1:1; // 1 RMP for Mailbox 1 + Uint16 RMP2:1; // 2 RMP for Mailbox 2 + Uint16 RMP3:1; // 3 RMP for Mailbox 3 + Uint16 RMP4:1; // 4 RMP for Mailbox 4 + Uint16 RMP5:1; // 5 RMP for Mailbox 5 + Uint16 RMP6:1; // 6 RMP for Mailbox 6 + Uint16 RMP7:1; // 7 RMP for Mailbox 7 + Uint16 RMP8:1; // 8 RMP for Mailbox 8 + Uint16 RMP9:1; // 9 RMP for Mailbox 9 + Uint16 RMP10:1; // 10 RMP for Mailbox 10 + Uint16 RMP11:1; // 11 RMP for Mailbox 11 + Uint16 RMP12:1; // 12 RMP for Mailbox 12 + Uint16 RMP13:1; // 13 RMP for Mailbox 13 + Uint16 RMP14:1; // 14 RMP for Mailbox 14 + Uint16 RMP15:1; // 15 RMP for Mailbox 15 + Uint16 RMP16:1; // 16 RMP for Mailbox 16 + Uint16 RMP17:1; // 17 RMP for Mailbox 17 + Uint16 RMP18:1; // 18 RMP for Mailbox 18 + Uint16 RMP19:1; // 19 RMP for Mailbox 19 + Uint16 RMP20:1; // 20 RMP for Mailbox 20 + Uint16 RMP21:1; // 21 RMP for Mailbox 21 + Uint16 RMP22:1; // 22 RMP for Mailbox 22 + Uint16 RMP23:1; // 23 RMP for Mailbox 23 + Uint16 RMP24:1; // 24 RMP for Mailbox 24 + Uint16 RMP25:1; // 25 RMP for Mailbox 25 + Uint16 RMP26:1; // 26 RMP for Mailbox 26 + Uint16 RMP27:1; // 27 RMP for Mailbox 27 + Uint16 RMP28:1; // 28 RMP for Mailbox 28 + Uint16 RMP29:1; // 29 RMP for Mailbox 29 + Uint16 RMP30:1; // 30 RMP for Mailbox 30 + Uint16 RMP31:1; // 31 RMP for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANRMP_REG { + Uint32 all; + struct CANRMP_BITS bit; +}; + +/* eCAN Received Message Lost register (CANRML) bit definitions */ +struct CANRML_BITS { // bit description + Uint16 RML0:1; // 0 RML for Mailbox 0 + Uint16 RML1:1; // 1 RML for Mailbox 1 + Uint16 RML2:1; // 2 RML for Mailbox 2 + Uint16 RML3:1; // 3 RML for Mailbox 3 + Uint16 RML4:1; // 4 RML for Mailbox 4 + Uint16 RML5:1; // 5 RML for Mailbox 5 + Uint16 RML6:1; // 6 RML for Mailbox 6 + Uint16 RML7:1; // 7 RML for Mailbox 7 + Uint16 RML8:1; // 8 RML for Mailbox 8 + Uint16 RML9:1; // 9 RML for Mailbox 9 + Uint16 RML10:1; // 10 RML for Mailbox 10 + Uint16 RML11:1; // 11 RML for Mailbox 11 + Uint16 RML12:1; // 12 RML for Mailbox 12 + Uint16 RML13:1; // 13 RML for Mailbox 13 + Uint16 RML14:1; // 14 RML for Mailbox 14 + Uint16 RML15:1; // 15 RML for Mailbox 15 + Uint16 RML16:1; // 16 RML for Mailbox 16 + Uint16 RML17:1; // 17 RML for Mailbox 17 + Uint16 RML18:1; // 18 RML for Mailbox 18 + Uint16 RML19:1; // 19 RML for Mailbox 19 + Uint16 RML20:1; // 20 RML for Mailbox 20 + Uint16 RML21:1; // 21 RML for Mailbox 21 + Uint16 RML22:1; // 22 RML for Mailbox 22 + Uint16 RML23:1; // 23 RML for Mailbox 23 + Uint16 RML24:1; // 24 RML for Mailbox 24 + Uint16 RML25:1; // 25 RML for Mailbox 25 + Uint16 RML26:1; // 26 RML for Mailbox 26 + Uint16 RML27:1; // 27 RML for Mailbox 27 + Uint16 RML28:1; // 28 RML for Mailbox 28 + Uint16 RML29:1; // 29 RML for Mailbox 29 + Uint16 RML30:1; // 30 RML for Mailbox 30 + Uint16 RML31:1; // 31 RML for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANRML_REG { + Uint32 all; + struct CANRML_BITS bit; +}; + +/* eCAN Remote Frame Pending register (CANRFP) bit definitions */ +struct CANRFP_BITS { // bit description + Uint16 RFP0:1; // 0 RFP for Mailbox 0 + Uint16 RFP1:1; // 1 RFP for Mailbox 1 + Uint16 RFP2:1; // 2 RFP for Mailbox 2 + Uint16 RFP3:1; // 3 RFP for Mailbox 3 + Uint16 RFP4:1; // 4 RFP for Mailbox 4 + Uint16 RFP5:1; // 5 RFP for Mailbox 5 + Uint16 RFP6:1; // 6 RFP for Mailbox 6 + Uint16 RFP7:1; // 7 RFP for Mailbox 7 + Uint16 RFP8:1; // 8 RFP for Mailbox 8 + Uint16 RFP9:1; // 9 RFP for Mailbox 9 + Uint16 RFP10:1; // 10 RFP for Mailbox 10 + Uint16 RFP11:1; // 11 RFP for Mailbox 11 + Uint16 RFP12:1; // 12 RFP for Mailbox 12 + Uint16 RFP13:1; // 13 RFP for Mailbox 13 + Uint16 RFP14:1; // 14 RFP for Mailbox 14 + Uint16 RFP15:1; // 15 RFP for Mailbox 15 + Uint16 RFP16:1; // 16 RFP for Mailbox 16 + Uint16 RFP17:1; // 17 RFP for Mailbox 17 + Uint16 RFP18:1; // 18 RFP for Mailbox 18 + Uint16 RFP19:1; // 19 RFP for Mailbox 19 + Uint16 RFP20:1; // 20 RFP for Mailbox 20 + Uint16 RFP21:1; // 21 RFP for Mailbox 21 + Uint16 RFP22:1; // 22 RFP for Mailbox 22 + Uint16 RFP23:1; // 23 RFP for Mailbox 23 + Uint16 RFP24:1; // 24 RFP for Mailbox 24 + Uint16 RFP25:1; // 25 RFP for Mailbox 25 + Uint16 RFP26:1; // 26 RFP for Mailbox 26 + Uint16 RFP27:1; // 27 RFP for Mailbox 27 + Uint16 RFP28:1; // 28 RFP for Mailbox 28 + Uint16 RFP29:1; // 29 RFP for Mailbox 29 + Uint16 RFP30:1; // 30 RFP for Mailbox 30 + Uint16 RFP31:1; // 31 RFP for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANRFP_REG { + Uint32 all; + struct CANRFP_BITS bit; +}; + +/* eCAN Global Acceptance Mask register (CANGAM) bit definitions */ +struct CANGAM_BITS { // bits description + Uint16 GAM150:16; // 15:0 Global acceptance mask bits 0-15 + Uint16 GAM2816:13; // 28:16 Global acceptance mask bits 16-28 + Uint16 rsvd:2; // 30:29 reserved + Uint16 AMI:1; // 31 AMI bit +}; + +/* Allow access to the bit fields or entire register */ +union CANGAM_REG { + Uint32 all; + struct CANGAM_BITS bit; +}; + + +/* eCAN Master Control register (CANMC) bit definitions */ +struct CANMC_BITS { // bits description + Uint16 MBNR:5; // 4:0 MBX # for CDR bit + Uint16 SRES:1; // 5 Soft reset + Uint16 STM:1; // 6 Self-test mode + Uint16 ABO:1; // 7 Auto bus-on + Uint16 CDR:1; // 8 Change data request + Uint16 WUBA:1; // 9 Wake-up on bus activity + Uint16 DBO:1; // 10 Data-byte order + Uint16 PDR:1; // 11 Power-down mode request + Uint16 CCR:1; // 12 Change configuration request + Uint16 SCB:1; // 13 SCC compatibility bit + Uint16 TCC:1; // 14 TSC MSB clear bit + Uint16 MBCC:1; // 15 TSC clear bit thru mailbox 16 + Uint16 SUSP:1; // 16 SUSPEND free/soft bit + Uint16 rsvd:15; // 31:17 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANMC_REG { + Uint32 all; + struct CANMC_BITS bit; +}; + +/* eCAN Bit -timing configuration register (CANBTC) bit definitions */ +struct CANBTC_BITS { // bits description + Uint16 TSEG2REG:3; // 2:0 TSEG2 register value + Uint16 TSEG1REG:4; // 6:3 TSEG1 register value + Uint16 SAM:1; // 7 Sample-point setting + Uint16 SJWREG:2; // 9:8 Synchroniztion Jump Width register value + Uint16 rsvd1:6; // 15:10 reserved + Uint16 BRPREG:8; // 23:16 Baudrate prescaler register value + Uint16 rsvd2:8; // 31:24 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANBTC_REG { + Uint32 all; + struct CANBTC_BITS bit; +}; + +/* eCAN Error & Status register (CANES) bit definitions */ +struct CANES_BITS { // bits description + Uint16 TM:1; // 0 Transmit Mode + Uint16 RM:1; // 1 Receive Mode + Uint16 rsvd1:1; // 2 reserved + Uint16 PDA:1; // 3 Power-down acknowledge + Uint16 CCE:1; // 4 Change Configuration Enable + Uint16 SMA:1; // 5 Suspend Mode Acknowledge + Uint16 rsvd2:10; // 15:6 reserved + Uint16 EW:1; // 16 Warning status + Uint16 EP:1; // 17 Error Passive status + Uint16 BO:1; // 18 Bus-off status + Uint16 ACKE:1; // 19 Acknowledge error + Uint16 SE:1; // 20 Stuff error + Uint16 CRCE:1; // 21 CRC error + Uint16 SA1:1; // 22 Stuck at Dominant error + Uint16 BE:1; // 23 Bit error + Uint16 FE:1; // 24 Framing error + Uint16 rsvd3:7; // 31:25 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANES_REG { + Uint32 all; + struct CANES_BITS bit; +}; + + +/* eCAN Transmit Error Counter register (CANTEC) bit definitions */ +struct CANTEC_BITS { // bits description + Uint16 TEC:8; // 7:0 TEC + Uint16 rsvd1:8; // 15:8 reserved + Uint16 rsvd2:16; // 31:16 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANTEC_REG { + Uint32 all; + struct CANTEC_BITS bit; +}; + +/* eCAN Receive Error Counter register (CANREC) bit definitions */ +struct CANREC_BITS { // bits description + Uint16 REC:8; // 7:0 REC + Uint16 rsvd1:8; // 15:8 reserved + Uint16 rsvd2:16; // 31:16 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANREC_REG { + Uint32 all; + struct CANREC_BITS bit; +}; + +/* eCAN Global Interrupt Flag 0 (CANGIF0) bit definitions */ +struct CANGIF0_BITS { // bits description + Uint16 MIV0:5; // 4:0 Mailbox Interrupt Vector + Uint16 rsvd1:3; // 7:5 reserved + Uint16 WLIF0:1; // 8 Warning level interrupt flag + Uint16 EPIF0:1; // 9 Error-passive interrupt flag + Uint16 BOIF0:1; // 10 Bus-off interrupt flag + Uint16 RMLIF0:1; // 11 Received message lost interrupt flag + Uint16 WUIF0:1; // 12 Wakeup interrupt flag + Uint16 WDIF0:1; // 13 Write denied interrupt flag + Uint16 AAIF0:1; // 14 Abort Ack interrupt flag + Uint16 GMIF0:1; // 15 Global MBX interrupt flag + Uint16 TCOF0:1; // 16 TSC Overflow flag + Uint16 MTOF0:1; // 17 Mailbox Timeout flag + Uint16 rsvd2:14; // 31:18 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANGIF0_REG { + Uint32 all; + struct CANGIF0_BITS bit; +}; + +/* eCAN Global Interrupt Mask register (CANGIM) bit definitions */ +struct CANGIM_BITS { // bits description + Uint16 I0EN:1; // 0 Interrupt 0 enable + Uint16 I1EN:1; // 1 Interrupt 1 enable + Uint16 GIL:1; // 2 Global Interrupt Level + Uint16 rsvd1:5; // 7:3 reserved + Uint16 WLIM:1; // 8 Warning level interrupt mask + Uint16 EPIM:1; // 9 Error-passive interrupt mask + Uint16 BOIM:1; // 10 Bus-off interrupt mask + Uint16 RMLIM:1; // 11 Received message lost interrupt mask + Uint16 WUIM:1; // 12 Wakeup interrupt mask + Uint16 WDIM:1; // 13 Write denied interrupt mask + Uint16 AAIM:1; // 14 Abort Ack interrupt mask + Uint16 rsvd2:1; // 15 reserved + Uint16 TCOM:1; // 16 TSC overflow interrupt mask + Uint16 MTOM:1; // 17 MBX Timeout interrupt mask + Uint16 rsvd3:14; // 31:18 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANGIM_REG { + Uint32 all; + struct CANGIM_BITS bit; +}; + + +/* eCAN Global Interrupt Flag 1 (eCANGIF1) bit definitions */ +struct CANGIF1_BITS { // bits description + Uint16 MIV1:5; // 4:0 Mailbox Interrupt Vector + Uint16 rsvd1:3; // 7:5 reserved + Uint16 WLIF1:1; // 8 Warning level interrupt flag + Uint16 EPIF1:1; // 9 Error-passive interrupt flag + Uint16 BOIF1:1; // 10 Bus-off interrupt flag + Uint16 RMLIF1:1; // 11 Received message lost interrupt flag + Uint16 WUIF1:1; // 12 Wakeup interrupt flag + Uint16 WDIF1:1; // 13 Write denied interrupt flag + Uint16 AAIF1:1; // 14 Abort Ack interrupt flag + Uint16 GMIF1:1; // 15 Global MBX interrupt flag + Uint16 TCOF1:1; // 16 TSC Overflow flag + Uint16 MTOF1:1; // 17 Mailbox Timeout flag + Uint16 rsvd2:14; // 31:18 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANGIF1_REG { + Uint32 all; + struct CANGIF1_BITS bit; +}; + + +/* eCAN Mailbox Interrupt Mask register (CANMIM) bit definitions */ +struct CANMIM_BITS { // bit description + Uint16 MIM0:1; // 0 MIM for Mailbox 0 + Uint16 MIM1:1; // 1 MIM for Mailbox 1 + Uint16 MIM2:1; // 2 MIM for Mailbox 2 + Uint16 MIM3:1; // 3 MIM for Mailbox 3 + Uint16 MIM4:1; // 4 MIM for Mailbox 4 + Uint16 MIM5:1; // 5 MIM for Mailbox 5 + Uint16 MIM6:1; // 6 MIM for Mailbox 6 + Uint16 MIM7:1; // 7 MIM for Mailbox 7 + Uint16 MIM8:1; // 8 MIM for Mailbox 8 + Uint16 MIM9:1; // 9 MIM for Mailbox 9 + Uint16 MIM10:1; // 10 MIM for Mailbox 10 + Uint16 MIM11:1; // 11 MIM for Mailbox 11 + Uint16 MIM12:1; // 12 MIM for Mailbox 12 + Uint16 MIM13:1; // 13 MIM for Mailbox 13 + Uint16 MIM14:1; // 14 MIM for Mailbox 14 + Uint16 MIM15:1; // 15 MIM for Mailbox 15 + Uint16 MIM16:1; // 16 MIM for Mailbox 16 + Uint16 MIM17:1; // 17 MIM for Mailbox 17 + Uint16 MIM18:1; // 18 MIM for Mailbox 18 + Uint16 MIM19:1; // 19 MIM for Mailbox 19 + Uint16 MIM20:1; // 20 MIM for Mailbox 20 + Uint16 MIM21:1; // 21 MIM for Mailbox 21 + Uint16 MIM22:1; // 22 MIM for Mailbox 22 + Uint16 MIM23:1; // 23 MIM for Mailbox 23 + Uint16 MIM24:1; // 24 MIM for Mailbox 24 + Uint16 MIM25:1; // 25 MIM for Mailbox 25 + Uint16 MIM26:1; // 26 MIM for Mailbox 26 + Uint16 MIM27:1; // 27 MIM for Mailbox 27 + Uint16 MIM28:1; // 28 MIM for Mailbox 28 + Uint16 MIM29:1; // 29 MIM for Mailbox 29 + Uint16 MIM30:1; // 30 MIM for Mailbox 30 + Uint16 MIM31:1; // 31 MIM for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANMIM_REG { + Uint32 all; + struct CANMIM_BITS bit; +}; + +/* eCAN Mailbox Interrupt Level register (CANMIL) bit definitions */ +struct CANMIL_BITS { // bit description + Uint16 MIL0:1; // 0 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL1:1; // 1 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL2:1; // 2 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL3:1; // 3 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL4:1; // 4 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL5:1; // 5 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL6:1; // 6 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL7:1; // 7 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL8:1; // 8 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL9:1; // 9 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL10:1; // 10 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL11:1; // 11 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL12:1; // 12 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL13:1; // 13 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL14:1; // 14 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL15:1; // 15 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL16:1; // 16 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL17:1; // 17 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL18:1; // 18 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL19:1; // 19 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL20:1; // 20 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL21:1; // 21 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL22:1; // 22 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL23:1; // 23 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL24:1; // 24 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL25:1; // 25 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL26:1; // 26 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL27:1; // 27 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL28:1; // 28 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL29:1; // 29 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL30:1; // 30 0 -> Int 9.5 1 -> Int 9.6 + Uint16 MIL31:1; // 31 0 -> Int 9.5 1 -> Int 9.6 + +}; + +/* Allow access to the bit fields or entire register */ +union CANMIL_REG { + Uint32 all; + struct CANMIL_BITS bit; +}; + + +/* eCAN Overwrite Protection Control register (CANOPC) bit definitions */ +struct CANOPC_BITS { // bit description + Uint16 OPC0:1; // 0 OPC for Mailbox 0 + Uint16 OPC1:1; // 1 OPC for Mailbox 1 + Uint16 OPC2:1; // 2 OPC for Mailbox 2 + Uint16 OPC3:1; // 3 OPC for Mailbox 3 + Uint16 OPC4:1; // 4 OPC for Mailbox 4 + Uint16 OPC5:1; // 5 OPC for Mailbox 5 + Uint16 OPC6:1; // 6 OPC for Mailbox 6 + Uint16 OPC7:1; // 7 OPC for Mailbox 7 + Uint16 OPC8:1; // 8 OPC for Mailbox 8 + Uint16 OPC9:1; // 9 OPC for Mailbox 9 + Uint16 OPC10:1; // 10 OPC for Mailbox 10 + Uint16 OPC11:1; // 11 OPC for Mailbox 11 + Uint16 OPC12:1; // 12 OPC for Mailbox 12 + Uint16 OPC13:1; // 13 OPC for Mailbox 13 + Uint16 OPC14:1; // 14 OPC for Mailbox 14 + Uint16 OPC15:1; // 15 OPC for Mailbox 15 + Uint16 OPC16:1; // 16 OPC for Mailbox 16 + Uint16 OPC17:1; // 17 OPC for Mailbox 17 + Uint16 OPC18:1; // 18 OPC for Mailbox 18 + Uint16 OPC19:1; // 19 OPC for Mailbox 19 + Uint16 OPC20:1; // 20 OPC for Mailbox 20 + Uint16 OPC21:1; // 21 OPC for Mailbox 21 + Uint16 OPC22:1; // 22 OPC for Mailbox 22 + Uint16 OPC23:1; // 23 OPC for Mailbox 23 + Uint16 OPC24:1; // 24 OPC for Mailbox 24 + Uint16 OPC25:1; // 25 OPC for Mailbox 25 + Uint16 OPC26:1; // 26 OPC for Mailbox 26 + Uint16 OPC27:1; // 27 OPC for Mailbox 27 + Uint16 OPC28:1; // 28 OPC for Mailbox 28 + Uint16 OPC29:1; // 29 OPC for Mailbox 29 + Uint16 OPC30:1; // 30 OPC for Mailbox 30 + Uint16 OPC31:1; // 31 OPC for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANOPC_REG { + Uint32 all; + struct CANOPC_BITS bit; +}; + + +/* eCAN TX I/O Control Register (CANTIOC) bit definitions */ +struct CANTIOC_BITS { // bits description + Uint16 rsvd1:3; // 2:0 reserved + Uint16 TXFUNC:1; // 3 TXFUNC + Uint16 rsvd2:12; // 15:4 reserved + Uint16 rsvd3:16; // 31:16 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANTIOC_REG { + Uint32 all; + struct CANTIOC_BITS bit; +}; + +/* eCAN RX I/O Control Register (CANRIOC) bit definitions */ +struct CANRIOC_BITS { // bits description + Uint16 rsvd1:3; // 2:0 reserved + Uint16 RXFUNC:1; // 3 RXFUNC + Uint16 rsvd2:12; // 15:4 reserved + Uint16 rsvd3:16; // 31:16 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANRIOC_REG { + Uint32 all; + struct CANRIOC_BITS bit; +}; + + +/* eCAN Time-out Control register (CANTOC) bit definitions */ +struct CANTOC_BITS { // bit description + Uint16 TOC0:1; // 0 TOC for Mailbox 0 + Uint16 TOC1:1; // 1 TOC for Mailbox 1 + Uint16 TOC2:1; // 2 TOC for Mailbox 2 + Uint16 TOC3:1; // 3 TOC for Mailbox 3 + Uint16 TOC4:1; // 4 TOC for Mailbox 4 + Uint16 TOC5:1; // 5 TOC for Mailbox 5 + Uint16 TOC6:1; // 6 TOC for Mailbox 6 + Uint16 TOC7:1; // 7 TOC for Mailbox 7 + Uint16 TOC8:1; // 8 TOC for Mailbox 8 + Uint16 TOC9:1; // 9 TOC for Mailbox 9 + Uint16 TOC10:1; // 10 TOC for Mailbox 10 + Uint16 TOC11:1; // 11 TOC for Mailbox 11 + Uint16 TOC12:1; // 12 TOC for Mailbox 12 + Uint16 TOC13:1; // 13 TOC for Mailbox 13 + Uint16 TOC14:1; // 14 TOC for Mailbox 14 + Uint16 TOC15:1; // 15 TOC for Mailbox 15 + Uint16 TOC16:1; // 16 TOC for Mailbox 16 + Uint16 TOC17:1; // 17 TOC for Mailbox 17 + Uint16 TOC18:1; // 18 TOC for Mailbox 18 + Uint16 TOC19:1; // 19 TOC for Mailbox 19 + Uint16 TOC20:1; // 20 TOC for Mailbox 20 + Uint16 TOC21:1; // 21 TOC for Mailbox 21 + Uint16 TOC22:1; // 22 TOC for Mailbox 22 + Uint16 TOC23:1; // 23 TOC for Mailbox 23 + Uint16 TOC24:1; // 24 TOC for Mailbox 24 + Uint16 TOC25:1; // 25 TOC for Mailbox 25 + Uint16 TOC26:1; // 26 TOC for Mailbox 26 + Uint16 TOC27:1; // 27 TOC for Mailbox 27 + Uint16 TOC28:1; // 28 TOC for Mailbox 28 + Uint16 TOC29:1; // 29 TOC for Mailbox 29 + Uint16 TOC30:1; // 30 TOC for Mailbox 30 + Uint16 TOC31:1; // 31 TOC for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANTOC_REG { + Uint32 all; + struct CANTOC_BITS bit; +}; + + +/* eCAN Time-out Status register (CANTOS) bit definitions */ +struct CANTOS_BITS { // bit description + Uint16 TOS0:1; // 0 TOS for Mailbox 0 + Uint16 TOS1:1; // 1 TOS for Mailbox 1 + Uint16 TOS2:1; // 2 TOS for Mailbox 2 + Uint16 TOS3:1; // 3 TOS for Mailbox 3 + Uint16 TOS4:1; // 4 TOS for Mailbox 4 + Uint16 TOS5:1; // 5 TOS for Mailbox 5 + Uint16 TOS6:1; // 6 TOS for Mailbox 6 + Uint16 TOS7:1; // 7 TOS for Mailbox 7 + Uint16 TOS8:1; // 8 TOS for Mailbox 8 + Uint16 TOS9:1; // 9 TOS for Mailbox 9 + Uint16 TOS10:1; // 10 TOS for Mailbox 10 + Uint16 TOS11:1; // 11 TOS for Mailbox 11 + Uint16 TOS12:1; // 12 TOS for Mailbox 12 + Uint16 TOS13:1; // 13 TOS for Mailbox 13 + Uint16 TOS14:1; // 14 TOS for Mailbox 14 + Uint16 TOS15:1; // 15 TOS for Mailbox 15 + Uint16 TOS16:1; // 16 TOS for Mailbox 16 + Uint16 TOS17:1; // 17 TOS for Mailbox 17 + Uint16 TOS18:1; // 18 TOS for Mailbox 18 + Uint16 TOS19:1; // 19 TOS for Mailbox 19 + Uint16 TOS20:1; // 20 TOS for Mailbox 20 + Uint16 TOS21:1; // 21 TOS for Mailbox 21 + Uint16 TOS22:1; // 22 TOS for Mailbox 22 + Uint16 TOS23:1; // 23 TOS for Mailbox 23 + Uint16 TOS24:1; // 24 TOS for Mailbox 24 + Uint16 TOS25:1; // 25 TOS for Mailbox 25 + Uint16 TOS26:1; // 26 TOS for Mailbox 26 + Uint16 TOS27:1; // 27 TOS for Mailbox 27 + Uint16 TOS28:1; // 28 TOS for Mailbox 28 + Uint16 TOS29:1; // 29 TOS for Mailbox 29 + Uint16 TOS30:1; // 30 TOS for Mailbox 30 + Uint16 TOS31:1; // 31 TOS for Mailbox 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANTOS_REG { + Uint32 all; + struct CANTOS_BITS bit; +}; + +/**************************************/ +/* eCAN Control & Status register file */ +/**************************************/ + +struct ECAN_REGS { + union CANME_REG CANME; // Mailbox Enable + union CANMD_REG CANMD; // Mailbox Direction + union CANTRS_REG CANTRS; // Transmit Request Set + union CANTRR_REG CANTRR; // Transmit Request Reset + union CANTA_REG CANTA; // Transmit Acknowledge + union CANAA_REG CANAA; // Abort Acknowledge + union CANRMP_REG CANRMP; // Received Message Pending + union CANRML_REG CANRML; // Received Message Lost + union CANRFP_REG CANRFP; // Remote Frame Pending + union CANGAM_REG CANGAM; // Global Acceptance Mask + union CANMC_REG CANMC; // Master Control + union CANBTC_REG CANBTC; // Bit Timing + union CANES_REG CANES; // Error Status + union CANTEC_REG CANTEC; // Transmit Error Counter + union CANREC_REG CANREC; // Receive Error Counter + union CANGIF0_REG CANGIF0; // Global Interrupt Flag 0 + union CANGIM_REG CANGIM; // Global Interrupt Mask 0 + union CANGIF1_REG CANGIF1; // Global Interrupt Flag 1 + union CANMIM_REG CANMIM; // Mailbox Interrupt Mask + union CANMIL_REG CANMIL; // Mailbox Interrupt Level + union CANOPC_REG CANOPC; // Overwrite Protection Control + union CANTIOC_REG CANTIOC; // TX I/O Control + union CANRIOC_REG CANRIOC; // RX I/O Control + Uint32 CANTSC; // Time-stamp counter + union CANTOC_REG CANTOC; // Time-out Control + union CANTOS_REG CANTOS; // Time-out Status + +}; + +/* --------------------------------------------------- */ +/* eCAN Mailbox Registers */ +/* ----------------------------------------------------*/ + +/* eCAN Message ID (MSGID) bit definitions */ +struct CANMSGID_BITS { // bits description + Uint16 EXTMSGID_L:16; // 0:15 + Uint16 EXTMSGID_H:2; // 16:17 + Uint16 STDMSGID:11; // 18:28 + Uint16 AAM:1; // 29 + Uint16 AME:1; // 30 + Uint16 IDE:1; // 31 + +}; + +/* Allow access to the bit fields or entire register */ +union CANMSGID_REG { + Uint32 all; + struct CANMSGID_BITS bit; +}; + +/* eCAN Message Control Field (MSGCTRL) bit definitions */ +struct CANMSGCTRL_BITS { // bits description + Uint16 DLC:4; // 0:3 + Uint16 RTR:1; // 4 + Uint16 rsvd1:3; // 7:5 reserved + Uint16 TPL:5; // 12:8 + Uint16 rsvd2:3; // 15:13 reserved + Uint16 rsvd3:16; // 31:16 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CANMSGCTRL_REG { + Uint32 all; + struct CANMSGCTRL_BITS bit; +}; + +/* eCAN Message Data Register low (MDR_L) word definitions */ +struct CANMDL_WORDS { // bits description + Uint16 LOW_WORD:16; // 0:15 + Uint16 HI_WORD:16; // 31:16 +}; + +/* eCAN Message Data Register low (MDR_L) byte definitions */ +struct CANMDL_BYTES { // bits description + Uint16 BYTE3:8; // 31:24 + Uint16 BYTE2:8; // 23:16 + Uint16 BYTE1:8; // 15:8 + Uint16 BYTE0:8; // 7:0 +}; + + +/* Allow access to the bit fields or entire register */ + +union CANMDL_REG { + Uint32 all; + struct CANMDL_WORDS word; + struct CANMDL_BYTES byte; +}; + + + +/* eCAN Message Data Register high (MDR_H) word definitions */ +struct CANMDH_WORDS { // bits description + Uint16 LOW_WORD:16; // 0:15 + Uint16 HI_WORD:16; // 31:16 +}; + +/* eCAN Message Data Register low (MDR_H) byte definitions */ +struct CANMDH_BYTES { // bits description + Uint16 BYTE7:8; // 63:56 + Uint16 BYTE6:8; // 55:48 + Uint16 BYTE5:8; // 47:40 + Uint16 BYTE4:8; // 39:32 +}; + +/* Allow access to the bit fields or entire register */ +union CANMDH_REG { + Uint32 all; + struct CANMDH_WORDS word; + struct CANMDH_BYTES byte; +}; + + +struct MBOX { + union CANMSGID_REG MSGID; + union CANMSGCTRL_REG MSGCTRL; + union CANMDL_REG MDL; + union CANMDH_REG MDH; +}; + +/**************************************/ +/* eCAN Mailboxes */ +/**************************************/ + +struct ECAN_MBOXES { + struct MBOX MBOX0; + struct MBOX MBOX1; + struct MBOX MBOX2; + struct MBOX MBOX3; + struct MBOX MBOX4; + struct MBOX MBOX5; + struct MBOX MBOX6; + struct MBOX MBOX7; + struct MBOX MBOX8; + struct MBOX MBOX9; + struct MBOX MBOX10; + struct MBOX MBOX11; + struct MBOX MBOX12; + struct MBOX MBOX13; + struct MBOX MBOX14; + struct MBOX MBOX15; + struct MBOX MBOX16; + struct MBOX MBOX17; + struct MBOX MBOX18; + struct MBOX MBOX19; + struct MBOX MBOX20; + struct MBOX MBOX21; + struct MBOX MBOX22; + struct MBOX MBOX23; + struct MBOX MBOX24; + struct MBOX MBOX25; + struct MBOX MBOX26; + struct MBOX MBOX27; + struct MBOX MBOX28; + struct MBOX MBOX29; + struct MBOX MBOX30; + struct MBOX MBOX31; +}; + +/* eCAN Local Acceptance Mask (LAM) bit definitions */ +struct CANLAM_BITS { // bits description + Uint16 LAM_L:16; // 0:15 + Uint16 LAM_H:13; // 16:28 + Uint16 rsvd1:2; // 29:30 reserved + Uint16 LAMI:1; // 31 +}; + +/* Allow access to the bit fields or entire register */ +union CANLAM_REG { + Uint32 all; + struct CANLAM_BITS bit; +}; + + +/**************************************/ +/* eCAN Local Acceptance Masks */ +/**************************************/ + +/* eCAN LAM File */ +struct LAM_REGS { + union CANLAM_REG LAM0; + union CANLAM_REG LAM1; + union CANLAM_REG LAM2; + union CANLAM_REG LAM3; + union CANLAM_REG LAM4; + union CANLAM_REG LAM5; + union CANLAM_REG LAM6; + union CANLAM_REG LAM7; + union CANLAM_REG LAM8; + union CANLAM_REG LAM9; + union CANLAM_REG LAM10; + union CANLAM_REG LAM11; + union CANLAM_REG LAM12; + union CANLAM_REG LAM13; + union CANLAM_REG LAM14; + union CANLAM_REG LAM15; + union CANLAM_REG LAM16; + union CANLAM_REG LAM17; + union CANLAM_REG LAM18; + union CANLAM_REG LAM19; + union CANLAM_REG LAM20; + union CANLAM_REG LAM21; + union CANLAM_REG LAM22; + union CANLAM_REG LAM23; + union CANLAM_REG LAM24; + union CANLAM_REG LAM25; + union CANLAM_REG LAM26; + union CANLAM_REG LAM27; + union CANLAM_REG LAM28; + union CANLAM_REG LAM29; + union CANLAM_REG LAM30; + union CANLAM_REG LAM31; +}; + +/* Mailbox MOTS File */ + +struct MOTS_REGS { + Uint32 MOTS0; + Uint32 MOTS1; + Uint32 MOTS2; + Uint32 MOTS3; + Uint32 MOTS4; + Uint32 MOTS5; + Uint32 MOTS6; + Uint32 MOTS7; + Uint32 MOTS8; + Uint32 MOTS9; + Uint32 MOTS10; + Uint32 MOTS11; + Uint32 MOTS12; + Uint32 MOTS13; + Uint32 MOTS14; + Uint32 MOTS15; + Uint32 MOTS16; + Uint32 MOTS17; + Uint32 MOTS18; + Uint32 MOTS19; + Uint32 MOTS20; + Uint32 MOTS21; + Uint32 MOTS22; + Uint32 MOTS23; + Uint32 MOTS24; + Uint32 MOTS25; + Uint32 MOTS26; + Uint32 MOTS27; + Uint32 MOTS28; + Uint32 MOTS29; + Uint32 MOTS30; + Uint32 MOTS31; +}; + +/* Mailbox MOTO File */ + +struct MOTO_REGS { + Uint32 MOTO0; + Uint32 MOTO1; + Uint32 MOTO2; + Uint32 MOTO3; + Uint32 MOTO4; + Uint32 MOTO5; + Uint32 MOTO6; + Uint32 MOTO7; + Uint32 MOTO8; + Uint32 MOTO9; + Uint32 MOTO10; + Uint32 MOTO11; + Uint32 MOTO12; + Uint32 MOTO13; + Uint32 MOTO14; + Uint32 MOTO15; + Uint32 MOTO16; + Uint32 MOTO17; + Uint32 MOTO18; + Uint32 MOTO19; + Uint32 MOTO20; + Uint32 MOTO21; + Uint32 MOTO22; + Uint32 MOTO23; + Uint32 MOTO24; + Uint32 MOTO25; + Uint32 MOTO26; + Uint32 MOTO27; + Uint32 MOTO28; + Uint32 MOTO29; + Uint32 MOTO30; + Uint32 MOTO31; +}; + + +//--------------------------------------------------------------------------- +// eCAN External References & Function Declarations: +// +extern volatile struct ECAN_REGS ECanaRegs; +extern volatile struct ECAN_MBOXES ECanaMboxes; +extern volatile struct LAM_REGS ECanaLAMRegs; +extern volatile struct MOTO_REGS ECanaMOTORegs; +extern volatile struct MOTS_REGS ECanaMOTSRegs; + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_ECAN.H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Ev.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Ev.h new file mode 100644 index 0000000..092a5fd --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Ev.h @@ -0,0 +1,654 @@ +// TI File $Revision: /main/4 $ +// Checkin $Date: June 22, 2007 09:30:33 $ +//########################################################################### +// +// FILE: DSP281x_Ev.h +// +// TITLE: DSP281x Device Event Manager Register Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_EV_H +#define DSP281x_EV_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#include "DSP281x_Device.h" +/* --------------------------------------------------- */ +/* F2810/12 Event Manager (EV) GP Timer Registers */ +/* */ +/* ----------------------------------------------------*/ + +/* Overall Timer Control Register */ + +struct GPTCONA_BITS { + Uint16 T1PIN:2; // 1:0 Polarity of GP timer 1 compare + Uint16 T2PIN:2; // 3:2 Polarity of GP timer 2 compare + Uint16 T1CMPOE:1; // 4 Timer1 compare output + Uint16 T2CMPOE:1; // 5 Timer2 compare output + Uint16 TCMPOE:1; // 6 Compare output enable + Uint16 T1TOADC:2; // 8:7 Start ADC with timer 1 event + Uint16 T2TOADC:2; // 10:9 Start ADC with timer 2 event + Uint16 T1CTRIPE:1; // 11 Enable Timer 1 compare trip + Uint16 T2CTRIPE:1; // 12 Enable Timer 2 compare trip + Uint16 T1STAT:1; // 13 GP Timer 1 status (read only) + Uint16 T2STAT:1; // 14 GP Timer 2 status (read only) + Uint16 rsvd:1; // 15 reserved +}; + +/* Allow access to the bit fields or entire register */ +union GPTCONA_REG { + Uint16 all; + struct GPTCONA_BITS bit; +}; + +struct GPTCONB_BITS { + Uint16 T3PIN:2; // 1:0 Polarity of GP timer 3 compare + Uint16 T4PIN:2; // 3:2 Polarity of GP timer 4 compare + Uint16 T3CMPOE:1; // 4 Timer3 compare output + Uint16 T4CMPOE:1; // 5 Timer4 compare output + Uint16 TCMPOE:1; // 6 Compare output enable + Uint16 T3TOADC:2; // 8:7 Start ADC with timer 3 event + Uint16 T4TOADC:2; // 10:9 Start ADC with timer 4 event + Uint16 T3CTRIPE:1; // 11 Timer 3 trip enable + Uint16 T4CTRIPE:1; // 12 Timer 4 trip enable + Uint16 T3STAT:1; // 13 GP Timer 3 status (read only) + Uint16 T4STAT:1; // 14 GP Timer 4 status (read only) + Uint16 rsvd2:1; // 15 reserved +}; + +/* Allow access to the bit fields or entire register */ +union GPTCONB_REG { + Uint16 all; + struct GPTCONB_BITS bit; +}; + +/* Timer 1 Control Register bit defintions */ +struct T1CON_BITS { + Uint16 rsvd1:1; // 0 reserved + Uint16 TECMPR:1; // 1 Timer compare enable + Uint16 TCLD10:2; // 3:2 Timer copare register reload + Uint16 TCLKS10:2; // 5:4 Clock source select + Uint16 TENABLE:1; // 6 Timer enable + Uint16 rsvd2:1; // 7 reserved + Uint16 TPS:3; // 10:8 Input clock prescaler + Uint16 TMODE:2; // 12:11 Count mode selection + Uint16 rsvd:1; // 13 reserved + Uint16 SOFT:1; // 14 Soft emulation control + Uint16 FREE:1; // 15 Free emulation control +}; + +/* Allow access to the bit fields or entire register */ +union T1CON_REG { + Uint16 all; + struct T1CON_BITS bit; +}; + + +/* Timer 2 Control Register bit defintions */ +struct T2CON_BITS { + Uint16 SET1PR:1; // 0 Period register select + Uint16 TECMPR:1; // 1 Timer compare enable + Uint16 TCLD10:2; // 3:2 Timer copare register reload + Uint16 TCLKS10:2; // 5:4 Clock source select + Uint16 TENABLE:1; // 6 Timer enable + Uint16 T2SWT1:1; // 7 Start GP timer 2 with GP timer 1's enable + Uint16 TPS:3; // 10:8 Input clock prescaler + Uint16 TMODE:2; // 12:11 Count mode selection + Uint16 rsvd:1; // 13 reserved + Uint16 SOFT:1; // 14 Soft emulation control + Uint16 FREE:1; // 15 Free emulation control +}; + +/* Allow access to the bit fields or entire register */ +union T2CON_REG { + Uint16 all; + struct T2CON_BITS bit; +}; + +/* Timer 3 Control Register bit defintions */ +struct T3CON_BITS { + Uint16 rsvd1:1; // 0 reserved + Uint16 TECMPR:1; // 1 Timer compare enable + Uint16 TCLD10:2; // 3:2 Timer copare register reload + Uint16 TCLKS10:2; // 5:4 Clock source select + Uint16 TENABLE:1; // 6 Timer enable + Uint16 rsvd2:1; // 7 reserved + Uint16 TPS:3; // 10:8 Input clock prescaler + Uint16 TMODE:2; // 12:11 Count mode selection + Uint16 rsvd:1; // 13 reserved + Uint16 SOFT:1; // 14 Soft emulation control + Uint16 FREE:1; // 15 Free emulation control +}; + +/* Allow access to the bit fields or entire register */ +union T3CON_REG { + Uint16 all; + struct T3CON_BITS bit; +}; + +/* Timer 4 Control Register bit defintions */ +struct T4CON_BITS { + Uint16 SET3PR:1; // 0 Period register select + Uint16 TECMPR:1; // 1 Timer compare enable + Uint16 TCLD10:2; // 3:2 Timer copare register reload + Uint16 TCLKS10:2; // 5:4 Clock source select + Uint16 TENABLE:1; // 6 Timer enable + Uint16 T4SWT3:1; // 7 Start GP timer 2 with GP timer 1's enable + Uint16 TPS:3; // 10:8 Input clock prescaler + Uint16 TMODE:2; // 12:11 Count mode selection + Uint16 rsvd:1; // 13 reserved + Uint16 SOFT:1; // 14 Soft emulation control + Uint16 FREE:1; // 15 Free emulation control +}; + +/* Allow access to the bit fields or entire register */ +union T4CON_REG { + Uint16 all; + struct T4CON_BITS bit; +}; + + +struct EXTCONA_BITS { + Uint16 INDCOE:1; // 0 Independant compare output + Uint16 QEPIQUAL:1; // 1 QEP/CAP3 Index Qual Mode + Uint16 QEPIE:1; // 2 QEP index enable + Uint16 EVSOCE:1; // 3 EvA start of conversion output enable + Uint16 rsvd:12; // 15:4 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EXTCONA_REG { + Uint16 all; + struct EXTCONA_BITS bit; +}; + + +struct EXTCONB_BITS { + Uint16 INDCOE:1; // 0 Independant compare output + Uint16 QEPIQUAL:1; // 1 QEP/CAP3 Index Qual Mode + Uint16 QEPIE:1; // 2 QEP index enable + Uint16 EVSOCE:1; // 3 EvB start of conversion output enable + Uint16 rsvd:12; // 15:4 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EXTCONB_REG { + Uint16 all; + struct EXTCONA_BITS bit; +}; + + + +/* Compare Control Register */ +struct COMCONA_BITS { + Uint16 C1TRIPE:1; // 0 C1TRIP enable + Uint16 C2TRIPE:1; // 1 C2TRIP enable + Uint16 C3TRIPE:1; // 2 C3TRIP eanble + Uint16 rsvd:2; // 4:3 reserved + Uint16 FCMP1OE:1; // 5 Full compare 1 output enable + Uint16 FCMP2OE:1; // 6 Full compare 2 output enable + Uint16 FCMP3OE:1; // 7 Full compare 3 output enable + Uint16 PDPINTASTATUS:1;// 8 Current status of the PDPINTA pin + Uint16 FCOMPOE:1; // 9 Compare output enable + Uint16 ACTRLD:2; // 11:10 Action control register reload + Uint16 SVENABLE:1; // 12 Space vector PWM Mode enable + Uint16 CLD:2; // 14:13 Compare register reload condition + Uint16 CENABLE:1; // 15 Compare enable +}; + +/* Allow access to the bit fields or entire register */ +union COMCONA_REG { + Uint16 all; + struct COMCONA_BITS bit; +}; + +struct COMCONB_BITS { + Uint16 C4TRIPE:1; // 0 C4TRIP enable + Uint16 C5TRIPE:1; // 1 C5TRIP enable + Uint16 C6TRIPE:1; // 2 C6TRIP eanble + Uint16 rsvd:2; // 4:3 reserved + Uint16 FCMP4OE:1; // 5 Full compare 4 output enable + Uint16 FCMP5OE:1; // 6 Full compare 5 output enable + Uint16 FCMP6OE:1; // 7 Full compare 6 output enable + Uint16 PDPINTBSTATUS:1;// 8 Current status of the PDPINTB pin + Uint16 FCOMPOE:1; // 9 Compare output enable + Uint16 ACTRLD:2; // 11:10 Action control register reload + Uint16 SVENABLE:1; // 12 Space vector PWM Mode enable + Uint16 CLD:2; // 14:13 Compare register reload condition + Uint16 CENABLE:1; // 15 Compare enable +}; + +/* Allow access to the bit fields or entire register */ +union COMCONB_REG { + Uint16 all; + struct COMCONB_BITS bit; +}; + +/* Compare Action Control Register bit definitions */ + +struct ACTRA_BITS { + Uint16 CMP1ACT:2; // 1:0 Action on compare output pin 1 CMP1 + Uint16 CMP2ACT:2; // 3:2 Action on compare output pin 2 CMP2 + Uint16 CMP3ACT:2; // 5:4 Action on compare output pin 3 CMP3 + Uint16 CMP4ACT:2; // 7:6 Action on compare output pin 4 CMP4 + Uint16 CMP5ACT:2; // 9:8 Action on compare output pin 5 CMP5 + Uint16 CMP6ACT:2; // 11:10 Action on compare output pin 6 CMP6 + Uint16 D:3; // 14:12 Basic vector bits + Uint16 SVRDIR:1; // 15 Space vecor PWM rotation dir +}; + +/* Allow access to the bit fields or entire register */ +union ACTRA_REG { + Uint16 all; + struct ACTRA_BITS bit; +}; + +struct ACTRB_BITS { + Uint16 CMP7ACT:2; // 1:0 Action on compare output pin 7 CMP7 + Uint16 CMP8ACT:2; // 3:2 Action on compare output pin 8 CMP8 + Uint16 CMP9ACT:2; // 5:4 Action on compare output pin 9 CMP9 + Uint16 CMP10ACT:2; // 7:6 Action on compare output pin 10 CMP10 + Uint16 CMP11ACT:2; // 9:8 Action on compare output pin 11 CMP11 + Uint16 CMP12ACT:2; // 11:10 Action on compare output pin 12 CMP12 + Uint16 D:3; // 14:12 Basic vector bits + Uint16 SVRDIR:1; // 15 Space vecor PWM rotation dir +}; + +/* Allow access to the bit fields or entire register */ +union ACTRB_REG { + Uint16 all; + struct ACTRB_BITS bit; +}; + +/* Dead-Band Timer Control register bit definitions */ +struct DBTCON_BITS { + Uint16 rsvd1:2; // 1:0 reserved + Uint16 DBTPS:3; // 4:2 Dead-Band timer prescaler + Uint16 EDBT1:1; // 5 Dead-Band timer 1 enable + Uint16 EDBT2:1; // 6 Dead-Band timer 2 enable + Uint16 EDBT3:1; // 7 Dead-Band timer 3 enable + Uint16 DBT:4; // 11:8 Dead-Band timer period + Uint16 rsvd2:4; // 15:12 reserved +}; + +/* Allow access to the bit fields or entire register */ +union DBTCON_REG { + Uint16 all; + struct DBTCON_BITS bit; +}; + + +/* Capture Control register bit definitions */ +struct CAPCONA_BITS { + Uint16 rsvd1:2; // 1:0 reserved + Uint16 CAP3EDGE:2; // 3:2 Edge Detection for Unit 3 + Uint16 CAP2EDGE:2; // 5:4 Edge Detection for Unit 2 + Uint16 CAP1EDGE:2; // 7:6 Edge Detection for Unit 1 + Uint16 CAP3TOADC:1; // 8 Unit 3 starts the ADC + Uint16 CAP12TSEL:1; // 9 GP Timer selection for Units 1 and 2 + Uint16 CAP3TSEL:1; // 10 GP Timer selection for Unit 3 + Uint16 rsvd2:1; // 11 reserved + Uint16 CAP3EN:1; // 12 Capture Unit 3 enable + Uint16 CAP12EN:2; // 14:13 Capture Unit 1 and 2 enable + Uint16 CAPRES:1; // 15 Capture reset (always reads 0) +}; + +/* Allow access to the bit fields or entire register */ +union CAPCONA_REG { + Uint16 all; + struct CAPCONA_BITS bit; +}; + + +/* Control register bit definitions */ +struct CAPCONB_BITS { + Uint16 rsvd1:2; // 1:0 reserved + Uint16 CAP6EDGE:2; // 3:2 Edge Detection for Unit 6 + Uint16 CAP5EDGE:2; // 5:4 Edge Detection for Unit 5 + Uint16 CAP4EDGE:2; // 7:6 Edge Detection for Unit 4 + Uint16 CAP6TOADC:1; // 8 Unit 6 starts the ADC + Uint16 CAP45TSEL:1; // 9 GP Timer selection for Units 4 and 5 + Uint16 CAP6TSEL:1; // 10 GP Timer selection for Unit 6 + Uint16 rsvd2:1; // 11 reserved + Uint16 CAP6EN:1; // 12 Capture Unit 6 control + Uint16 CAP45EN:2; // 14:13 Capture Unit 4 and 5 control + Uint16 CAPRES:1; // 15 Capture reset (always reads 0) +}; + +/* Allow access to the bit fields or entire register */ +union CAPCONB_REG { + Uint16 all; + struct CAPCONB_BITS bit; +}; + +/* Capture FIFO Status Register bit definitions */ +struct CAPFIFOA_BITS { + Uint16 rsvd1:8; // 7:0 reserved + Uint16 CAP1FIFO:2; // 9:8 CAP1 FIFO status + Uint16 CAP2FIFO:2; // 11:10 CAP2 FIFO status + Uint16 CAP3FIFO:2; // 13:12 CAP2 FIFO status + Uint16 rsvd2:2; // 15:14 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CAPFIFOA_REG { + Uint16 all; + struct CAPFIFOA_BITS bit; +}; + +/* Capture FIFO Status Register bit definitions */ +struct CAPFIFOB_BITS { + Uint16 rsvd1:8; // 7:0 reserved + Uint16 CAP4FIFO:2; // 9:8 CAP4 FIFO status + Uint16 CAP5FIFO:2; // 11:10 CAP5 FIFO status + Uint16 CAP6FIFO:2; // 13:12 CAP6 FIFO status + Uint16 rsvd2:2; // 15:14 reserved +}; + +/* Allow access to the bit fields or entire register */ +union CAPFIFOB_REG { + Uint16 all; + struct CAPFIFOB_BITS bit; +}; + +/* Interrupt Mask Register bit definitions */ +struct EVAIMRA_BITS { + Uint16 PDPINTA:1; // 0 Enable PDPINTA + Uint16 CMP1INT:1; // 1 Enable + Uint16 CMP2INT:1; // 2 Enable + Uint16 CMP3INT:1; // 3 Enable + Uint16 rsvd1:3; // 6:4 reserved + Uint16 T1PINT:1; // 7 Enable + Uint16 T1CINT:1; // 8 Enable + Uint16 T1UFINT:1; // 9 Enable + Uint16 T1OFINT:1; // 10 Enable + Uint16 rsvd2:5; // 15:11 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVAIMRA_REG { + Uint16 all; + struct EVAIMRA_BITS bit; +}; + +/* Interrupt Mask Register bit definitions */ +struct EVBIMRA_BITS { + Uint16 PDPINTB:1; // 0 Enable PDPINTB + Uint16 CMP4INT:1; // 1 Enable + Uint16 CMP5INT:1; // 2 Enable + Uint16 CMP6INT:1; // 3 Enable + Uint16 rsvd1:3; // 6:4 reserved + Uint16 T3PINT:1; // 7 Enable + Uint16 T3CINT:1; // 8 Enable + Uint16 T3UFINT:1; // 9 Enable + Uint16 T3OFINT:1; // 10 Enable + Uint16 rsvd2:5; // 15:11 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVBIMRA_REG { + Uint16 all; + struct EVBIMRA_BITS bit; +}; + +struct EVAIMRB_BITS { + Uint16 T2PINT:1; // 0 Enable + Uint16 T2CINT:1; // 1 Enable + Uint16 T2UFINT:1; // 2 Enable + Uint16 T2OFINT:1; // 3 Enable + Uint16 rsvd1:12; // 15:4 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVAIMRB_REG { + Uint16 all; + struct EVAIMRB_BITS bit; +}; + +struct EVBIMRB_BITS { + Uint16 T4PINT:1; // 0 Enable + Uint16 T4CINT:1; // 1 Enable + Uint16 T4UFINT:1; // 2 Enable + Uint16 T4OFINT:1; // 3 Enable + Uint16 rsvd1:12; // 15:4 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVBIMRB_REG { + Uint16 all; + struct EVBIMRB_BITS bit; +}; + +struct EVAIMRC_BITS { + Uint16 CAP1INT:1; // 0 Enable + Uint16 CAP2INT:1; // 1 Enable + Uint16 CAP3INT:1; // 2 Enable + Uint16 rsvd1:13; // 15:3 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVAIMRC_REG { + Uint16 all; + struct EVAIMRC_BITS bit; +}; + +struct EVBIMRC_BITS { + Uint16 CAP4INT:1; // 0 Enable + Uint16 CAP5INT:1; // 1 Enable + Uint16 CAP6INT:1; // 2 Enable + Uint16 rsvd1:13; // 15:3 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVBIMRC_REG { + Uint16 all; + struct EVBIMRC_BITS bit; +}; + +/* Interrupt Flag Register bit definitions */ +struct EVAIFRA_BITS { + Uint16 PDPINTA:1; // 0 Flag PDPINTA + Uint16 CMP1INT:1; // 1 Flag + Uint16 CMP2INT:1; // 2 Flag + Uint16 CMP3INT:1; // 3 Flag + Uint16 rsvd1:3; // 6:4 reserved + Uint16 T1PINT:1; // 7 Flag + Uint16 T1CINT:1; // 8 Flag + Uint16 T1UFINT:1; // 9 Flag + Uint16 T1OFINT:1; // 10 Flag + Uint16 rsvd2:5; // 15:11 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVAIFRA_REG { + Uint16 all; + struct EVAIMRA_BITS bit; +}; + +/* Interrupt Mask Register bit definitions */ +struct EVBIFRA_BITS { + Uint16 PDPINTB:1; // 0 Flag PDPINTB + Uint16 CMP4INT:1; // 1 Flag + Uint16 CMP5INT:1; // 2 Flag + Uint16 CMP6INT:1; // 3 Flag + Uint16 rsvd1:3; // 6:4 reserved + Uint16 T3PINT:1; // 7 Flag + Uint16 T3CINT:1; // 8 Flag + Uint16 T3UFINT:1; // 9 Flag + Uint16 T3OFINT:1; // 10 Flag + Uint16 rsvd2:5; // 15:11 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVBIFRA_REG { + Uint16 all; + struct EVBIFRA_BITS bit; +}; + +struct EVAIFRB_BITS { + Uint16 T2PINT:1; // 0 Flag + Uint16 T2CINT:1; // 1 Flag + Uint16 T2UFINT:1; // 2 Flag + Uint16 T2OFINT:1; // 3 Flag + Uint16 rsvd1:12; // 15:4 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVAIFRB_REG { + Uint16 all; + struct EVAIFRB_BITS bit; +}; + +struct EVBIFRB_BITS { + Uint16 T4PINT:1; // 0 Flag + Uint16 T4CINT:1; // 1 Flag + Uint16 T4UFINT:1; // 2 Flag + Uint16 T4OFINT:1; // 3 Flag + Uint16 rsvd1:12; // 15:4 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVBIFRB_REG { + Uint16 all; + struct EVBIFRB_BITS bit; +}; + +struct EVAIFRC_BITS { + Uint16 CAP1INT:1; // 0 Flag + Uint16 CAP2INT:1; // 1 Flag + Uint16 CAP3INT:1; // 2 Flag + Uint16 rsvd1:13; // 15:3 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVAIFRC_REG { + Uint16 all; + struct EVAIFRC_BITS bit; +}; + +struct EVBIFRC_BITS { + Uint16 CAP4INT:1; // 0 Flag + Uint16 CAP5INT:1; // 1 Flag + Uint16 CAP6INT:1; // 2 Flag + Uint16 rsvd1:13; // 15:3 reserved +}; + +/* Allow access to the bit fields or entire register */ +union EVBIFRC_REG { + Uint16 all; + struct EVBIFRC_BITS bit; +}; + +/* EVA Register File */ + +struct EVA_REGS { + union GPTCONA_REG GPTCONA; //0x7400 + Uint16 T1CNT; //0x7401 + Uint16 T1CMPR; //0x7402 + Uint16 T1PR; //0x7403 + union T1CON_REG T1CON; //0x7404 + Uint16 T2CNT; //0x7405 + Uint16 T2CMPR; //0x7406 + Uint16 T2PR; //0x7407 + union T2CON_REG T2CON; //0x7408 + union EXTCONA_REG EXTCONA; //0x7409 + Uint16 rsvd1[7]; //0x740A-10 + union COMCONA_REG COMCONA; //0x7411 + Uint16 rsvd2; //0x7412 + union ACTRA_REG ACTRA; //0x7413 + Uint16 rsvd3; //0x7414 + union DBTCON_REG DBTCONA; //0x7415 + Uint16 rsvd4; //0x7416 + Uint16 CMPR1; //0x7417 + Uint16 CMPR2; //0x7418 + Uint16 CMPR3; //0x7419 + Uint16 rsvd5[6]; //0x741A-F + union CAPCONA_REG CAPCONA; //0x7420 + Uint16 rsvd6; //0x7421 + union CAPFIFOA_REG CAPFIFOA; //0x7422 + Uint16 CAP1FIFO; //0x7423 + Uint16 CAP2FIFO; //0x7424 + Uint16 CAP3FIFO; //0x7425 + Uint16 rsvd7; //0x7426 + Uint16 CAP1FBOT; //0x7427 + Uint16 CAP2FBOT; //0x7428 + Uint16 CAP3FBOT; //0x7429 + Uint16 rsvd8[2]; //0x742A-B + union EVAIMRA_REG EVAIMRA; //0x742C + union EVAIMRB_REG EVAIMRB; //0x742D + union EVAIMRC_REG EVAIMRC; //0x742E + union EVAIFRA_REG EVAIFRA; //0x742F + union EVAIFRB_REG EVAIFRB; //0x7430 + union EVAIFRC_REG EVAIFRC; //0x7431 +}; + + +/* EVB Register File */ + +struct EVB_REGS { + union GPTCONB_REG GPTCONB; //0x7500 + Uint16 T3CNT; //0x7501 + Uint16 T3CMPR; //0x7502 + Uint16 T3PR; //0x7503 + union T3CON_REG T3CON; //0x7504 + Uint16 T4CNT; //0x7505 + Uint16 T4CMPR; //0x7506 + Uint16 T4PR; //0x7507 + union T4CON_REG T4CON; //0x7508 + union EXTCONB_REG EXTCONB; //0x7509 + Uint16 rsvd1[7]; //0x750A-10 + union COMCONB_REG COMCONB; //0x7511 + Uint16 rsvd2; //0x7512 + union ACTRB_REG ACTRB; //0x7513 + Uint16 rsvd3; //0x7514 + union DBTCON_REG DBTCONB; //0x7515 + Uint16 rsvd4; //0x7516 + Uint16 CMPR4; //0x7517 + Uint16 CMPR5; //0x7518 + Uint16 CMPR6; //0x7519 + Uint16 rsvd5[6]; //0x751A-F + union CAPCONB_REG CAPCONB; //0x7520 + Uint16 rsvd6; //0x7521 + union CAPFIFOB_REG CAPFIFOB; //0x7522 + Uint16 CAP4FIFO; //0x7523 + Uint16 CAP5FIFO; //0x7524 + Uint16 CAP6FIFO; //0x7525 + Uint16 rsvd7; //0x7526 + Uint16 CAP4FBOT; //0x7527 + Uint16 CAP5FBOT; //0x7528 + Uint16 CAP6FBOT; //0x7529 + Uint16 rsvd8[2]; //0x752A-B + union EVBIMRA_REG EVBIMRA; //0x752C + union EVBIMRB_REG EVBIMRB; //0x752D + union EVBIMRC_REG EVBIMRC; //0x752E + union EVBIFRA_REG EVBIFRA; //0x752F + union EVBIFRB_REG EVBIFRB; //0x7530 + union EVBIFRC_REG EVBIFRC; //0x7531 +}; + + + +//--------------------------------------------------------------------------- +// Function prototypes and external definitions: +// + +extern volatile struct EVA_REGS EvaRegs; +extern volatile struct EVB_REGS EvbRegs; + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_EV.H definition + + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Gpio.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Gpio.h new file mode 100644 index 0000000..fb3d751 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Gpio.h @@ -0,0 +1,1034 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 28, 2005 14:57:26 $ +//########################################################################### +// +// FILE: DSP281x_Gpio.h +// +// TITLE: DSP281x General Purpose I/O Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_GPIO_H +#define DSP281x_GPIO_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +//---------------------------------------------------- +// General purpose I/O (GPIO) Register Bit Definitions + +//---------------------------------------------------- +// GPIO A mux control register bit definitions */ +// +// +struct GPAMUX_BITS { // bits description + Uint16 PWM1_GPIOA0:1; // 0 + Uint16 PWM2_GPIOA1:1; // 1 + Uint16 PWM3_GPIOA2:1; // 2 + Uint16 PWM4_GPIOA3:1; // 3 + Uint16 PWM5_GPIOA4:1; // 4 + Uint16 PWM6_GPIOA5:1; // 5 + Uint16 T1PWM_GPIOA6:1; // 6 + Uint16 T2PWM_GPIOA7:1; // 7 + Uint16 CAP1Q1_GPIOA8:1; // 8 + Uint16 CAP2Q2_GPIOA9:1; // 9 + Uint16 CAP3QI1_GPIOA10:1; // 10 + Uint16 TDIRA_GPIOA11:1; // 11 + Uint16 TCLKINA_GPIOA12:1; // 12 + Uint16 C1TRIP_GPIOA13:1; // 13 + Uint16 C2TRIP_GPIOA14:1; // 14 + Uint16 C3TRIP_GPIOA15:1; // 15 + +}; + +union GPAMUX_REG { + Uint16 all; + struct GPAMUX_BITS bit; +}; + + + +//--------------------------------------------------------------------------------------- +// GPIO A Direction control register bit definitions +// +// +struct GPADIR_BITS { // bits description + Uint16 GPIOA0:1; // 0 + Uint16 GPIOA1:1; // 1 + Uint16 GPIOA2:1; // 2 + Uint16 GPIOA3:1; // 3 + Uint16 GPIOA4:1; // 4 + Uint16 GPIOA5:1; // 5 + Uint16 GPIOA6:1; // 6 + Uint16 GPIOA7:1; // 7 + Uint16 GPIOA8:1; // 8 + Uint16 GPIOA9:1; // 9 + Uint16 GPIOA10:1; // 10 + Uint16 GPIOA11:1; // 11 + Uint16 GPIOA12:1; // 12 + Uint16 GPIOA13:1; // 13 + Uint16 GPIOA14:1; // 14 + Uint16 GPIOA15:1; // 15 + +}; + +union GPADIR_REG { + Uint16 all; + struct GPADIR_BITS bit; +}; + +//---------------------------------- +// GPA Qualregister bit definitions +// +// + +struct GPAQUAL_BITS { // bits description + Uint16 QUALPRD:8; // 0:7 Qualification Sampling Period + Uint16 rsvd1:8; // 15:8 reserved +}; + +union GPAQUAL_REG { + Uint16 all; + struct GPAQUAL_BITS bit; +}; + + +//--------------------------------------------------------------------------------------- +// GPIO A Data register bit definitions +// +// +struct GPADAT_BITS { // bits description + Uint16 GPIOA0:1; // 0 + Uint16 GPIOA1:1; // 1 + Uint16 GPIOA2:1; // 2 + Uint16 GPIOA3:1; // 3 + Uint16 GPIOA4:1; // 4 + Uint16 GPIOA5:1; // 5 + Uint16 GPIOA6:1; // 6 + Uint16 GPIOA7:1; // 7 + Uint16 GPIOA8:1; // 8 + Uint16 GPIOA9:1; // 9 + Uint16 GPIOA10:1; // 10 + Uint16 GPIOA11:1; // 11 + Uint16 GPIOA12:1; // 12 + Uint16 GPIOA13:1; // 13 + Uint16 GPIOA14:1; // 14 + Uint16 GPIOA15:1; // 15 + +}; + +union GPADAT_REG { + Uint16 all; + struct GPADAT_BITS bit; +}; + + +//--------------------------------------------------------------------------------------- +// GPIO A Data set bit definitions +// +// +struct GPASET_BITS { // bits description + Uint16 GPIOA0:1; // 0 + Uint16 GPIOA1:1; // 1 + Uint16 GPIOA2:1; // 2 + Uint16 GPIOA3:1; // 3 + Uint16 GPIOA4:1; // 4 + Uint16 GPIOA5:1; // 5 + Uint16 GPIOA6:1; // 6 + Uint16 GPIOA7:1; // 7 + Uint16 GPIOA8:1; // 8 + Uint16 GPIOA9:1; // 9 + Uint16 GPIOA10:1; // 10 + Uint16 GPIOA11:1; // 11 + Uint16 GPIOA12:1; // 12 + Uint16 GPIOA13:1; // 13 + Uint16 GPIOA14:1; // 14 + Uint16 GPIOA15:1; // 15 + +}; + +union GPASET_REG { + Uint16 all; + struct GPASET_BITS bit; +}; + + + +//--------------------------------------------------------------------------------------- +// GPIO A Data clear register bit definitions +// +// +struct GPACLEAR_BITS { // bits description + Uint16 GPIOA0:1; // 0 + Uint16 GPIOA1:1; // 1 + Uint16 GPIOA2:1; // 2 + Uint16 GPIOA3:1; // 3 + Uint16 GPIOA4:1; // 4 + Uint16 GPIOA5:1; // 5 + Uint16 GPIOA6:1; // 6 + Uint16 GPIOA7:1; // 7 + Uint16 GPIOA8:1; // 8 + Uint16 GPIOA9:1; // 9 + Uint16 GPIOA10:1; // 10 + Uint16 GPIOA11:1; // 11 + Uint16 GPIOA12:1; // 12 + Uint16 GPIOA13:1; // 13 + Uint16 GPIOA14:1; // 14 + Uint16 GPIOA15:1; // 15 + +}; + +union GPACLEAR_REG { + Uint16 all; + struct GPACLEAR_BITS bit; +}; + +//--------------------------------------------------------------------------------------- +// GPIO A Data toggle register bit definitions +// +// +struct GPATOGGLE_BITS { // bits description + Uint16 GPIOA0:1; // 0 + Uint16 GPIOA1:1; // 1 + Uint16 GPIOA2:1; // 2 + Uint16 GPIOA3:1; // 3 + Uint16 GPIOA4:1; // 4 + Uint16 GPIOA5:1; // 5 + Uint16 GPIOA6:1; // 6 + Uint16 GPIOA7:1; // 7 + Uint16 GPIOA8:1; // 8 + Uint16 GPIOA9:1; // 9 + Uint16 GPIOA10:1; // 10 + Uint16 GPIOA11:1; // 11 + Uint16 GPIOA12:1; // 12 + Uint16 GPIOA13:1; // 13 + Uint16 GPIOA14:1; // 14 + Uint16 GPIOA15:1; // 15 + +}; + +union GPATOGGLE_REG { + Uint16 all; + struct GPATOGGLE_BITS bit; +}; + + + +//--------------------------------------------------------------------------------- +// GPIO B mux control register bit definitions +// +// +struct GPBMUX_BITS { // bits description + Uint16 PWM7_GPIOB0:1; // 0 + Uint16 PWM8_GPIOB1:1; // 1 + Uint16 PWM9_GPIOB2:1; // 2 + Uint16 PWM10_GPIOB3:1; // 3 + Uint16 PWM11_GPIOB4:1; // 4 + Uint16 PWM12_GPIOB5:1; // 5 + Uint16 T3PWM_GPIOB6:1; // 6 + Uint16 T4PWM_GPIOB7:1; // 7 + Uint16 CAP4Q1_GPIOB8:1; // 8 + Uint16 CAP5Q2_GPIOB9:1; // 9 + Uint16 CAP6QI2_GPIOB10:1; // 10 + Uint16 TDIRB_GPIOB11:1; // 11 + Uint16 TCLKINB_GPIOB12:1; // 12 + Uint16 C4TRIP_GPIOB13:1; // 13 + Uint16 C5TRIP_GPIOB14:1; // 14 + Uint16 C6TRIP_GPIOB15:1; // 15 + +}; + +union GPBMUX_REG { + Uint16 all; + struct GPBMUX_BITS bit; +}; + +//--------------------------------------------------------------------------------------- +// GPIO B Direction control register bit definitions +// +// +struct GPBDIR_BITS { // bits description + Uint16 GPIOB0:1; // 0 + Uint16 GPIOB1:1; // 1 + Uint16 GPIOB2:1; // 2 + Uint16 GPIOB3:1; // 3 + Uint16 GPIOB4:1; // 4 + Uint16 GPIOB5:1; // 5 + Uint16 GPIOB6:1; // 6 + Uint16 GPIOB7:1; // 7 + Uint16 GPIOB8:1; // 8 + Uint16 GPIOB9:1; // 9 + Uint16 GPIOB10:1; // 10 + Uint16 GPIOB11:1; // 11 + Uint16 GPIOB12:1; // 12 + Uint16 GPIOB13:1; // 13 + Uint16 GPIOB14:1; // 14 + Uint16 GPIOB15:1; // 15 + +}; + +union GPBDIR_REG { + Uint16 all; + struct GPBDIR_BITS bit; +}; + +//----------------------------------- +// GPB Qualregister bit definitions +// +// + +struct GPBQUAL_BITS { // bits description + Uint16 QUALPRD:8; // 0:7 Qualification Sampling Period + Uint16 rsvd1:8; // 15:8 reserved +}; + +union GPBQUAL_REG { + Uint16 all; + struct GPBQUAL_BITS bit; +}; + + +//--------------------------------------------------------------------------------------- +// GPIO B data register bit definitions +// +// +struct GPBDAT_BITS { // bits description + Uint16 GPIOB0:1; // 0 + Uint16 GPIOB1:1; // 1 + Uint16 GPIOB2:1; // 2 + Uint16 GPIOB3:1; // 3 + Uint16 GPIOB4:1; // 4 + Uint16 GPIOB5:1; // 5 + Uint16 GPIOB6:1; // 6 + Uint16 GPIOB7:1; // 7 + Uint16 GPIOB8:1; // 8 + Uint16 GPIOB9:1; // 9 + Uint16 GPIOB10:1; // 10 + Uint16 GPIOB11:1; // 11 + Uint16 GPIOB12:1; // 12 + Uint16 GPIOB13:1; // 13 + Uint16 GPIOB14:1; // 14 + Uint16 GPIOB15:1; // 15 + +}; + +union GPBDAT_REG { + Uint16 all; + struct GPBDAT_BITS bit; +}; + + + +//--------------------------------------------------------------------------------------- +// GPIO B data set register bit definitions +// +// +struct GPBSET_BITS { // bits description + Uint16 GPIOB0:1; // 0 + Uint16 GPIOB1:1; // 1 + Uint16 GPIOB2:1; // 2 + Uint16 GPIOB3:1; // 3 + Uint16 GPIOB4:1; // 4 + Uint16 GPIOB5:1; // 5 + Uint16 GPIOB6:1; // 6 + Uint16 GPIOB7:1; // 7 + Uint16 GPIOB8:1; // 8 + Uint16 GPIOB9:1; // 9 + Uint16 GPIOB10:1; // 10 + Uint16 GPIOB11:1; // 11 + Uint16 GPIOB12:1; // 12 + Uint16 GPIOB13:1; // 13 + Uint16 GPIOB14:1; // 14 + Uint16 GPIOB15:1; // 15 + +}; + + +union GPBSET_REG { + Uint16 all; + struct GPBSET_BITS bit; +}; + + +//--------------------------------------------------------------------------------------- +// GPIO B data clear register bit definitions +// +// +struct GPBCLEAR_BITS { // bits description + Uint16 GPIOB0:1; // 0 + Uint16 GPIOB1:1; // 1 + Uint16 GPIOB2:1; // 2 + Uint16 GPIOB3:1; // 3 + Uint16 GPIOB4:1; // 4 + Uint16 GPIOB5:1; // 5 + Uint16 GPIOB6:1; // 6 + Uint16 GPIOB7:1; // 7 + Uint16 GPIOB8:1; // 8 + Uint16 GPIOB9:1; // 9 + Uint16 GPIOB10:1; // 10 + Uint16 GPIOB11:1; // 11 + Uint16 GPIOB12:1; // 12 + Uint16 GPIOB13:1; // 13 + Uint16 GPIOB14:1; // 14 + Uint16 GPIOB15:1; // 15 + +}; + +union GPBCLEAR_REG { + Uint16 all; + struct GPBCLEAR_BITS bit; +}; + + + +//--------------------------------------------------------------------------------------- +// GPIO B data toggle register bit definitions +// +// +struct GPBTOGGLE_BITS { // bits description + Uint16 GPIOB0:1; // 0 + Uint16 GPIOB1:1; // 1 + Uint16 GPIOB2:1; // 2 + Uint16 GPIOB3:1; // 3 + Uint16 GPIOB4:1; // 4 + Uint16 GPIOB5:1; // 5 + Uint16 GPIOB6:1; // 6 + Uint16 GPIOB7:1; // 7 + Uint16 GPIOB8:1; // 8 + Uint16 GPIOB9:1; // 9 + Uint16 GPIOB10:1; // 10 + Uint16 GPIOB11:1; // 11 + Uint16 GPIOB12:1; // 12 + Uint16 GPIOB13:1; // 13 + Uint16 GPIOB14:1; // 14 + Uint16 GPIOB15:1; // 15 + +}; + +union GPBTOGGLE_REG { + Uint16 all; + struct GPBTOGGLE_BITS bit; +}; + + +//--------------------------------------------------------------------------------- +// GPIO D mux control register bit definitions +// +// +struct GPDMUX_BITS { // bits description + Uint16 T1CTRIP_PDPA_GPIOD0:1; // 0 + Uint16 T2CTRIP_SOCA_GPIOD1:1; // 1 + Uint16 rsvd1:3; // 4:2 + Uint16 T3CTRIP_PDPB_GPIOD5:1; // 5 + Uint16 T4CTRIP_SOCB_GPIOD6:1; // 6 + Uint16 rsvd2:9; // 15:7 + +}; + +union GPDMUX_REG { + Uint16 all; + struct GPDMUX_BITS bit; +}; + +//---------------------------------------------------- +// GPIO D Direction control register bit definitions +// +// +struct GPDDIR_BITS { // bits description + Uint16 GPIOD0:1; // 0 + Uint16 GPIOD1:1; // 1 + Uint16 rsvd1:3; // 4:2 + Uint16 GPIOD5:1; // 5 + Uint16 GPIOD6:1; // 6 + Uint16 rsvd2:9; // 15:7 +}; + +union GPDDIR_REG { + Uint16 all; + struct GPDDIR_BITS bit; +}; + + +//---------------------------------------------------- +// GPIO D data register bit definitions +// +// +struct GPDDAT_BITS { // bits description + Uint16 GPIOD0:1; // 0 + Uint16 GPIOD1:1; // 1 + Uint16 rsvd1:3; // 4:2 + Uint16 GPIOD5:1; // 5 + Uint16 GPIOD6:1; // 6 + Uint16 rsvd2:9; // 15:7 +}; + +union GPDDAT_REG { + Uint16 all; + struct GPDDAT_BITS bit; +}; + + +//---------------------------------------------------- +// GPIO D data set register bit definitions +// +// +struct GPDSET_BITS { // bits description + Uint16 GPIOD0:1; // 0 + Uint16 GPIOD1:1; // 1 + Uint16 rsvd1:3; // 4:2 + Uint16 GPIOD5:1; // 5 + Uint16 GPIOD6:1; // 6 + Uint16 rsvd2:9; // 15:7 +}; + +union GPDSET_REG { + Uint16 all; + struct GPDSET_BITS bit; +}; + + +//---------------------------------------------------- +// GPIO D data clear register bit definitions +// +// +struct GPDCLEAR_BITS { // bits description + Uint16 GPIOD0:1; // 0 + Uint16 GPIOD1:1; // 1 + Uint16 rsvd1:3; // 4:2 + Uint16 GPIOD5:1; // 5 + Uint16 GPIOD6:1; // 6 + Uint16 rsvd2:9; // 15:7 +}; + +union GPDCLEAR_REG { + Uint16 all; + struct GPDCLEAR_BITS bit; +}; + + + +//---------------------------------------------------- +// GPIO D data toggle register bit definitions +// +// +struct GPDTOGGLE_BITS { // bits description + Uint16 GPIOD0:1; // 0 + Uint16 GPIOD1:1; // 1 + Uint16 rsvd1:3; // 4:2 + Uint16 GPIOD5:1; // 5 + Uint16 GPIOD6:1; // 6 + Uint16 rsvd2:9; // 15:7 +}; + +union GPDTOGGLE_REG { + Uint16 all; + struct GPDTOGGLE_BITS bit; +}; + + + +//---------------------------------- +// GPIOD Qualregister bit definitions +// +// +struct GPDQUAL_BITS { // bits description + Uint16 QUALPRD:8; // 0:7 Qualification Sampling Period + Uint16 rsvd1:8; // 15:8 reserved +}; + +union GPDQUAL_REG { + Uint16 all; + struct GPDQUAL_BITS bit; +}; + + +//--------------------------------------------- +// GPIO E mux control register bit definitions +// +// +struct GPEMUX_BITS { // bits description + Uint16 XINT1_XBIO_GPIOE0:1; // 0 + Uint16 XINT2_ADCSOC_GPIOE1:1; // 1 + Uint16 XNMI_XINT13_GPIOE2:1; // 2 + Uint16 rsvd1:12; // 15:3 + +}; + +union GPEMUX_REG { + Uint16 all; + struct GPEMUX_BITS bit; +}; + +//--------------------------------------------------- +// GPIO E Direction control register bit definitions +// +// +struct GPEDIR_BITS { // bits description + Uint16 GPIOE0:1; // 0 + Uint16 GPIOE1:1; // 1 + Uint16 GPIOE2:1; // 2 + Uint16 rsvd1:12; // 15:3 +}; + +union GPEDIR_REG { + Uint16 all; + struct GPEDIR_BITS bit; +}; + +//--------------------------------------------------- +// GPIO E data register bit definitions +// +// +struct GPEDAT_BITS { // bits description + Uint16 GPIOE0:1; // 0 + Uint16 GPIOE1:1; // 1 + Uint16 GPIOE2:1; // 2 + Uint16 rsvd1:12; // 15:3 +}; + +union GPEDAT_REG { + Uint16 all; + struct GPEDAT_BITS bit; +}; + + + +//--------------------------------------------------- +// GPIO E data set register bit definitions +// +// +struct GPESET_BITS { // bits description + Uint16 GPIOE0:1; // 0 + Uint16 GPIOE1:1; // 1 + Uint16 GPIOE2:1; // 2 + Uint16 rsvd1:12; // 15:3 +}; + +union GPESET_REG { + Uint16 all; + struct GPESET_BITS bit; +}; + + +//--------------------------------------------------- +// GPIO E data clear register bit definitions +// +// +struct GPECLEAR_BITS { // bits description + Uint16 GPIOE0:1; // 0 + Uint16 GPIOE1:1; // 1 + Uint16 GPIOE2:1; // 2 + Uint16 rsvd1:12; // 15:3 +}; + +union GPECLEAR_REG { + Uint16 all; + struct GPECLEAR_BITS bit; +}; + + +//--------------------------------------------------- +// GPIO E data toggle register bit definitions +// +// +struct GPETOGGLE_BITS { // bits description + Uint16 GPIOE0:1; // 0 + Uint16 GPIOE1:1; // 1 + Uint16 GPIOE2:1; // 2 + Uint16 rsvd1:12; // 15:3 +}; + +union GPETOGGLE_REG { + Uint16 all; + struct GPETOGGLE_BITS bit; +}; + + + +//----------------------------------- +// GPIOE Qualregister bit definitions +// +// +struct GPEQUAL_BITS { // bits description + Uint16 QUALPRD:8; // 0:7 Qualification Sampling Period + Uint16 rsvd1:8; // 15:8 reserved +}; + +union GPEQUAL_REG { + Uint16 all; + struct GPEQUAL_BITS bit; +}; + + +//---------------------------------------------- +// GPIO F mux control register bit definitions +// +// +struct GPFMUX_BITS { // bits description + Uint16 SPISIMOA_GPIOF0:1; // 0 + Uint16 SPISOMIA_GPIOF1:1; // 1 + Uint16 SPICLKA_GPIOF2:1; // 2 + Uint16 SPISTEA_GPIOF3:1; // 3 + Uint16 SCITXDA_GPIOF4:1; // 4 + Uint16 SCIRXDA_GPIOF5:1; // 5 + Uint16 CANTXA_GPIOF6:1; // 6 + Uint16 CANRXA_GPIOF7:1; // 7 + Uint16 MCLKXA_GPIOF8:1; // 8 + Uint16 MCLKRA_GPIOF9:1; // 9 + Uint16 MFSXA_GPIOF10:1; // 10 + Uint16 MFSRA_GPIOF11:1; // 11 + Uint16 MDXA_GPIOF12:1; // 12 + Uint16 MDRA_GPIOF13:1; // 13 + Uint16 XF_GPIOF14:1; // 14 + Uint16 spare_GPIOF15:1; // 15 + +}; + +/* Allow access to the bit fields or entire register */ +union GPFMUX_REG { + Uint16 all; + struct GPFMUX_BITS bit; +}; + +//--------------------------------------------------- +// GPIO F Direction control register bit definitions +// +// + +struct GPFDIR_BITS { // bits description + Uint16 GPIOF0:1; // 0 + Uint16 GPIOF1:1; // 1 + Uint16 GPIOF2:1; // 2 + Uint16 GPIOF3:1; // 3 + Uint16 GPIOF4:1; // 4 + Uint16 GPIOF5:1; // 5 + Uint16 GPIOF6:1; // 6 + Uint16 GPIOF7:1; // 7 + Uint16 GPIOF8:1; // 8 + Uint16 GPIOF9:1; // 9 + Uint16 GPIOF10:1; // 10 + Uint16 GPIOF11:1; // 11 + Uint16 GPIOF12:1; // 12 + Uint16 GPIOF13:1; // 13 + Uint16 GPIOF14:1; // 14 + Uint16 GPIOF15:1; // 15 + +}; + +union GPFDIR_REG { + Uint16 all; + struct GPFDIR_BITS bit; +}; + +//--------------------------------------------------- +// GPIO F data register bit definitions +// +// + +struct GPFDAT_BITS { // bits description + Uint16 GPIOF0:1; // 0 + Uint16 GPIOF1:1; // 1 + Uint16 GPIOF2:1; // 2 + Uint16 GPIOF3:1; // 3 + Uint16 GPIOF4:1; // 4 + Uint16 GPIOF5:1; // 5 + Uint16 GPIOF6:1; // 6 + Uint16 GPIOF7:1; // 7 + Uint16 GPIOF8:1; // 8 + Uint16 GPIOF9:1; // 9 + Uint16 GPIOF10:1; // 10 + Uint16 GPIOF11:1; // 11 + Uint16 GPIOF12:1; // 12 + Uint16 GPIOF13:1; // 13 + Uint16 GPIOF14:1; // 14 + Uint16 GPIOF15:1; // 15 + +}; + +union GPFDAT_REG { + Uint16 all; + struct GPFDAT_BITS bit; +}; + + +//--------------------------------------------------- +// GPIO F data set register bit definitions +// +// + +struct GPFSET_BITS { // bits description + Uint16 GPIOF0:1; // 0 + Uint16 GPIOF1:1; // 1 + Uint16 GPIOF2:1; // 2 + Uint16 GPIOF3:1; // 3 + Uint16 GPIOF4:1; // 4 + Uint16 GPIOF5:1; // 5 + Uint16 GPIOF6:1; // 6 + Uint16 GPIOF7:1; // 7 + Uint16 GPIOF8:1; // 8 + Uint16 GPIOF9:1; // 9 + Uint16 GPIOF10:1; // 10 + Uint16 GPIOF11:1; // 11 + Uint16 GPIOF12:1; // 12 + Uint16 GPIOF13:1; // 13 + Uint16 GPIOF14:1; // 14 + Uint16 GPIOF15:1; // 15 + +}; + +union GPFSET_REG { + Uint16 all; + struct GPFSET_BITS bit; +}; + + +//--------------------------------------------------- +// GPIO F data clear register bit definitions +// +// + +struct GPFCLEAR_BITS { // bits description + Uint16 GPIOF0:1; // 0 + Uint16 GPIOF1:1; // 1 + Uint16 GPIOF2:1; // 2 + Uint16 GPIOF3:1; // 3 + Uint16 GPIOF4:1; // 4 + Uint16 GPIOF5:1; // 5 + Uint16 GPIOF6:1; // 6 + Uint16 GPIOF7:1; // 7 + Uint16 GPIOF8:1; // 8 + Uint16 GPIOF9:1; // 9 + Uint16 GPIOF10:1; // 10 + Uint16 GPIOF11:1; // 11 + Uint16 GPIOF12:1; // 12 + Uint16 GPIOF13:1; // 13 + Uint16 GPIOF14:1; // 14 + Uint16 GPIOF15:1; // 15 + +}; + +union GPFCLEAR_REG { + Uint16 all; + struct GPFCLEAR_BITS bit; +}; + + +//--------------------------------------------------- +// GPIO F data toggle register bit definitions +// +// + +struct GPFTOGGLE_BITS { // bits description + Uint16 GPIOF0:1; // 0 + Uint16 GPIOF1:1; // 1 + Uint16 GPIOF2:1; // 2 + Uint16 GPIOF3:1; // 3 + Uint16 GPIOF4:1; // 4 + Uint16 GPIOF5:1; // 5 + Uint16 GPIOF6:1; // 6 + Uint16 GPIOF7:1; // 7 + Uint16 GPIOF8:1; // 8 + Uint16 GPIOF9:1; // 9 + Uint16 GPIOF10:1; // 10 + Uint16 GPIOF11:1; // 11 + Uint16 GPIOF12:1; // 12 + Uint16 GPIOF13:1; // 13 + Uint16 GPIOF14:1; // 14 + Uint16 GPIOF15:1; // 15 + +}; + +union GPFTOGGLE_REG { + Uint16 all; + struct GPFTOGGLE_BITS bit; +}; + +//---------------------------------------------- +// GPIO G mux control register bit definitions +// +// +struct GPGMUX_BITS { // bits description + Uint16 rsvd1:4; // 3:0 + Uint16 SCITXDB_GPIOG4:1; // 4 + Uint16 SCIRXDB_GPIOG5:1; // 5 + Uint16 rsvd2:10; // 15:6 + +}; + + +/* Allow access to the bit fields or entire register */ +union GPGMUX_REG { + Uint16 all; + struct GPGMUX_BITS bit; +}; + +//--------------------------------------------------- +// GPIO G Direction control register bit definitions +// +// + +struct GPGDIR_BITS { // bits description + Uint16 rsvd1:4; // 3:0 + Uint16 GPIOG4:1; // 4 + Uint16 GPIOG5:1; // 5 + Uint16 rsvd2:10; // 15:6 + +}; + +union GPGDIR_REG { + Uint16 all; + struct GPGDIR_BITS bit; +}; + +//--------------------------------------------------- +// GPIO G data register bit definitions +// +// + +struct GPGDAT_BITS { // bits description + Uint16 rsvd1:4; // 3:0 + Uint16 GPIOG4:1; // 4 + Uint16 GPIOG5:1; // 5 + Uint16 rsvd2:10; // 15:6 + +}; + +union GPGDAT_REG { + Uint16 all; + struct GPGDAT_BITS bit; +}; + + +//--------------------------------------------------- +// GPIO G data set register bit definitions +// +// + +struct GPGSET_BITS { // bits description + Uint16 rsvd1:4; // 3:0 + Uint16 GPIOG4:1; // 4 + Uint16 GPIOG5:1; // 5 + Uint16 rsvd2:10; // 15:6 + +}; + +union GPGSET_REG { + Uint16 all; + struct GPGSET_BITS bit; +}; + + +//--------------------------------------------------- +// GPIO G data clear register bit definitions +// +// + +struct GPGCLEAR_BITS { // bits description + Uint16 rsvd1:4; // 3:0 + Uint16 GPIOG4:1; // 4 + Uint16 GPIOG5:1; // 5 + Uint16 rsvd2:10; // 15:6 + +}; + +union GPGCLEAR_REG { + Uint16 all; + struct GPGCLEAR_BITS bit; +}; + + +//--------------------------------------------------- +// GPIO G data toggle register bit definitions +// +// + +struct GPGTOGGLE_BITS { // bits description + Uint16 rsvd1:4; // 3:0 + Uint16 GPIOG4:1; // 4 + Uint16 GPIOG5:1; // 5 + Uint16 rsvd2:10; // 15:6 + +}; + +union GPGTOGGLE_REG { + Uint16 all; + struct GPGTOGGLE_BITS bit; +}; + + +struct GPIO_MUX_REGS { + union GPAMUX_REG GPAMUX; + union GPADIR_REG GPADIR; + union GPAQUAL_REG GPAQUAL; + Uint16 rsvd1; + union GPBMUX_REG GPBMUX; + union GPBDIR_REG GPBDIR; + union GPBQUAL_REG GPBQUAL; + Uint16 rsvd2[5]; + union GPDMUX_REG GPDMUX; + union GPDDIR_REG GPDDIR; + union GPDQUAL_REG GPDQUAL; + Uint16 rsvd3; + union GPEMUX_REG GPEMUX; + union GPEDIR_REG GPEDIR; + union GPEQUAL_REG GPEQUAL; + Uint16 rsvd4; + union GPFMUX_REG GPFMUX; + union GPFDIR_REG GPFDIR; + Uint16 rsvd5[2]; + union GPGMUX_REG GPGMUX; + union GPGDIR_REG GPGDIR; + Uint16 rsvd6[6]; +}; + +struct GPIO_DATA_REGS { + union GPADAT_REG GPADAT; + union GPASET_REG GPASET; + union GPACLEAR_REG GPACLEAR; + union GPATOGGLE_REG GPATOGGLE; + union GPBDAT_REG GPBDAT; + union GPBSET_REG GPBSET; + union GPBCLEAR_REG GPBCLEAR; + union GPBTOGGLE_REG GPBTOGGLE; + Uint16 rsvd1[4]; + union GPDDAT_REG GPDDAT; + union GPDSET_REG GPDSET; + union GPDCLEAR_REG GPDCLEAR; + union GPDTOGGLE_REG GPDTOGGLE; + union GPEDAT_REG GPEDAT; + union GPESET_REG GPESET; + union GPECLEAR_REG GPECLEAR; + union GPETOGGLE_REG GPETOGGLE; + union GPFDAT_REG GPFDAT; + union GPFSET_REG GPFSET; + union GPFCLEAR_REG GPFCLEAR; + union GPFTOGGLE_REG GPFTOGGLE; + union GPGDAT_REG GPGDAT; + union GPGSET_REG GPGSET; + union GPGCLEAR_REG GPGCLEAR; + union GPGTOGGLE_REG GPGTOGGLE; + Uint16 rsvd2[4]; +}; + + +//--------------------------------------------------------------------------- +// GPI/O External References & Function Declarations: +// +extern volatile struct GPIO_MUX_REGS GpioMuxRegs; +extern volatile struct GPIO_DATA_REGS GpioDataRegs; + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_GPIO_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Mcbsp.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Mcbsp.h new file mode 100644 index 0000000..559d96d --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Mcbsp.h @@ -0,0 +1,777 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 28, 2005 14:57:24 $ +//########################################################################### +// +// FILE: DSP281x_Mcbsp.h +// +// TITLE: DSP281x Device McBSP Register Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_MCBSP_H +#define DSP281x_MCBSP_H + +#ifdef __cplusplus +extern "C" { +#endif + + +//--------------------------------------------------------------------------- +// McBSP Individual Register Bit Definitions: +// +// McBSP DRR2 register bit definitions: +struct DRR2_BITS { // bit description + Uint16 HWLB:8; // 16:23 High word low byte + Uint16 HWHB:8; // 24:31 High word high byte +}; + +union DRR2_REG { + Uint16 all; + struct DRR2_BITS bit; +}; + +// McBSP DRR1 register bit definitions: +struct DRR1_BITS { // bit description + Uint16 LWLB:8; // 16:23 Low word low byte + Uint16 LWHB:8; // 24:31 low word high byte +}; + +union DRR1_REG { + Uint16 all; + struct DRR1_BITS bit; +}; + +// McBSP DXR2 register bit definitions: +struct DXR2_BITS { // bit description + Uint16 HWLB:8; // 16:23 High word low byte + Uint16 HWHB:8; // 24:31 High word high byte +}; + +union DXR2_REG { + Uint16 all; + struct DXR2_BITS bit; +}; + +// McBSP DXR1 register bit definitions: +struct DXR1_BITS { // bit description + Uint16 LWLB:8; // 16:23 Low word low byte + Uint16 LWHB:8; // 24:31 low word high byte +}; + +union DXR1_REG { + Uint16 all; + struct DXR1_BITS bit; +}; + +// SPCR2 control register bit definitions: +struct SPCR2_BITS { // bit description + Uint16 XRST:1; // 0 transmit reset + Uint16 XRDY:1; // 1 transmit ready + Uint16 XEMPTY:1; // 2 Transmit empty + Uint16 XSYNCERR:1; // 3 Transmit syn errorINT flag + Uint16 XINTM:2; // 5:4 Transmit interrupt types + Uint16 GRST:1; // 6 CLKG reset + Uint16 FRST:1; // 7 Frame sync reset + Uint16 SOFT:1; // 8 SOFT bit + Uint16 FREE:1; // 9 FREE bit + Uint16 rsvd:6; // 15:10 reserved +}; + +union SPCR2_REG { + Uint16 all; + struct SPCR2_BITS bit; +}; + +// SPCR1 control register bit definitions: +struct SPCR1_BITS { // bit description + Uint16 RRST:1; // 0 Receive reset + Uint16 RRDY:1; // 1 Receive ready + Uint16 RFULL:1; // 2 Receive full + Uint16 RSYNCERR:1; // 7 Receive syn error + Uint16 RINTM:2; // 5:4 Receive interrupt types + Uint16 ABIS:1; // 6 ABIS mode select + Uint16 DXENA:1; // 7 DX hi-z enable + Uint16 rsvd:3; // 10:8 reserved + Uint16 CLKSTP:2; // 12:11 CLKSTOP mode bit + Uint16 RJUST:2; // 13:14 Right justified + Uint16 DLB:1; // 15 Digital loop back +}; + +union SPCR1_REG { + Uint16 all; + struct SPCR1_BITS bit; +}; + +// RCR2 control register bit definitions: +struct RCR2_BITS { // bit description + Uint16 RDATDLY:2; // 1:0 Receive data delay + Uint16 RFIG:1; // 2 Receive frame sync ignore + Uint16 RCOMPAND:2; // 4:3 Receive Companding Mode selects + Uint16 RWDLEN2:3; // 7:5 Receive word length + Uint16 RFRLEN2:7; // 14:8 Receive Frame sync + Uint16 RPHASE:1; // 15 Receive Phase +}; + +union RCR2_REG { + Uint16 all; + struct RCR2_BITS bit; +}; + +// RCR1 control register bit definitions: +struct RCR1_BITS { // bit description + Uint16 rsvd1:5; // 4:0 reserved + Uint16 RWDLEN1:3; // 7:5 Receive word length + Uint16 RFRLEN1:7; // 14:8 Receive frame length + Uint16 rsvd2:1; // 15 reserved +}; + +union RCR1_REG { + Uint16 all; + struct RCR1_BITS bit; +}; + +// XCR2 control register bit definitions: + +struct XCR2_BITS { // bit description + Uint16 XDATDLY:2; // 1:0 Transmit data delay + Uint16 XFIG:1; // 2 Transmit frame sync ignore + Uint16 XCOMPAND:2; // 4:3 Transmit Companding Mode selects + Uint16 XWDLEN2:3; // 7:5 Transmit word length + Uint16 XFRLEN2:7; // 14:8 Transmit Frame sync + Uint16 XPHASE:1; // 15 Transmit Phase +}; + +union XCR2_REG { + Uint16 all; + struct XCR2_BITS bit; +}; + +// XCR1 control register bit definitions: +struct XCR1_BITS { // bit description + Uint16 rsvd1:5; // 4:0 reserved + Uint16 XWDLEN1:3; // 7:5 Transmit word length + Uint16 XFRLEN1:7; // 14:8 Transmit frame length + Uint16 rsvd2:1; // 15 reserved +}; + +union XCR1_REG { + Uint16 all; + struct XCR1_BITS bit; +}; + +// SRGR2 Sample rate generator control register bit definitions: +struct SRGR2_BITS { // bit description + Uint16 FPER:12; // 11:0 Frame period + Uint16 FSGM:1; // 12 Frame sync generator mode + Uint16 CLKSM:1; // 13 Sample rate generator mode + Uint16 rsvd:1; // 14 reserved + Uint16 GSYNC:1; // 15 CLKG sync +}; + +union SRGR2_REG { + Uint16 all; + struct SRGR2_BITS bit; +}; + +// SRGR1 control register bit definitions: +struct SRGR1_BITS { // bit description + Uint16 CLKGDV:8; // 7:0 CLKG divider + Uint16 FWID:8; // 15:8 Frame width +}; + +union SRGR1_REG { + Uint16 all; + struct SRGR1_BITS bit; +}; + +// MCR2 Multichannel control register bit definitions: +struct MCR2_BITS { // bit description + Uint16 XMCM:2; // 1:0 Transmit multichannel mode + Uint16 XCBLK:3; // 2:4 Transmit current block + Uint16 XPABLK:2; // 5:6 Transmit partition A Block + Uint16 XPBBLK:2; // 7:8 Transmit partition B Block + Uint16 XMCME:1; // 9 Transmit multi-channel enhance mode + Uint16 rsvd:6; // 15:10 reserved +}; + +union MCR2_REG { + Uint16 all; + struct MCR2_BITS bit; +}; + +// MCR1 Multichannel control register bit definitions: +struct MCR1_BITS { // bit description + Uint16 RMCM:1; // 0 Receive multichannel mode + Uint16 rsvd:1; // 1 reserved + Uint16 RCBLK:3; // 4:2 Receive current block + Uint16 RPABLK:2; // 6:5 Receive partition A Block + Uint16 RPBBLK:2; // 7:8 Receive partition B Block + Uint16 RMCME:1; // 9 Receive multi-channel enhance mode + Uint16 rsvd1:6; // 15:10 reserved +}; + +union MCR1_REG { + Uint16 all; + struct MCR1_BITS bit; +}; + +// RCERA control register bit definitions: +struct RCERA_BITS { // bit description + Uint16 RCEA0:1; // 0 Receive Channel enable bit + Uint16 RCEA1:1; // 1 Receive Channel enable bit + Uint16 RCEA2:1; // 2 Receive Channel enable bit + Uint16 RCEA3:1; // 3 Receive Channel enable bit + Uint16 RCEA4:1; // 4 Receive Channel enable bit + Uint16 RCEA5:1; // 5 Receive Channel enable bit + Uint16 RCEA6:1; // 6 Receive Channel enable bit + Uint16 RCEA7:1; // 7 Receive Channel enable bit + Uint16 RCEA8:1; // 8 Receive Channel enable bit + Uint16 RCEA9:1; // 9 Receive Channel enable bit + Uint16 RCEA10:1; // 10 Receive Channel enable bit + Uint16 RCEA11:1; // 11 Receive Channel enable bit + Uint16 RCEA12:1; // 12 Receive Channel enable bit + Uint16 RCEA13:1; // 13 Receive Channel enable bit + Uint16 RCEA14:1; // 14 Receive Channel enable bit + Uint16 RCEA15:1; // 15 Receive Channel enable bit +}; + +union RCERA_REG { + Uint16 all; + struct RCERA_BITS bit; +}; + +// RCERB control register bit definitions: +struct RCERB_BITS { // bit description + Uint16 RCEB0:1; // 0 Receive Channel enable bit + Uint16 RCEB1:1; // 1 Receive Channel enable bit + Uint16 RCEB2:1; // 2 Receive Channel enable bit + Uint16 RCEB3:1; // 3 Receive Channel enable bit + Uint16 RCEB4:1; // 4 Receive Channel enable bit + Uint16 RCEB5:1; // 5 Receive Channel enable bit + Uint16 RCEB6:1; // 6 Receive Channel enable bit + Uint16 RCEB7:1; // 7 Receive Channel enable bit + Uint16 RCEB8:1; // 8 Receive Channel enable bit + Uint16 RCEB9:1; // 9 Receive Channel enable bit + Uint16 RCEB10:1; // 10 Receive Channel enable bit + Uint16 RCEB11:1; // 11 Receive Channel enable bit + Uint16 RCEB12:1; // 12 Receive Channel enable bit + Uint16 RCEB13:1; // 13 Receive Channel enable bit + Uint16 RCEB14:1; // 14 Receive Channel enable bit + Uint16 RCEB15:1; // 15 Receive Channel enable bit +}; + +union RCERB_REG { + Uint16 all; + struct RCERB_BITS bit; +}; + +// XCERA control register bit definitions: +struct XCERA_BITS { // bit description + Uint16 XCERA0:1; // 0 Receive Channel enable bit + Uint16 XCERA1:1; // 1 Receive Channel enable bit + Uint16 XCERA2:1; // 2 Receive Channel enable bit + Uint16 XCERA3:1; // 3 Receive Channel enable bit + Uint16 XCERA4:1; // 4 Receive Channel enable bit + Uint16 XCERA5:1; // 5 Receive Channel enable bit + Uint16 XCERA6:1; // 6 Receive Channel enable bit + Uint16 XCERA7:1; // 7 Receive Channel enable bit + Uint16 XCERA8:1; // 8 Receive Channel enable bit + Uint16 XCERA9:1; // 9 Receive Channel enable bit + Uint16 XCERA10:1; // 10 Receive Channel enable bit + Uint16 XCERA11:1; // 11 Receive Channel enable bit + Uint16 XCERA12:1; // 12 Receive Channel enable bit + Uint16 XCERA13:1; // 13 Receive Channel enable bit + Uint16 XCERA14:1; // 14 Receive Channel enable bit + Uint16 XCERA15:1; // 15 Receive Channel enable bit +}; + +union XCERA_REG { + Uint16 all; + struct XCERA_BITS bit; +}; + +// XCERB control register bit definitions: +struct XCERB_BITS { // bit description + Uint16 XCERB0:1; // 0 Receive Channel enable bit + Uint16 XCERB1:1; // 1 Receive Channel enable bit + Uint16 XCERB2:1; // 2 Receive Channel enable bit + Uint16 XCERB3:1; // 3 Receive Channel enable bit + Uint16 XCERB4:1; // 4 Receive Channel enable bit + Uint16 XCERB5:1; // 5 Receive Channel enable bit + Uint16 XCERB6:1; // 6 Receive Channel enable bit + Uint16 XCERB7:1; // 7 Receive Channel enable bit + Uint16 XCERB8:1; // 8 Receive Channel enable bit + Uint16 XCERB9:1; // 9 Receive Channel enable bit + Uint16 XCERB10:1; // 10 Receive Channel enable bit + Uint16 XCERB11:1; // 11 Receive Channel enable bit + Uint16 XCERB12:1; // 12 Receive Channel enable bit + Uint16 XCERB13:1; // 13 Receive Channel enable bit + Uint16 XCERB14:1; // 14 Receive Channel enable bit + Uint16 XCERB15:1; // 15 Receive Channel enable bit +}; + +union XCERB_REG { + Uint16 all; + struct XCERB_BITS bit; +}; + +// PCR control register bit definitions: +struct PCR_BITS { // bit description + Uint16 CLKRP:1; // 0 Receive Clock polarity + Uint16 CLKXP:1; // 1 Transmit clock polarity + Uint16 FSRP:1; // 2 Receive Frame synchronization polarity + Uint16 FSXP:1; // 3 Transmit Frame synchronization polarity + Uint16 DR_STAT:1; // 4 DR pin status - reserved for this McBSP + Uint16 DX_STAT:1; // 5 DX pin status - reserved for this McBSP + Uint16 CLKS_STAT:1; // 6 CLKS pin status - reserved for 28x -McBSP + Uint16 SCLKME:1; // 7 Enhanced sample clock mode selection bit. + Uint16 CLKRM:1; // 8 Receiver Clock Mode + Uint16 CLKXM:1; // 9 Transmitter Clock Mode. + Uint16 FSRM:1; // 10 Receive Frame Synchronization Mode + Uint16 FSXM:1; // 11 Transmit Frame Synchronization Mode + Uint16 RIOEN:1; // 12 General Purpose I/O Mode - reserved in this 28x-McBSP + Uint16 XIOEN:1; // 13 General Purpose I/O Mode - reserved in this 28x-McBSP + Uint16 IDEL_EN:1; // 14 reserved in this 28x-McBSP + Uint16 rsvd:1 ; // 15 reserved +}; + +union PCR_REG { + Uint16 all; + struct PCR_BITS bit; +}; + +// RCERC control register bit definitions: +struct RCERC_BITS { // bit description + Uint16 RCEC0:1; // 0 Receive Channel enable bit + Uint16 RCEC1:1; // 1 Receive Channel enable bit + Uint16 RCEC2:1; // 2 Receive Channel enable bit + Uint16 RCEC3:1; // 3 Receive Channel enable bit + Uint16 RCEC4:1; // 4 Receive Channel enable bit + Uint16 RCEC5:1; // 5 Receive Channel enable bit + Uint16 RCEC6:1; // 6 Receive Channel enable bit + Uint16 RCEC7:1; // 7 Receive Channel enable bit + Uint16 RCEC8:1; // 8 Receive Channel enable bit + Uint16 RCEC9:1; // 9 Receive Channel enable bit + Uint16 RCEC10:1; // 10 Receive Channel enable bit + Uint16 RCEC11:1; // 11 Receive Channel enable bit + Uint16 RCEC12:1; // 12 Receive Channel enable bit + Uint16 RCEC13:1; // 13 Receive Channel enable bit + Uint16 RCEC14:1; // 14 Receive Channel enable bit + Uint16 RCEC15:1; // 15 Receive Channel enable bit +}; + +union RCERC_REG { + Uint16 all; + struct RCERC_BITS bit; +}; + +// RCERD control register bit definitions: +struct RCERD_BITS { // bit description + Uint16 RCED0:1; // 0 Receive Channel enable bit + Uint16 RCED1:1; // 1 Receive Channel enable bit + Uint16 RCED2:1; // 2 Receive Channel enable bit + Uint16 RCED3:1; // 3 Receive Channel enable bit + Uint16 RCED4:1; // 4 Receive Channel enable bit + Uint16 RCED5:1; // 5 Receive Channel enable bit + Uint16 RCED6:1; // 6 Receive Channel enable bit + Uint16 RCED7:1; // 7 Receive Channel enable bit + Uint16 RCED8:1; // 8 Receive Channel enable bit + Uint16 RCED9:1; // 9 Receive Channel enable bit + Uint16 RCED10:1; // 10 Receive Channel enable bit + Uint16 RCED11:1; // 11 Receive Channel enable bit + Uint16 RCED12:1; // 12 Receive Channel enable bit + Uint16 RCED13:1; // 13 Receive Channel enable bit + Uint16 RCED14:1; // 14 Receive Channel enable bit + Uint16 RCED15:1; // 15 Receive Channel enable bit +}; + +union RCERD_REG { + Uint16 all; + struct RCERD_BITS bit; +}; + +// XCERC control register bit definitions: +struct XCERC_BITS { // bit description + Uint16 XCERC0:1; // 0 Receive Channel enable bit + Uint16 XCERC1:1; // 1 Receive Channel enable bit + Uint16 XCERC2:1; // 2 Receive Channel enable bit + Uint16 XCERC3:1; // 3 Receive Channel enable bit + Uint16 XCERC4:1; // 4 Receive Channel enable bit + Uint16 XCERC5:1; // 5 Receive Channel enable bit + Uint16 XCERC6:1; // 6 Receive Channel enable bit + Uint16 XCERC7:1; // 7 Receive Channel enable bit + Uint16 XCERC8:1; // 8 Receive Channel enable bit + Uint16 XCERC9:1; // 9 Receive Channel enable bit + Uint16 XCERC10:1; // 10 Receive Channel enable bit + Uint16 XCERC11:1; // 11 Receive Channel enable bit + Uint16 XCERC12:1; // 12 Receive Channel enable bit + Uint16 XCERC13:1; // 13 Receive Channel enable bit + Uint16 XCERC14:1; // 14 Receive Channel enable bit + Uint16 XCERC15:1; // 15 Receive Channel enable bit +}; + +union XCERC_REG { + Uint16 all; + struct XCERC_BITS bit; +}; + +// XCERD control register bit definitions: +struct XCERD_BITS { // bit description + Uint16 XCERD0:1; // 0 Receive Channel enable bit + Uint16 XCERD1:1; // 1 Receive Channel enable bit + Uint16 XCERD2:1; // 2 Receive Channel enable bit + Uint16 XCERD3:1; // 3 Receive Channel enable bit + Uint16 XCERD4:1; // 4 Receive Channel enable bit + Uint16 XCERD5:1; // 5 Receive Channel enable bit + Uint16 XCERD6:1; // 6 Receive Channel enable bit + Uint16 XCERD7:1; // 7 Receive Channel enable bit + Uint16 XCERD8:1; // 8 Receive Channel enable bit + Uint16 XCERD9:1; // 9 Receive Channel enable bit + Uint16 XCERD10:1; // 10 Receive Channel enable bit + Uint16 XCERD11:1; // 11 Receive Channel enable bit + Uint16 XCERD12:1; // 12 Receive Channel enable bit + Uint16 XCERD13:1; // 13 Receive Channel enable bit + Uint16 XCERD14:1; // 14 Receive Channel enable bit + Uint16 XCERD15:1; // 15 Receive Channel enable bit +}; + +union XCERD_REG { + Uint16 all; + struct XCERD_BITS bit; +}; + +// RCERE control register bit definitions: +struct RCERE_BITS { // bit description + Uint16 RCEE0:1; // 0 Receive Channel enable bit + Uint16 RCEE1:1; // 1 Receive Channel enable bit + Uint16 RCEE2:1; // 2 Receive Channel enable bit + Uint16 RCEE3:1; // 3 Receive Channel enable bit + Uint16 RCEE4:1; // 4 Receive Channel enable bit + Uint16 RCEE5:1; // 5 Receive Channel enable bit + Uint16 RCEE6:1; // 6 Receive Channel enable bit + Uint16 RCEE7:1; // 7 Receive Channel enable bit + Uint16 RCEE8:1; // 8 Receive Channel enable bit + Uint16 RCEE9:1; // 9 Receive Channel enable bit + Uint16 RCEE10:1; // 10 Receive Channel enable bit + Uint16 RCEE11:1; // 11 Receive Channel enable bit + Uint16 RCEE12:1; // 12 Receive Channel enable bit + Uint16 RCEE13:1; // 13 Receive Channel enable bit + Uint16 RCEE14:1; // 14 Receive Channel enable bit + Uint16 RCEE15:1; // 15 Receive Channel enable bit +}; + +union RCERE_REG { + Uint16 all; + struct RCERE_BITS bit; +}; + +// RCERF control register bit definitions: +struct RCERF_BITS { // bit description + Uint16 RCEF0:1; // 0 Receive Channel enable bit + Uint16 RCEF1:1; // 1 Receive Channel enable bit + Uint16 RCEF2:1; // 2 Receive Channel enable bit + Uint16 RCEF3:1; // 3 Receive Channel enable bit + Uint16 RCEF4:1; // 4 Receive Channel enable bit + Uint16 RCEF5:1; // 5 Receive Channel enable bit + Uint16 RCEF6:1; // 6 Receive Channel enable bit + Uint16 RCEF7:1; // 7 Receive Channel enable bit + Uint16 RCEF8:1; // 8 Receive Channel enable bit + Uint16 RCEF9:1; // 9 Receive Channel enable bit + Uint16 RCEF10:1; // 10 Receive Channel enable bit + Uint16 RCEF11:1; // 11 Receive Channel enable bit + Uint16 RCEF12:1; // 12 Receive Channel enable bit + Uint16 RCEF13:1; // 13 Receive Channel enable bit + Uint16 RCEF14:1; // 14 Receive Channel enable bit + Uint16 RCEF15:1; // 15 Receive Channel enable bit +}; + +union RCERF_REG { + Uint16 all; + struct RCERF_BITS bit; +}; + +// XCERE control register bit definitions: +struct XCERE_BITS { // bit description + Uint16 XCERE0:1; // 0 Receive Channel enable bit + Uint16 XCERE1:1; // 1 Receive Channel enable bit + Uint16 XCERE2:1; // 2 Receive Channel enable bit + Uint16 XCERE3:1; // 3 Receive Channel enable bit + Uint16 XCERE4:1; // 4 Receive Channel enable bit + Uint16 XCERE5:1; // 5 Receive Channel enable bit + Uint16 XCERE6:1; // 6 Receive Channel enable bit + Uint16 XCERE7:1; // 7 Receive Channel enable bit + Uint16 XCERE8:1; // 8 Receive Channel enable bit + Uint16 XCERE9:1; // 9 Receive Channel enable bit + Uint16 XCERE10:1; // 10 Receive Channel enable bit + Uint16 XCERE11:1; // 11 Receive Channel enable bit + Uint16 XCERE12:1; // 12 Receive Channel enable bit + Uint16 XCERE13:1; // 13 Receive Channel enable bit + Uint16 XCERE14:1; // 14 Receive Channel enable bit + Uint16 XCERE15:1; // 15 Receive Channel enable bit +}; + +union XCERE_REG { + Uint16 all; + struct XCERE_BITS bit; +}; + +// XCERF control register bit definitions: +struct XCERF_BITS { // bit description + Uint16 XCERF0:1; // 0 Receive Channel enable bit + Uint16 XCERF1:1; // 1 Receive Channel enable bit + Uint16 XCERF2:1; // 2 Receive Channel enable bit + Uint16 XCERF3:1; // 3 Receive Channel enable bit + Uint16 XCERF4:1; // 4 Receive Channel enable bit + Uint16 XCERF5:1; // 5 Receive Channel enable bit + Uint16 XCERF6:1; // 6 Receive Channel enable bit + Uint16 XCERF7:1; // 7 Receive Channel enable bit + Uint16 XCERF8:1; // 8 Receive Channel enable bit + Uint16 XCERF9:1; // 9 Receive Channel enable bit + Uint16 XCERF10:1; // 10 Receive Channel enable bit + Uint16 XCERF11:1; // 11 Receive Channel enable bit + Uint16 XCERF12:1; // 12 Receive Channel enable bit + Uint16 XCERF13:1; // 13 Receive Channel enable bit + Uint16 XCERF14:1; // 14 Receive Channel enable bit + Uint16 XCERF15:1; // 15 Receive Channel enable bit +}; + +union XCERF_REG { + Uint16 all; + struct XCERF_BITS bit; +}; + +// RCERG control register bit definitions: +struct RCERG_BITS { // bit description + Uint16 RCEG0:1; // 0 Receive Channel enable bit + Uint16 RCEG1:1; // 1 Receive Channel enable bit + Uint16 RCEG2:1; // 2 Receive Channel enable bit + Uint16 RCEG3:1; // 3 Receive Channel enable bit + Uint16 RCEG4:1; // 4 Receive Channel enable bit + Uint16 RCEG5:1; // 5 Receive Channel enable bit + Uint16 RCEG6:1; // 6 Receive Channel enable bit + Uint16 RCEG7:1; // 7 Receive Channel enable bit + Uint16 RCEG8:1; // 8 Receive Channel enable bit + Uint16 RCEG9:1; // 9 Receive Channel enable bit + Uint16 RCEG10:1; // 10 Receive Channel enable bit + Uint16 RCEG11:1; // 11 Receive Channel enable bit + Uint16 RCEG12:1; // 12 Receive Channel enable bit + Uint16 RCEG13:1; // 13 Receive Channel enable bit + Uint16 RCEG14:1; // 14 Receive Channel enable bit + Uint16 RCEG15:1; // 15 Receive Channel enable bit +}; + +union RCERG_REG { + Uint16 all; + struct RCERG_BITS bit; +}; + +// RCERH control register bit definitions: +struct RCERH_BITS { // bit description + Uint16 RCEH0:1; // 0 Receive Channel enable bit + Uint16 RCEH1:1; // 1 Receive Channel enable bit + Uint16 RCEH2:1; // 2 Receive Channel enable bit + Uint16 RCEH3:1; // 3 Receive Channel enable bit + Uint16 RCEH4:1; // 4 Receive Channel enable bit + Uint16 RCEH5:1; // 5 Receive Channel enable bit + Uint16 RCEH6:1; // 6 Receive Channel enable bit + Uint16 RCEH7:1; // 7 Receive Channel enable bit + Uint16 RCEH8:1; // 8 Receive Channel enable bit + Uint16 RCEH9:1; // 9 Receive Channel enable bit + Uint16 RCEH10:1; // 10 Receive Channel enable bit + Uint16 RCEH11:1; // 11 Receive Channel enable bit + Uint16 RCEH12:1; // 12 Receive Channel enable bit + Uint16 RCEH13:1; // 13 Receive Channel enable bit + Uint16 RCEH14:1; // 14 Receive Channel enable bit + Uint16 RCEH15:1; // 15 Receive Channel enable bit +}; + +union RCERH_REG { + Uint16 all; + struct RCERH_BITS bit; +}; + +// XCERG control register bit definitions: +struct XCERG_BITS { // bit description + Uint16 XCERG0:1; // 0 Receive Channel enable bit + Uint16 XCERG1:1; // 1 Receive Channel enable bit + Uint16 XCERG2:1; // 2 Receive Channel enable bit + Uint16 XCERG3:1; // 3 Receive Channel enable bit + Uint16 XCERG4:1; // 4 Receive Channel enable bit + Uint16 XCERG5:1; // 5 Receive Channel enable bit + Uint16 XCERG6:1; // 6 Receive Channel enable bit + Uint16 XCERG7:1; // 7 Receive Channel enable bit + Uint16 XCERG8:1; // 8 Receive Channel enable bit + Uint16 XCERG9:1; // 9 Receive Channel enable bit + Uint16 XCERG10:1; // 10 Receive Channel enable bit + Uint16 XCERG11:1; // 11 Receive Channel enable bit + Uint16 XCERG12:1; // 12 Receive Channel enable bit + Uint16 XCERG13:1; // 13 Receive Channel enable bit + Uint16 XCERG14:1; // 14 Receive Channel enable bit + Uint16 XCERG15:1; // 15 Receive Channel enable bit +}; + +union XCERG_REG { + Uint16 all; + struct XCERG_BITS bit; +}; + +// XCERH control register bit definitions: +struct XCERH_BITS { // bit description + Uint16 XCEH0:1; // 0 Receive Channel enable bit + Uint16 XCEH1:1; // 1 Receive Channel enable bit + Uint16 XCEH2:1; // 2 Receive Channel enable bit + Uint16 XCEH3:1; // 3 Receive Channel enable bit + Uint16 XCEH4:1; // 4 Receive Channel enable bit + Uint16 XCEH5:1; // 5 Receive Channel enable bit + Uint16 XCEH6:1; // 6 Receive Channel enable bit + Uint16 XCEH7:1; // 7 Receive Channel enable bit + Uint16 XCEH8:1; // 8 Receive Channel enable bit + Uint16 XCEH9:1; // 9 Receive Channel enable bit + Uint16 XCEH10:1; // 10 Receive Channel enable bit + Uint16 XCEH11:1; // 11 Receive Channel enable bit + Uint16 XCEH12:1; // 12 Receive Channel enable bit + Uint16 XCEH13:1; // 13 Receive Channel enable bit + Uint16 XCEH14:1; // 14 Receive Channel enable bit + Uint16 XCEH15:1; // 15 Receive Channel enable bit +}; + +union XCERH_REG { + Uint16 all; + struct XCERH_BITS bit; +}; + +// McBSP FIFO Transmit register bit definitions: +struct MFFTX_BITS { // bit description + Uint16 TXFFIL:5; // 4:0 Interrupt level + Uint16 TXFFIENA:1; // 5 Interrupt enable + Uint16 TXFFINT_CLEAR:1; // 6 Clear INT flag + Uint16 TXFFINT_FLAG:1; // 7 INT flag + Uint16 TXFFST:5; // 12:8 FIFO status + Uint16 TXFIFO_RESET:1; // 13 FIFO reset + Uint16 MFFENA:1; // 14 Enhancement enable + Uint16 rsvd:1; // 15 reserved +}; + +union MFFTX_REG { + Uint16 all; + struct MFFTX_BITS bit; +}; + +// McBSP FIFO recieve register bit definitions: +struct MFFRX_BITS { // bits description + Uint16 RXFFIL:5; // 4:0 Interrupt level + Uint16 RXFFIENA:1; // 5 Interrupt enable + Uint16 RXFFINT_CLEAR:1; // 6 Clear INT flag + Uint16 RXFFINT_FLAG:1; // 7 INT flag + Uint16 RXFFST:5; // 12:8 FIFO status + Uint16 RXFIFO_RESET:1; // 13 FIFO reset + Uint16 RXFFOVF_CLEAR:1; // 14 Clear overflow + Uint16 RXFFOVF_FLAG:1; // 15 FIFO overflow +}; + +union MFFRX_REG { + Uint16 all; + struct MFFRX_BITS bit; +}; + +// McBSP FIFO control register bit definitions: +struct MFFCT_BITS { // bits description + Uint16 FFTXTXDLY:8; // 7:0 FIFO transmit delay + Uint16 rsvd:7; // 15:7 reserved + Uint16 IACKM:1; // 15 is IACK mode enable bit +}; + +union MFFCT_REG { + Uint16 all; + struct MFFCT_BITS bit; +}; + +// McBSP FIFO INTERRUPT control register bit definitions: +struct MFFINT_BITS { // bits description + Uint16 XINT:1; // 0 XINT interrupt enable + Uint16 XEVTA:1; // 1 XEVTA interrupt enable + Uint16 RINT:1; // 2 RINT interrupt enable + Uint16 REVTA:1; // 3 REVTA interrupt enable + Uint16 rsvd:12; // 15:4 reserved +}; + +union MFFINT_REG { + Uint16 all; + struct MFFINT_BITS bit; +}; + +// McBSP FIFO INTERRUPT status register bit definitions: +struct MFFST_BITS { // bits description + Uint16 EOBX:1; // 0 EOBX flag + Uint16 FSX:1; // 1 FSX flag + Uint16 EOBR:1; // 2 EOBR flag + Uint16 FSR:1; // 3 FSR flag + Uint16 rsvd:12; // 15:4 reserved +}; + +union MFFST_REG { + Uint16 all; + struct MFFST_BITS bit; +}; + + +//--------------------------------------------------------------------------- +// McBSP Register File: +// +struct MCBSP_REGS { + union DRR2_REG DRR2; // 0x7800, MCBSP Data receive register bits 31-16 + union DRR1_REG DRR1; // 0x7801, MCBSP Data receive register bits 15-0 + union DXR2_REG DXR2; // 0x7802, MCBSP Data transmit register bits 31-16 + union DXR1_REG DXR1; // 0x7803, MCBSP Data transmit register bits 15-0 + union SPCR2_REG SPCR2; // 0x7804, MCBSP control register bits 31-16 + union SPCR1_REG SPCR1; // 0x7805, MCBSP control register bits 15-0 + union RCR2_REG RCR2; // 0x7806, MCBSP receive control register bits 31-16 + union RCR1_REG RCR1; // 0x7807, MCBSP receive control register bits 15-0 + union XCR2_REG XCR2; // 0x7808, MCBSP transmit control register bits 31-16 + union XCR1_REG XCR1; // 0x7809, MCBSP transmit control register bits 15-0 + union SRGR2_REG SRGR2; // 0x7810, MCBSP sample rate gen register bits 31-16 + union SRGR1_REG SRGR1; // 0x7811, MCBSP sample rate gen register bits 15-0 + union MCR2_REG MCR2; // 0x7812, MCBSP multichannel register bits 31-16 + union MCR1_REG MCR1; // 0x7813, MCBSP multichannel register bits 15-0 + union RCERA_REG RCERA; // 0x7814, MCBSP Receive channel enable partition A + union RCERB_REG RCERB; // 0x7815, MCBSP Receive channel enable partition B + union XCERA_REG XCERA; // 0x7816, MCBSP Transmit channel enable partition A + union XCERB_REG XCERB; // 0x7817, MCBSP Transmit channel enable partition B + union PCR_REG PCR; // 0x7818, MCBSP Pin control register bits 15-0 + union RCERC_REG RCERC; // 0x7819, MCBSP Receive channel enable partition C + union RCERD_REG RCERD; // 0x7820, MCBSP Receive channel enable partition D + union XCERC_REG XCERC; // 0x7821, MCBSP Transmit channel enable partition C + union XCERD_REG XCERD; // 0x7823, MCBSP Transmit channel enable partition D + union RCERE_REG RCERE; // 0x7824, MCBSP Receive channel enable partition E + union RCERF_REG RCERF; // 0x7825, MCBSP Receive channel enable partition F + union XCERE_REG XCERE; // 0x7826, MCBSP Transmit channel enable partition E + union XCERF_REG XCERF; // 0x7827, MCBSP Transmit channel enable partition F + union RCERG_REG RCERG; // 0x7828, MCBSP Receive channel enable partition G + union RCERH_REG RCERH; // 0x7829, MCBSP Receive channel enable partition H + union XCERG_REG XCERG; // 0x7830, MCBSP Transmit channel enable partition G + union XCERH_REG XCERH; // 0x7831, MCBSP Transmit channel enable partition H + Uint16 rsvd1; // 0x7832, reserved + union MFFTX_REG MFFTX; // 0x7833, MCBSP Transmit FIFO register bits + union MFFRX_REG MFFRX; // 0x7834, MCBSP Receive FIFO register bits + union MFFCT_REG MFFCT; // 0x7835, MCBSP FIFO control register bits + union MFFINT_REG MFFINT; // 0x7836, MCBSP Interrupt register bits + union MFFST_REG MFFST; // 0x7837, MCBSP Status register bits +}; + +//--------------------------------------------------------------------------- +// McBSP External References & Function Declarations: +// +extern volatile struct MCBSP_REGS McbspaRegs; + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_MCBSP_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_PieCtrl.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_PieCtrl.h new file mode 100644 index 0000000..512b29a --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_PieCtrl.h @@ -0,0 +1,153 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 28, 2005 14:57:22 $ +//########################################################################### +// +// FILE: DSP281x_PieCtrl.h +// +// TITLE: DSP281x Device PIE Control Register Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + + +#ifndef DSP281x_PIE_CTRL_H +#define DSP281x_PIE_CTRL_H + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------------- +// PIE Control Register Bit Definitions: +// +// PIECTRL: Register bit definitions: +struct PIECTRL_BITS { // bits description + Uint16 ENPIE:1; // 0 Enable PIE block + Uint16 PIEVECT:15; // 15:1 Fetched vector address +}; + +union PIECTRL_REG { + Uint16 all; + struct PIECTRL_BITS bit; +}; + +// PIEIER: Register bit definitions: +struct PIEIER_BITS { // bits description + Uint16 INTx1:1; // 0 INTx.1 + Uint16 INTx2:1; // 1 INTx.2 + Uint16 INTx3:1; // 2 INTx.3 + Uint16 INTx4:1; // 3 INTx.4 + Uint16 INTx5:1; // 4 INTx.5 + Uint16 INTx6:1; // 5 INTx.6 + Uint16 INTx7:1; // 6 INTx.7 + Uint16 INTx8:1; // 7 INTx.8 + Uint16 rsvd:8; // 15:8 reserved +}; + +union PIEIER_REG { + Uint16 all; + struct PIEIER_BITS bit; +}; + +// PIEIFR: Register bit definitions: +struct PIEIFR_BITS { // bits description + Uint16 INTx1:1; // 0 INTx.1 + Uint16 INTx2:1; // 1 INTx.2 + Uint16 INTx3:1; // 2 INTx.3 + Uint16 INTx4:1; // 3 INTx.4 + Uint16 INTx5:1; // 4 INTx.5 + Uint16 INTx6:1; // 5 INTx.6 + Uint16 INTx7:1; // 6 INTx.7 + Uint16 INTx8:1; // 7 INTx.8 + Uint16 rsvd:8; // 15:8 reserved +}; + +union PIEIFR_REG { + Uint16 all; + struct PIEIFR_BITS bit; +}; + +// PIEACK: Register bit definitions: +struct PIEACK_BITS { // bits description + Uint16 ACK1:1; // 0 Acknowledge PIE interrupt group 1 + Uint16 ACK2:1; // 1 Acknowledge PIE interrupt group 2 + Uint16 ACK3:1; // 2 Acknowledge PIE interrupt group 3 + Uint16 ACK4:1; // 3 Acknowledge PIE interrupt group 4 + Uint16 ACK5:1; // 4 Acknowledge PIE interrupt group 5 + Uint16 ACK6:1; // 5 Acknowledge PIE interrupt group 6 + Uint16 ACK7:1; // 6 Acknowledge PIE interrupt group 7 + Uint16 ACK8:1; // 7 Acknowledge PIE interrupt group 8 + Uint16 ACK9:1; // 8 Acknowledge PIE interrupt group 9 + Uint16 ACK10:1; // 9 Acknowledge PIE interrupt group 10 + Uint16 ACK11:1; // 10 Acknowledge PIE interrupt group 11 + Uint16 ACK12:1; // 11 Acknowledge PIE interrupt group 12 + Uint16 rsvd:4; // 15:12 reserved +}; + +union PIEACK_REG { + Uint16 all; + struct PIEACK_BITS bit; +}; + +//--------------------------------------------------------------------------- +// PIE Control Register File: +// +struct PIE_CTRL_REGS { + union PIECTRL_REG PIECRTL; // PIE control register + union PIEACK_REG PIEACK; // PIE acknowledge + union PIEIER_REG PIEIER1; // PIE INT1 IER register + union PIEIFR_REG PIEIFR1; // PIE INT1 IFR register + union PIEIER_REG PIEIER2; // PIE INT2 IER register + union PIEIFR_REG PIEIFR2; // PIE INT2 IFR register + union PIEIER_REG PIEIER3; // PIE INT3 IER register + union PIEIFR_REG PIEIFR3; // PIE INT3 IFR register + union PIEIER_REG PIEIER4; // PIE INT4 IER register + union PIEIFR_REG PIEIFR4; // PIE INT4 IFR register + union PIEIER_REG PIEIER5; // PIE INT5 IER register + union PIEIFR_REG PIEIFR5; // PIE INT5 IFR register + union PIEIER_REG PIEIER6; // PIE INT6 IER register + union PIEIFR_REG PIEIFR6; // PIE INT6 IFR register + union PIEIER_REG PIEIER7; // PIE INT7 IER register + union PIEIFR_REG PIEIFR7; // PIE INT7 IFR register + union PIEIER_REG PIEIER8; // PIE INT8 IER register + union PIEIFR_REG PIEIFR8; // PIE INT8 IFR register + union PIEIER_REG PIEIER9; // PIE INT9 IER register + union PIEIFR_REG PIEIFR9; // PIE INT9 IFR register + union PIEIER_REG PIEIER10; // PIE INT10 IER register + union PIEIFR_REG PIEIFR10; // PIE INT10 IFR register + union PIEIER_REG PIEIER11; // PIE INT11 IER register + union PIEIFR_REG PIEIFR11; // PIE INT11 IFR register + union PIEIER_REG PIEIER12; // PIE INT12 IER register + union PIEIFR_REG PIEIFR12; // PIE INT12 IFR register +}; + +#define PIEACK_GROUP1 0x0001; +#define PIEACK_GROUP2 0x0002; +#define PIEACK_GROUP3 0x0004; +#define PIEACK_GROUP4 0x0008; +#define PIEACK_GROUP5 0x0010; +#define PIEACK_GROUP6 0x0020; +#define PIEACK_GROUP7 0x0040; +#define PIEACK_GROUP8 0x0080; +#define PIEACK_GROUP9 0x0100; +#define PIEACK_GROUP10 0x0200; +#define PIEACK_GROUP11 0x0400; +#define PIEACK_GROUP12 0x0800; + +//--------------------------------------------------------------------------- +// PIE Control Registers External References & Function Declarations: +// +extern volatile struct PIE_CTRL_REGS PieCtrlRegs; + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_PIE_CTRL_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_PieVect.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_PieVect.h new file mode 100644 index 0000000..ec34743 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_PieVect.h @@ -0,0 +1,210 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 28, 2005 14:57:21 $ +//########################################################################### +// +// FILE: DSP281x_PieVect.h +// +// TITLE: DSP281x Devices PIE Vector Table Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_PIE_VECT_H +#define DSP281x_PIE_VECT_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +//--------------------------------------------------------------------------- +// PIE Interrupt Vector Table Definition: +// +// Create a user type called PINT (pointer to interrupt): + +typedef interrupt void(*PINT)(void); + +// Define Vector Table: +struct PIE_VECT_TABLE { + +// Reset is never fetched from this table. +// It will always be fetched from 0x3FFFC0 in either +// boot ROM or XINTF Zone 7 depending on the state of +// the XMP/MC input signal. On the F2810 it is always +// fetched from boot ROM. + + PINT PIE1_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE2_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE3_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE4_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE5_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE6_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE7_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE8_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE9_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE10_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE11_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE12_RESERVED; // @suppress("Type cannot be resolved") + PINT PIE13_RESERVED; // @suppress("Type cannot be resolved") + +// Non-Peripheral Interrupts: + PINT XINT13; // XINT13 // @suppress("Type cannot be resolved") + PINT TINT2; // CPU-Timer2 // @suppress("Type cannot be resolved") + PINT DATALOG; // Datalogging interrupt // @suppress("Type cannot be resolved") + PINT RTOSINT; // RTOS interrupt // @suppress("Type cannot be resolved") + PINT EMUINT; // Emulation interrupt // @suppress("Type cannot be resolved") + PINT XNMI; // Non-maskable interrupt // @suppress("Type cannot be resolved") + PINT ILLEGAL; // Illegal operation TRAP // @suppress("Type cannot be resolved") + PINT USER1; // User Defined trap 1 // @suppress("Type cannot be resolved") + PINT USER2; // User Defined trap 2 // @suppress("Type cannot be resolved") + PINT USER3; // User Defined trap 3 // @suppress("Type cannot be resolved") + PINT USER4; // User Defined trap 4 // @suppress("Type cannot be resolved") + PINT USER5; // User Defined trap 5 // @suppress("Type cannot be resolved") + PINT USER6; // User Defined trap 6 // @suppress("Type cannot be resolved") + PINT USER7; // User Defined trap 7 // @suppress("Type cannot be resolved") + PINT USER8; // User Defined trap 8 // @suppress("Type cannot be resolved") + PINT USER9; // User Defined trap 9 // @suppress("Type cannot be resolved") + PINT USER10; // User Defined trap 10 // @suppress("Type cannot be resolved") + PINT USER11; // User Defined trap 11 // @suppress("Type cannot be resolved") + PINT USER12; // User Defined trap 12 // @suppress("Type cannot be resolved") + +// Group 1 PIE Peripheral Vectors: + PINT PDPINTA; // EV-A // @suppress("Type cannot be resolved") + PINT PDPINTB; // EV-B // @suppress("Type cannot be resolved") + PINT rsvd1_3; // @suppress("Type cannot be resolved") + PINT XINT1; // @suppress("Type cannot be resolved") + PINT XINT2; // @suppress("Type cannot be resolved") + PINT ADCINT; // ADC // @suppress("Type cannot be resolved") + PINT TINT0; // Timer 0 // @suppress("Type cannot be resolved") + PINT WAKEINT; // WD // @suppress("Type cannot be resolved") + +// Group 2 PIE Peripheral Vectors: + PINT CMP1INT; // EV-A // @suppress("Type cannot be resolved") + PINT CMP2INT; // EV-A // @suppress("Type cannot be resolved") + PINT CMP3INT; // EV-A // @suppress("Type cannot be resolved") + PINT T1PINT; // EV-A // @suppress("Type cannot be resolved") + PINT T1CINT; // EV-A // @suppress("Type cannot be resolved") + PINT T1UFINT; // EV-A // @suppress("Type cannot be resolved") + PINT T1OFINT; // EV-A // @suppress("Type cannot be resolved") + PINT rsvd2_8; // @suppress("Type cannot be resolved") + +// Group 3 PIE Peripheral Vectors: + PINT T2PINT; // EV-A // @suppress("Type cannot be resolved") + PINT T2CINT; // EV-A // @suppress("Type cannot be resolved") + PINT T2UFINT; // EV-A // @suppress("Type cannot be resolved") + PINT T2OFINT; // EV-A // @suppress("Type cannot be resolved") + PINT CAPINT1; // EV-A // @suppress("Type cannot be resolved") + PINT CAPINT2; // EV-A // @suppress("Type cannot be resolved") + PINT CAPINT3; // EV-A // @suppress("Type cannot be resolved") + PINT rsvd3_8; // @suppress("Type cannot be resolved") + +// Group 4 PIE Peripheral Vectors: + PINT CMP4INT; // EV-B // @suppress("Type cannot be resolved") + PINT CMP5INT; // EV-B // @suppress("Type cannot be resolved") + PINT CMP6INT; // EV-B // @suppress("Type cannot be resolved") + PINT T3PINT; // EV-B // @suppress("Type cannot be resolved") + PINT T3CINT; // EV-B // @suppress("Type cannot be resolved") + PINT T3UFINT; // EV-B // @suppress("Type cannot be resolved") + PINT T3OFINT; // EV-B // @suppress("Type cannot be resolved") + PINT rsvd4_8; // @suppress("Type cannot be resolved") + +// Group 5 PIE Peripheral Vectors: + PINT T4PINT; // EV-B // @suppress("Type cannot be resolved") + PINT T4CINT; // EV-B // @suppress("Type cannot be resolved") + PINT T4UFINT; // EV-B // @suppress("Type cannot be resolved") + PINT T4OFINT; // EV-B // @suppress("Type cannot be resolved") + PINT CAPINT4; // EV-B // @suppress("Type cannot be resolved") + PINT CAPINT5; // EV-B // @suppress("Type cannot be resolved") + PINT CAPINT6; // EV-B // @suppress("Type cannot be resolved") + PINT rsvd5_8; // @suppress("Type cannot be resolved") + +// Group 6 PIE Peripheral Vectors: + PINT SPIRXINTA; // SPI-A // @suppress("Type cannot be resolved") + PINT SPITXINTA; // SPI-A // @suppress("Type cannot be resolved") + PINT rsvd6_3; // @suppress("Type cannot be resolved") + PINT rsvd6_4; // @suppress("Type cannot be resolved") + PINT MRINTA; // McBSP-A // @suppress("Type cannot be resolved") + PINT MXINTA; // McBSP-A // @suppress("Type cannot be resolved") + PINT rsvd6_7; // @suppress("Type cannot be resolved") + PINT rsvd6_8; // @suppress("Type cannot be resolved") + +// Group 7 PIE Peripheral Vectors: + PINT rsvd7_1; // @suppress("Type cannot be resolved") + PINT rsvd7_2; // @suppress("Type cannot be resolved") + PINT rsvd7_3; // @suppress("Type cannot be resolved") + PINT rsvd7_4; // @suppress("Type cannot be resolved") + PINT rsvd7_5; // @suppress("Type cannot be resolved") + PINT rsvd7_6; // @suppress("Type cannot be resolved") + PINT rsvd7_7; // @suppress("Type cannot be resolved") + PINT rsvd7_8; // @suppress("Type cannot be resolved") + +// Group 8 PIE Peripheral Vectors: + PINT rsvd8_1; // @suppress("Type cannot be resolved") + PINT rsvd8_2; // @suppress("Type cannot be resolved") + PINT rsvd8_3; // @suppress("Type cannot be resolved") + PINT rsvd8_4; // @suppress("Type cannot be resolved") + PINT rsvd8_5; // @suppress("Type cannot be resolved") + PINT rsvd8_6; // @suppress("Type cannot be resolved") + PINT rsvd8_7; // @suppress("Type cannot be resolved") + PINT rsvd8_8; // @suppress("Type cannot be resolved") + +// Group 9 PIE Peripheral Vectors: + PINT RXAINT; // SCI-A // @suppress("Type cannot be resolved") + PINT TXAINT; // SCI-A // @suppress("Type cannot be resolved") + PINT RXBINT; // SCI-B // @suppress("Type cannot be resolved") + PINT TXBINT; // SCI-B // @suppress("Type cannot be resolved") + PINT ECAN0INTA; // eCAN // @suppress("Type cannot be resolved") + PINT ECAN1INTA; // eCAN // @suppress("Type cannot be resolved") + PINT rsvd9_7; // @suppress("Type cannot be resolved") + PINT rsvd9_8; // @suppress("Type cannot be resolved") + +// Group 10 PIE Peripheral Vectors: + PINT rsvd10_1; // @suppress("Type cannot be resolved") + PINT rsvd10_2; // @suppress("Type cannot be resolved") + PINT rsvd10_3; // @suppress("Type cannot be resolved") + PINT rsvd10_4; // @suppress("Type cannot be resolved") + PINT rsvd10_5; // @suppress("Type cannot be resolved") + PINT rsvd10_6; // @suppress("Type cannot be resolved") + PINT rsvd10_7; // @suppress("Type cannot be resolved") + PINT rsvd10_8; // @suppress("Type cannot be resolved") + +// Group 11 PIE Peripheral Vectors: + PINT rsvd11_1; // @suppress("Type cannot be resolved") + PINT rsvd11_2; // @suppress("Type cannot be resolved") + PINT rsvd11_3; // @suppress("Type cannot be resolved") + PINT rsvd11_4; // @suppress("Type cannot be resolved") + PINT rsvd11_5; // @suppress("Type cannot be resolved") + PINT rsvd11_6; // @suppress("Type cannot be resolved") + PINT rsvd11_7; // @suppress("Type cannot be resolved") + PINT rsvd11_8; // @suppress("Type cannot be resolved") + +// Group 12 PIE Peripheral Vectors: + PINT rsvd12_1; // @suppress("Type cannot be resolved") + PINT rsvd12_2; // @suppress("Type cannot be resolved") + PINT rsvd12_3; // @suppress("Type cannot be resolved") + PINT rsvd12_4; // @suppress("Type cannot be resolved") + PINT rsvd12_5; // @suppress("Type cannot be resolved") + PINT rsvd12_6; // @suppress("Type cannot be resolved") + PINT rsvd12_7; // @suppress("Type cannot be resolved") + PINT rsvd12_8; // @suppress("Type cannot be resolved") +}; + +//--------------------------------------------------------------------------- +// PIE Interrupt Vector Table External References & Function Declarations: +// +extern struct PIE_VECT_TABLE PieVectTable; + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_PIE_VECT_H definition + +//=========================================================================== +// No more. +//=========================================================================== + diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Sci.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Sci.h new file mode 100644 index 0000000..2a86da0 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Sci.h @@ -0,0 +1,233 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 28, 2005 14:57:19 $ +//########################################################################### +// +// FILE: DSP281x_Sci.h +// +// TITLE: DSP281x Device SCI Register Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_SCI_H +#define DSP281x_SCI_H + + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------------- +// SCI Individual Register Bit Definitions + +//---------------------------------------------------------- +// SCICCR communication control register bit definitions: +// + +struct SCICCR_BITS { // bit description + Uint16 SCICHAR:3; // 2:0 Character length control + Uint16 ADDRIDLE_MODE:1; // 3 ADDR/IDLE Mode control + Uint16 LOOPBKENA:1; // 4 Loop Back enable + Uint16 PARITYENA:1; // 5 Parity enable + Uint16 PARITY:1; // 6 Even or Odd Parity + Uint16 STOPBITS:1; // 7 Number of Stop Bits + Uint16 rsvd1:8; // 15:8 reserved +}; + + +union SCICCR_REG { + Uint16 all; + struct SCICCR_BITS bit; +}; + +//------------------------------------------- +// SCICTL1 control register 1 bit definitions: +// + +struct SCICTL1_BITS { // bit description + Uint16 RXENA:1; // 0 SCI receiver enable + Uint16 TXENA:1; // 1 SCI transmitter enable + Uint16 SLEEP:1; // 2 SCI sleep + Uint16 TXWAKE:1; // 3 Transmitter wakeup method + Uint16 rsvd:1; // 4 reserved + Uint16 SWRESET:1; // 5 Software reset + Uint16 RXERRINTENA:1; // 6 Recieve interrupt enable + Uint16 rsvd1:9; // 15:7 reserved + +}; + +union SCICTL1_REG { + Uint16 all; + struct SCICTL1_BITS bit; +}; + +//--------------------------------------------- +// SCICTL2 control register 2 bit definitions: +// + +struct SCICTL2_BITS { // bit description + Uint16 TXINTENA:1; // 0 Transmit interrupt enable + Uint16 RXBKINTENA:1; // 1 Receiver-buffer break enable + Uint16 rsvd:4; // 5:2 reserved + Uint16 TXEMPTY:1; // 6 Transmitter empty flag + Uint16 TXRDY:1; // 7 Transmitter ready flag + Uint16 rsvd1:8; // 15:8 reserved + +}; + +union SCICTL2_REG { + Uint16 all; + struct SCICTL2_BITS bit; +}; + +//--------------------------------------------------- +// SCIRXST Receiver status register bit definitions: +// + +struct SCIRXST_BITS { // bit description + Uint16 rsvd:1; // 0 reserved + Uint16 RXWAKE:1; // 1 Receiver wakeup detect flag + Uint16 PE:1; // 2 Parity error flag + Uint16 OE:1; // 3 Overrun error flag + Uint16 FE:1; // 4 Framing error flag + Uint16 BRKDT:1; // 5 Break-detect flag + Uint16 RXRDY:1; // 6 Receiver ready flag + Uint16 RXERROR:1; // 7 Receiver error flag + +}; + +union SCIRXST_REG { + Uint16 all; + struct SCIRXST_BITS bit; +}; + +//---------------------------------------------------- +// SCIRXBUF Receiver Data Buffer with FIFO bit definitions: +// + +struct SCIRXBUF_BITS { // bits description + Uint16 RXDT:8; // 7:0 Receive word + Uint16 rsvd:6; // 13:8 reserved + Uint16 SCIFFPE:1; // 14 SCI PE error in FIFO mode + Uint16 SCIFFFE:1; // 15 SCI FE error in FIFO mode +}; + +union SCIRXBUF_REG { + Uint16 all; + struct SCIRXBUF_BITS bit; +}; + +//-------------------------------------------------- +// SCIPRI Priority control register bit definitions: +// +// + +struct SCIPRI_BITS { // bit description + Uint16 rsvd:3; // 2:0 reserved + Uint16 FREE:1; // 3 Free emulation suspend mode + Uint16 SOFT:1; // 4 Soft emulation suspend mode + Uint16 rsvd1:3; // 7:5 reserved +}; + +union SCIPRI_REG { + Uint16 all; + struct SCIPRI_BITS bit; +}; + +//------------------------------------------------- +// SCI FIFO Transmit register bit definitions: +// +// + +struct SCIFFTX_BITS { // bit description + Uint16 TXFFILIL:5; // 4:0 Interrupt level + Uint16 TXFFIENA:1; // 5 Interrupt enable + Uint16 TXINTCLR:1; // 6 Clear INT flag + Uint16 TXFFINT:1; // 7 INT flag + Uint16 TXFFST:5; // 12:8 FIFO status + Uint16 TXFIFOXRESET:1; // 13 FIFO reset + Uint16 SCIFFENA:1; // 14 Enhancement enable + Uint16 SCIRST:1; // 15 SCI reset rx/tx channels + +}; + +union SCIFFTX_REG { + Uint16 all; + struct SCIFFTX_BITS bit; +}; + +//------------------------------------------------ +// SCI FIFO recieve register bit definitions: +// +// + +struct SCIFFRX_BITS { // bits description + Uint16 RXFFIL:5; // 4:0 Interrupt level + Uint16 RXFFIENA:1; // 5 Interrupt enable + Uint16 RXFFINTCLR:1; // 6 Clear INT flag + Uint16 RXFFINT:1; // 7 INT flag + Uint16 RXFIFST:5; // 12:8 FIFO status + Uint16 RXFIFORESET:1; // 13 FIFO reset + Uint16 RXFFOVRCLR:1; // 14 Clear overflow + Uint16 RXFFOVF:1; // 15 FIFO overflow + +}; + +union SCIFFRX_REG { + Uint16 all; + struct SCIFFRX_BITS bit; +}; + +// SCI FIFO control register bit definitions: +struct SCIFFCT_BITS { // bits description + Uint16 FFTXDLY:8; // 7:0 FIFO transmit delay + Uint16 rsvd:5; // 12:8 reserved + Uint16 CDC:1; // 13 Auto baud mode enable + Uint16 ABDCLR:1; // 14 Auto baud clear + Uint16 ABD:1; // 15 Auto baud detect +}; + +union SCIFFCT_REG { + Uint16 all; + struct SCIFFCT_BITS bit; +}; + +//--------------------------------------------------------------------------- +// SCI Register File: +// +struct SCI_REGS { + union SCICCR_REG SCICCR; // Communications control register + union SCICTL1_REG SCICTL1; // Control register 1 + Uint16 SCIHBAUD; // Baud rate (high) register + Uint16 SCILBAUD; // Baud rate (low) register + union SCICTL2_REG SCICTL2; // Control register 2 + union SCIRXST_REG SCIRXST; // Recieve status register + Uint16 SCIRXEMU; // Recieve emulation buffer register + union SCIRXBUF_REG SCIRXBUF; // Recieve data buffer + Uint16 rsvd1; // reserved + Uint16 SCITXBUF; // Transmit data buffer + union SCIFFTX_REG SCIFFTX; // FIFO transmit register + union SCIFFRX_REG SCIFFRX; // FIFO recieve register + union SCIFFCT_REG SCIFFCT; // FIFO control register + Uint16 rsvd2; // reserved + Uint16 rsvd3; // reserved + union SCIPRI_REG SCIPRI; // FIFO Priority control +}; + +//--------------------------------------------------------------------------- +// SCI External References & Function Declarations: +// +extern volatile struct SCI_REGS SciaRegs; +extern volatile struct SCI_REGS ScibRegs; + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_SCI_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Spi.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Spi.h new file mode 100644 index 0000000..a5c29ab --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Spi.h @@ -0,0 +1,183 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 28, 2005 14:57:16 $ +//########################################################################### +// +// FILE: DSP281x_Spi.h +// +// TITLE: DSP281x Device SPI Register Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_SPI_H +#define DSP281x_SPI_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +//--------------------------------------------------------------------------- +// SPI Individual Register Bit Definitions: +// +// SPI FIFO Transmit register bit definitions: +struct SPIFFTX_BITS { // bit description + Uint16 TXFFIL:5; // 4:0 Interrupt level + Uint16 TXFFIENA:1; // 5 Interrupt enable + Uint16 TXFFINTCLR:1; // 6 Clear INT flag + Uint16 TXFFINT:1; // 7 INT flag + Uint16 TXFFST:5; // 12:8 FIFO status + Uint16 TXFIFO:1; // 13 FIFO reset + Uint16 SPIFFENA:1; // 14 Enhancement enable + Uint16 SPIRST:1; // 15 Reset SPI +}; + +union SPIFFTX_REG { + Uint16 all; + struct SPIFFTX_BITS bit; +}; + +//-------------------------------------------- +// SPI FIFO recieve register bit definitions: +// +// +struct SPIFFRX_BITS { // bits description + Uint16 RXFFIL:5; // 4:0 Interrupt level + Uint16 RXFFIENA:1; // 5 Interrupt enable + Uint16 RXFFINTCLR:1; // 6 Clear INT flag + Uint16 RXFFINT:1; // 7 INT flag + Uint16 RXFFST:5; // 12:8 FIFO status + Uint16 RXFIFORESET:1; // 13 FIFO reset + Uint16 RXFFOVFCLR:1; // 14 Clear overflow + Uint16 RXFFOVF:1; // 15 FIFO overflow + +}; + +union SPIFFRX_REG { + Uint16 all; + struct SPIFFRX_BITS bit; +}; + +//-------------------------------------------- +// SPI FIFO control register bit definitions: +// +// +struct SPIFFCT_BITS { // bits description + Uint16 TXDLY:8; // 7:0 FIFO transmit delay + Uint16 rsvd:8; // 15:8 reserved +}; + +union SPIFFCT_REG { + Uint16 all; + struct SPIFFCT_BITS bit; +}; + +//--------------------------------------------- +// SPI configuration register bit definitions: +// +// +struct SPICCR_BITS { // bits description + Uint16 SPICHAR:4; // 3:0 Character length control + Uint16 SPILBK:1; // 4 Loop-back enable/disable + Uint16 rsvd1:1; // 5 reserved + Uint16 CLKPOLARITY:1; // 6 Clock polarity + Uint16 SPISWRESET:1; // 7 SPI SW Reset + Uint16 rsvd2:8; // 15:8 reserved +}; + +union SPICCR_REG { + Uint16 all; + struct SPICCR_BITS bit; +}; + +//------------------------------------------------- +// SPI operation control register bit definitions: +// +// +struct SPICTL_BITS { // bits description + Uint16 SPIINTENA:1; // 0 Interrupt enable + Uint16 TALK:1; // 1 Master/Slave transmit enable + Uint16 MASTER_SLAVE:1; // 2 Network control mode + Uint16 CLK_PHASE:1; // 3 Clock phase select + Uint16 OVERRUNINTENA:1; // 4 Overrun interrupt enable + Uint16 rsvd:11; // 15:5 reserved +}; + +union SPICTL_REG { + Uint16 all; + struct SPICTL_BITS bit; +}; + +//-------------------------------------- +// SPI status register bit definitions: +// +// +struct SPISTS_BITS { // bits description + Uint16 rsvd1:5; // 4:0 reserved + Uint16 BUFFULL_FLAG:1; // 5 SPI transmit buffer full flag + Uint16 INT_FLAG:1; // 6 SPI interrupt flag + Uint16 OVERRUN_FLAG:1; // 7 SPI reciever overrun flag + Uint16 rsvd2:8; // 15:8 reserved +}; + +union SPISTS_REG { + Uint16 all; + struct SPISTS_BITS bit; +}; + +//------------------------------------------------ +// SPI priority control register bit definitions: +// +// +struct SPIPRI_BITS { // bits description + Uint16 rsvd1:4; // 3:0 reserved + Uint16 FREE:1; // 4 Free emulation mode control + Uint16 SOFT:1; // 5 Soft emulation mode control + Uint16 PRIORITY:1; // 6 Interrupt priority select + Uint16 rsvd2:9; // 15:7 reserved +}; + +union SPIPRI_REG { + Uint16 all; + struct SPIPRI_BITS bit; +}; + +//--------------------------------------------------------------------------- +// SPI Register File: +// +struct SPI_REGS { + union SPICCR_REG SPICCR; // Configuration register + union SPICTL_REG SPICTL; // Operation control register + union SPISTS_REG SPISTS; // Status register + Uint16 rsvd1; // reserved + Uint16 SPIBRR; // Baud Rate + Uint16 rsvd2; // reserved + Uint16 SPIRXEMU; // Emulation buffer + Uint16 SPIRXBUF; // Serial input buffer + Uint16 SPITXBUF; // Serial output buffer + Uint16 SPIDAT; // Serial data + union SPIFFTX_REG SPIFFTX; // FIFO transmit register + union SPIFFRX_REG SPIFFRX; // FIFO recieve register + union SPIFFCT_REG SPIFFCT; // FIFO control register + Uint16 rsvd3[2]; // reserved + union SPIPRI_REG SPIPRI; // FIFO Priority control +}; + +//--------------------------------------------------------------------------- +// SPI External References & Function Declarations: +// +extern volatile struct SPI_REGS SpiaRegs; + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_SPI_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_SysCtrl.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_SysCtrl.h new file mode 100644 index 0000000..6700f62 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_SysCtrl.h @@ -0,0 +1,325 @@ +// TI File $Revision: /main/3 $ +// Checkin $Date: March 16, 2007 13:58:47 $ +//########################################################################### +// +// FILE: DSP281x_SysCtrl.h +// +// TITLE: DSP281x Device System Control Register Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_SYS_CTRL_H +#define DSP281x_SYS_CTRL_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +//--------------------------------------------------------------------------- +// System Control Individual Register Bit Definitions: +// +// High speed peripheral clock register bit definitions: +struct HISPCP_BITS { // bits description + Uint16 HSPCLK:3; // 2:0 Rate relative to SYSCLKOUT + Uint16 rsvd1:13; // 15:3 reserved +}; + +union HISPCP_REG { + Uint16 all; + struct HISPCP_BITS bit; +}; + +// Low speed peripheral clock register bit definitions: +struct LOSPCP_BITS { // bits description + Uint16 LSPCLK:3; // 2:0 Rate relative to SYSCLKOUT + Uint16 rsvd1:13; // 15:3 reserved +}; + +union LOSPCP_REG { + Uint16 all; + struct LOSPCP_BITS bit; +}; + +// Peripheral clock control register bit definitions: +struct PCLKCR_BITS { // bits description + Uint16 EVAENCLK:1; // 0 Enable high speed clk to EV-A + Uint16 EVBENCLK:1; // 1 Enable high speed clk to EV-B + Uint16 rsvd1:1; // 2 + Uint16 ADCENCLK:1; // 3 Enable high speed clk to ADC + Uint16 rsvd2:4; // 7:4 reserved + Uint16 SPIENCLK:1; // 8 Enable low speed clk to SPI + Uint16 rsvd3:1; // 9 reserved + Uint16 SCIAENCLK:1; // 10 Enable low speed clk to SCI-A + Uint16 SCIBENCLK:1; // 11 Enable low speed clk to SCI-B + Uint16 MCBSPENCLK:1; // 12 Enable low speed clk to McBSP + Uint16 rsvd4:1; // 13 reserved + Uint16 ECANENCLK:1; // 14 Enable system clk to eCAN +}; + +union PCLKCR_REG { + Uint16 all; + struct PCLKCR_BITS bit; +}; + +// PLL control register bit definitions: +struct PLLCR_BITS { // bits description + Uint16 DIV:4; // 3:0 Set clock ratio for the PLL + Uint16 rsvd1:12; // 15:4 reserved +}; + +union PLLCR_REG { + Uint16 all; + struct PLLCR_BITS bit; +}; + +// Low Power Mode 0 control register bit definitions: +struct LPMCR0_BITS { // bits description + Uint16 LPM:2; // 1:0 Set the low power mode + Uint16 QUALSTDBY:6; // 7:2 Qualification + Uint16 rsvd1:8; // 15:8 reserved +}; + +union LPMCR0_REG { + Uint16 all; + struct LPMCR0_BITS bit; +}; + +// Low Power Mode 1 control register bit definitions: +struct LPMCR1_BITS { // bits description + Uint16 XINT1:1; // 0 Enable XINT1 to wake the device from standby + Uint16 XNMI:1; // 1 Enable XMNI to wake the device from standby + Uint16 WDINT:1; // 2 Enable watchdog interrupt to wake the device from standby + Uint16 T1CTRIP:1; // 3 Enable T1CTRIP to wake the device from standby + Uint16 T2CTRIP:1; // 4 Enable T2CTRIP to wake the device from standby + Uint16 T3CTRIP:1; // 5 Enable T3CTRIP to wake the device from standby + Uint16 T4CTRIP:1; // 6 Enable T4CTRIP to wake the device from standby + Uint16 C1TRIP:1; // 7 Enable C1TRIP to wake the device from standby + Uint16 C2TRIP:1; // 8 Enable C2TRIP to wake the device from standby + Uint16 C3TRIP:1; // 9 Enable C3TRIP to wake the device from standby + Uint16 C4TRIP:1; // 10 Enable C4TRIP to wake the device from standby + Uint16 C5TRIP:1; // 11 Enable C5TRIP to wake the device from standby + Uint16 C6TRIP:1; // 12 Enable C6TRIP to wake the device from standby + Uint16 SCIRXA:1; // 13 Enable SCIRXA to wake the device from standby + Uint16 SCIRXB:1; // 14 Enable SCIRXB to wake the device from standby + Uint16 CANRX:1; // 15 Enable CANRX to wake the device from standby +}; + +union LPMCR1_REG { + Uint16 all; + struct LPMCR1_BITS bit; +}; + +//--------------------------------------------------------------------------- +// System Control Register File: +// +struct SYS_CTRL_REGS { + Uint16 rsvd1[10]; // 0-9 + union HISPCP_REG HISPCP; // 10: High-speed peripheral clock pre-scaler + union LOSPCP_REG LOSPCP; // 11: Low-speed peripheral clock pre-scaler + union PCLKCR_REG PCLKCR; // 12: Peripheral clock control register + Uint16 rsvd2; // 13: reserved + union LPMCR0_REG LPMCR0; // 14: Low-power mode control register 0 + union LPMCR1_REG LPMCR1; // 15: Low-power mode control register 1 + Uint16 rsvd3; // 16: reserved + union PLLCR_REG PLLCR; // 17: PLL control register + // No bit definitions are defined for SCSR because + // a read-modify-write instruction can clear the WDOVERRIDE bit + Uint16 SCSR; // 18: System control and status register + Uint16 WDCNTR; // 19: WD counter register + Uint16 rsvd4; // 20 + Uint16 WDKEY; // 21: WD reset key register + Uint16 rsvd5[3]; // 22-24 + // No bit definitions are defined for WDCR because + // the proper value must be written to the WDCHK field + // whenever writing to this register. + Uint16 WDCR; // 25: WD timer control register + Uint16 rsvd6[6]; // 26-31 +}; + + +/* --------------------------------------------------- */ +/* CSM Registers */ +/* */ +/* ----------------------------------------------------*/ + +/* CSM Status & Control register bit definitions */ +struct CSMSCR_BITS { // bit description + Uint16 SECURE:1; // 0 Secure flag + Uint16 rsvd1:14; // 14-1 reserved + Uint16 FORCESEC:1; // 15 Force Secure control bit + +}; + +/* Allow access to the bit fields or entire register */ +union CSMSCR_REG { + Uint16 all; + struct CSMSCR_BITS bit; +}; + +/* CSM Register File */ +struct CSM_REGS { + Uint16 KEY0; // KEY reg bits 15-0 + Uint16 KEY1; // KEY reg bits 31-16 + Uint16 KEY2; // KEY reg bits 47-32 + Uint16 KEY3; // KEY reg bits 63-48 + Uint16 KEY4; // KEY reg bits 79-64 + Uint16 KEY5; // KEY reg bits 95-80 + Uint16 KEY6; // KEY reg bits 111-96 + Uint16 KEY7; // KEY reg bits 127-112 + Uint16 rsvd1; // reserved + Uint16 rsvd2; // reserved + Uint16 rsvd3; // reserved + Uint16 rsvd4; // reserved + Uint16 rsvd5; // reserved + Uint16 rsvd6; // reserved + Uint16 rsvd7; // reserved + union CSMSCR_REG CSMSCR; // CSM Status & Control register +}; + +/* Password locations */ +struct CSM_PWL { + Uint16 PSWD0; // PSWD bits 15-0 + Uint16 PSWD1; // PSWD bits 31-16 + Uint16 PSWD2; // PSWD bits 47-32 + Uint16 PSWD3; // PSWD bits 63-48 + Uint16 PSWD4; // PSWD bits 79-64 + Uint16 PSWD5; // PSWD bits 95-80 + Uint16 PSWD6; // PSWD bits 111-96 + Uint16 PSWD7; // PSWD bits 127-112 +}; + + + +/* Flash Registers */ + +#define FLASH_SLEEP 0x0000; +#define FLASH_STANDBY 0x0001; +#define FLASH_ACTIVE 0x0003; + + +/* Flash Option Register bit definitions */ +struct FOPT_BITS { // bit description + Uint16 ENPIPE:1; // 0 Enable Pipeline Mode + Uint16 rsvd:15; // 1-15 reserved +}; + +/* Allow access to the bit fields or entire register */ +union FOPT_REG { + Uint16 all; + struct FOPT_BITS bit; +}; + +/* Flash Power Modes Register bit definitions */ +struct FPWR_BITS { // bit description + Uint16 PWR:2; // 0-1 Power Mode bits + Uint16 rsvd:14; // 2-15 reserved +}; + +/* Allow access to the bit fields or entire register */ +union FPWR_REG { + Uint16 all; + struct FPWR_BITS bit; +}; + + +/* Flash Status Register bit definitions */ +struct FSTATUS_BITS { // bit description + Uint16 PWRS:2; // 0-1 Power Mode Status bits + Uint16 STDBYWAITS:1; // 2 Bank/Pump Sleep to Standby Wait Counter Status bits + Uint16 ACTIVEWAITS:1; // 3 Bank/Pump Standby to Active Wait Counter Status bits + Uint16 rsvd1:4; // 4-7 reserved + Uint16 V3STAT:1; // 8 VDD3V Status Latch bit + Uint16 rsvd2:7; // 9-15 reserved +}; + +/* Allow access to the bit fields or entire register */ +union FSTATUS_REG { + Uint16 all; + struct FSTATUS_BITS bit; +}; + +/* Flash Sleep to Standby Wait Counter Register bit definitions */ +struct FSTDBYWAIT_BITS { // bit description + Uint16 STDBYWAIT:9; // 0-8 Bank/Pump Sleep to Standby Wait Count bits + Uint16 rsvd:7; // 9-15 reserved +}; + +/* Allow access to the bit fields or entire register */ +union FSTDBYWAIT_REG { + Uint16 all; + struct FSTDBYWAIT_BITS bit; +}; + +/* Flash Standby to Active Wait Counter Register bit definitions */ +struct FACTIVEWAIT_BITS { // bit description + Uint16 ACTIVEWAIT:9; // 0-8 Bank/Pump Standby to Active Wait Count bits + Uint16 rsvd:7; // 9-15 reserved +}; + +/* Allow access to the bit fields or entire register */ +union FACTIVEWAIT_REG { + Uint16 all; + struct FACTIVEWAIT_BITS bit; +}; + +/* Bank Read Access Wait State Register bit definitions */ +struct FBANKWAIT_BITS { // bit description + Uint16 RANDWAIT:4; // 0-3 Flash Random Read Wait State bits + Uint16 rsvd1:4; // 4-7 reserved + Uint16 PAGEWAIT:4; // 8-11 Flash Paged Read Wait State bits + Uint16 rsvd2:4; // 12-15 reserved +}; + +/* Allow access to the bit fields or entire register */ +union FBANKWAIT_REG { + Uint16 all; + struct FBANKWAIT_BITS bit; +}; + +/* OTP Read Access Wait State Register bit definitions */ +struct FOTPWAIT_BITS { // bit description + Uint16 OTPWAIT:5; // 0-4 OTP Read Wait State bits + Uint16 rsvd:11; // 5-15 reserved +}; + +/* Allow access to the bit fields or entire register */ +union FOTPWAIT_REG { + Uint16 all; + struct FOTPWAIT_BITS bit; +}; + + +struct FLASH_REGS { + union FOPT_REG FOPT; // Option Register + Uint16 rsvd1; // reserved + union FPWR_REG FPWR; // Power Modes Register + union FSTATUS_REG FSTATUS; // Status Register + union FSTDBYWAIT_REG FSTDBYWAIT; // Pump/Bank Sleep to Standby Wait State Register + union FACTIVEWAIT_REG FACTIVEWAIT; // Pump/Bank Standby to Active Wait State Register + union FBANKWAIT_REG FBANKWAIT; // Bank Read Access Wait State Register + union FOTPWAIT_REG FOTPWAIT; // OTP Read Access Wait State Register +}; + +//--------------------------------------------------------------------------- +// System Control External References & Function Declarations: +// +extern volatile struct SYS_CTRL_REGS SysCtrlRegs; +extern volatile struct CSM_REGS CsmRegs; +extern volatile struct CSM_PWL CsmPwl; +extern volatile struct FLASH_REGS FlashRegs; + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_SYS_CTRL_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_XIntrupt.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_XIntrupt.h new file mode 100644 index 0000000..7cb66d7 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_XIntrupt.h @@ -0,0 +1,78 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 28, 2005 14:57:07 $ +//########################################################################### +// +// FILE: DSP281x_XIntrupt.h +// +// TITLE: DSP281x Device External Interrupt Register Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_XINTRUPT_H +#define DSP281x_XINTRUPT_H + + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------------- + +struct XINTCR_BITS { + Uint16 ENABLE:1; // 0 enable/disable + Uint16 rsvd1:1; // 1 reserved + Uint16 POLARITY:1; // 2 pos/neg triggered + Uint16 rsvd2:12; // 15:3 reserved +}; + +union XINTCR_REG { + Uint16 all; + struct XINTCR_BITS bit; +}; + +struct XNMICR_BITS { + Uint16 ENABLE:1; // 0 enable/disable + Uint16 SELECT:1; // 1 Timer 1 or XNMI connected to INT13 + Uint16 POLARITY:1; // 2 pos/neg triggered + Uint16 rsvd2:12; // 15:3 reserved +}; + +union XNMICR_REG { + Uint16 all; + struct XNMICR_BITS bit; +}; + + + + +//--------------------------------------------------------------------------- +// External Interrupt Register File: +// +struct XINTRUPT_REGS { + union XINTCR_REG XINT1CR; + union XINTCR_REG XINT2CR; + Uint16 rsvd1[5]; + union XNMICR_REG XNMICR; + Uint16 XINT1CTR; + Uint16 XINT2CTR; + Uint16 rsvd[5]; + Uint16 XNMICTR; +}; + +//--------------------------------------------------------------------------- +// External Interrupt References & Function Declarations: +// +extern volatile struct XINTRUPT_REGS XIntruptRegs; + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_XINTF_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Xintf.h b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Xintf.h new file mode 100644 index 0000000..b394f72 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/include/DSP281x_Xintf.h @@ -0,0 +1,111 @@ +// TI File $Revision: /main/3 $ +// Checkin $Date: March 20, 2007 16:30:14 $ +//########################################################################### +// +// FILE: DSP281x_Xintf.h +// +// TITLE: DSP281x Device External Interface Register Definitions. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#ifndef DSP281x_XINTF_H +#define DSP281x_XINTF_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +// XINTF timing register bit definitions: +struct XTIMING_BITS { // bits description + Uint16 XWRTRAIL:2; // 1:0 Write access trail timing + Uint16 XWRACTIVE:3; // 4:2 Write access active timing + Uint16 XWRLEAD:2; // 6:5 Write access lead timing + Uint16 XRDTRAIL:2; // 8:7 Read access trail timing + Uint16 XRDACTIVE:3; // 11:9 Read access active timing + Uint16 XRDLEAD:2; // 13:12 Read access lead timing + Uint16 USEREADY:1; // 14 Extend access using HW waitstates + Uint16 READYMODE:1; // 15 Ready mode + Uint16 XSIZE:2; // 17:16 XINTF bus width - must be written as 11b + Uint16 rsvd1:4; // 21:18 reserved + Uint16 X2TIMING:1; // 22 Double lead/active/trail timing + Uint16 rsvd3:9; // 31:23 reserved +}; + +union XTIMING_REG { + Uint32 all; + struct XTIMING_BITS bit; +}; + +// XINTF control register bit definitions: +struct XINTCNF2_BITS { // bits description + Uint16 WRBUFF:2; // 1:0 Write buffer depth + Uint16 CLKMODE:1; // 2 Ratio for XCLKOUT with respect to XTIMCLK + Uint16 CLKOFF:1; // 3 Disable XCLKOUT + Uint16 rsvd1:2; // 5:4 reserved + Uint16 WLEVEL:2; // 7:6 Current level of the write buffer + Uint16 MPNMC:1; // 8 Micro-processor/micro-computer mode + Uint16 HOLD:1; // 9 Hold enable/disable + Uint16 HOLDS:1; // 10 Current state of HOLDn input + Uint16 HOLDAS:1; // 11 Current state of HOLDAn output + Uint16 rsvd2:4; // 15:12 reserved + Uint16 XTIMCLK:3; // 18:16 Ratio for XTIMCLK + Uint16 rsvd3:13; // 31:19 reserved +}; + +union XINTCNF2_REG { + Uint32 all; + struct XINTCNF2_BITS bit; +}; + +// XINTF bank switching register bit definitions: +struct XBANK_BITS { // bits description + Uint16 BANK:3; // 2:0 Zone for which banking is enabled + Uint16 BCYC:3; // 5:3 XTIMCLK cycles to add + Uint16 rsvd:10; // 15:6 reserved +}; + +union XBANK_REG { + Uint16 all; + struct XBANK_BITS bit; +}; + + +//--------------------------------------------------------------------------- +// XINTF Register File: +// +struct XINTF_REGS { + union XTIMING_REG XTIMING0; + union XTIMING_REG XTIMING1; + union XTIMING_REG XTIMING2; + Uint32 rsvd1[3]; + union XTIMING_REG XTIMING6; + union XTIMING_REG XTIMING7; + Uint32 rsvd2[2]; + union XINTCNF2_REG XINTCNF2; + Uint32 rsvd3; + union XBANK_REG XBANK; + Uint16 rsvd4; + Uint16 XREVISION; + Uint16 rsvd5[5]; +}; + +//--------------------------------------------------------------------------- +// XINTF External References & Function Declarations: +// +extern volatile struct XINTF_REGS XintfRegs; + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif // end of DSP281x_XINTF_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/source/DSP281x_CpuTimers.c b/c/protocan-boot/vendor/ti/f2812/source/DSP281x_CpuTimers.c new file mode 100644 index 0000000..63bdc48 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/source/DSP281x_CpuTimers.c @@ -0,0 +1,109 @@ +// TI File $Revision: /main/3 $ +// Checkin $Date: July 9, 2009 10:51:58 $ +//########################################################################### +// +// FILE: DSP281x_CpuTimers.c +// +// TITLE: CPU 32-bit Timers Initialization & Support Functions. +// +// NOTES: CpuTimer2 is reserved for use with DSP BIOS and +// other realtime operating systems. +// +// Do not use these this timer in your application if you ever plan +// on integrating DSP-BIOS or another realtime OS. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#include "DSP281x_Device.h" // Headerfile Include File +#include "DSP281x_Examples.h" // Examples Include File +#include "DSP281x_CpuTimers.h" +struct CPUTIMER_VARS CpuTimer0; + +// When using DSP BIOS & other RTOS, comment out CPU Timer 2 code. +struct CPUTIMER_VARS CpuTimer1; +struct CPUTIMER_VARS CpuTimer2; + +//--------------------------------------------------------------------------- +// InitCpuTimers: +//--------------------------------------------------------------------------- +// This function initializes all three CPU timers to a known state. +// +void InitCpuTimers(void) +{ + // CPU Timer 0 + // Initialize address pointers to respective timer registers: + CpuTimer0.RegsAddr = &CpuTimer0Regs; + // Initialize timer period to maximum: + CpuTimer0Regs.PRD.all = 0xFFFFFFFF; + // Initialize pre-scale counter to divide by 1 (SYSCLKOUT): + CpuTimer0Regs.TPR.all = 0; + CpuTimer0Regs.TPRH.all = 0; + // Make sure timer is stopped: + CpuTimer0Regs.TCR.bit.TSS = 1; + // Reload all counter register with period value: + CpuTimer0Regs.TCR.bit.TRB = 1; + // Reset interrupt counters: + CpuTimer0.InterruptCount = 0; + + +// CpuTimer2 is reserved for DSP BIOS & other RTOS +// Do not use this timer if you ever plan on integrating +// DSP-BIOS or another realtime OS. + + // Initialize address pointers to respective timer registers: + CpuTimer1.RegsAddr = &CpuTimer1Regs; + CpuTimer2.RegsAddr = &CpuTimer2Regs; + // Initialize timer period to maximum: + CpuTimer1Regs.PRD.all = 0xFFFFFFFF; + CpuTimer2Regs.PRD.all = 0xFFFFFFFF; + // Make sure timers are stopped: + CpuTimer1Regs.TCR.bit.TSS = 1; + CpuTimer2Regs.TCR.bit.TSS = 1; + // Reload all counter register with period value: + CpuTimer1Regs.TCR.bit.TRB = 1; + CpuTimer2Regs.TCR.bit.TRB = 1; + // Reset interrupt counters: + CpuTimer1.InterruptCount = 0; + CpuTimer2.InterruptCount = 0; + +} + +//--------------------------------------------------------------------------- +// ConfigCpuTimer: +//--------------------------------------------------------------------------- +// This function initializes the selected timer to the period specified +// by the "Freq" and "Period" parameters. The "Freq" is entered as "MHz" +// and the period in "uSeconds". The timer is held in the stopped state +// after configuration. +// +void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period) +{ + Uint32 temp; + + // Initialize timer period: + Timer->CPUFreqInMHz = Freq; + Timer->PeriodInUSec = Period; + temp = (long) (Freq * Period); + Timer->RegsAddr->PRD.all = temp; + + // Set pre-scale counter to divide by 1 (SYSCLKOUT): + Timer->RegsAddr->TPR.all = 0; + Timer->RegsAddr->TPRH.all = 0; + + // Initialize timer control register: + Timer->RegsAddr->TCR.bit.TSS = 1; // 1 = Stop timer, 0 = Start/Restart Timer + Timer->RegsAddr->TCR.bit.TRB = 1; // 1 = reload timer + Timer->RegsAddr->TCR.bit.SOFT = 1; + Timer->RegsAddr->TCR.bit.FREE = 1; // Timer Free Run + Timer->RegsAddr->TCR.bit.TIE = 1; // 0 = Disable/ 1 = Enable Timer Interrupt + + // Reset interrupt counter: + Timer->InterruptCount = 0; +} + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/source/DSP281x_GlobalVariableDefs.c b/c/protocan-boot/vendor/ti/f2812/source/DSP281x_GlobalVariableDefs.c new file mode 100644 index 0000000..cdd93b0 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/source/DSP281x_GlobalVariableDefs.c @@ -0,0 +1,265 @@ +// TI File $Revision: /main/3 $ +// Checkin $Date: July 9, 2009 17:28:45 $ +//########################################################################### +// +// FILE: DSP281x_GlobalVariableDefs.c +// +// TITLE: DSP281x Global Variables and Data Section Pragmas. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#include "DSP281x_Device.h" // DSP281x Headerfile Include File + +//--------------------------------------------------------------------------- +// Define Global Peripheral Variables: +// + +#ifdef __cplusplus +#pragma DATA_SECTION("AdcRegsFile") +#else +#pragma DATA_SECTION(AdcRegs,"AdcRegsFile"); +#endif +volatile struct ADC_REGS AdcRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("CpuTimer0RegsFile") +#else +#pragma DATA_SECTION(CpuTimer0Regs,"CpuTimer0RegsFile"); +#endif +volatile struct CPUTIMER_REGS CpuTimer0Regs; +//---------------------------------------- + +#ifdef __cplusplus +#pragma DATA_SECTION("CpuTimer1RegsFile") +#else +#pragma DATA_SECTION(CpuTimer1Regs,"CpuTimer1RegsFile"); +#endif +volatile struct CPUTIMER_REGS CpuTimer1Regs; +//---------------------------------------- + +#ifdef __cplusplus +#pragma DATA_SECTION("CpuTimer2RegsFile") +#else +#pragma DATA_SECTION(CpuTimer2Regs,"CpuTimer2RegsFile"); +#endif +volatile struct CPUTIMER_REGS CpuTimer2Regs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("ECanaRegsFile") +#else +#pragma DATA_SECTION(ECanaRegs,"ECanaRegsFile"); +#endif +volatile struct ECAN_REGS ECanaRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("ECanaMboxesFile") +#else +#pragma DATA_SECTION(ECanaMboxes,"ECanaMboxesFile"); +#endif +volatile struct ECAN_MBOXES ECanaMboxes; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("ECanaLAMRegsFile") +#else +#pragma DATA_SECTION(ECanaLAMRegs,"ECanaLAMRegsFile"); +#endif +volatile struct LAM_REGS ECanaLAMRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("ECanaMOTSRegsFile") +#else +#pragma DATA_SECTION(ECanaMOTSRegs,"ECanaMOTSRegsFile"); +#endif +volatile struct MOTS_REGS ECanaMOTSRegs; + + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("ECanaMOTORegsFile") +#else +#pragma DATA_SECTION(ECanaMOTORegs,"ECanaMOTORegsFile"); +#endif +volatile struct MOTO_REGS ECanaMOTORegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("EvaRegsFile") +#else +#pragma DATA_SECTION(EvaRegs,"EvaRegsFile"); +#endif +volatile struct EVA_REGS EvaRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("EvbRegsFile") +#else +#pragma DATA_SECTION(EvbRegs,"EvbRegsFile"); +#endif +volatile struct EVB_REGS EvbRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("GpioDataRegsFile") +#else +#pragma DATA_SECTION(GpioDataRegs,"GpioDataRegsFile"); +#endif +volatile struct GPIO_DATA_REGS GpioDataRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("GpioMuxRegsFile") +#else +#pragma DATA_SECTION(GpioMuxRegs,"GpioMuxRegsFile"); +#endif +volatile struct GPIO_MUX_REGS GpioMuxRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("McbspaRegsFile") +#else +#pragma DATA_SECTION(McbspaRegs,"McbspaRegsFile"); +#endif +volatile struct MCBSP_REGS McbspaRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("PieCtrlRegsFile") +#else +#pragma DATA_SECTION(PieCtrlRegs,"PieCtrlRegsFile"); +#endif +volatile struct PIE_CTRL_REGS PieCtrlRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("PieVectTableFile") +#else +#pragma DATA_SECTION(PieVectTable,"PieVectTableFile"); +#endif +struct PIE_VECT_TABLE PieVectTable; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("SciaRegsFile") +#else +#pragma DATA_SECTION(SciaRegs,"SciaRegsFile"); +#endif +volatile struct SCI_REGS SciaRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("ScibRegsFile") +#else +#pragma DATA_SECTION(ScibRegs,"ScibRegsFile"); +#endif +volatile struct SCI_REGS ScibRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("SpiaRegsFile") +#else +#pragma DATA_SECTION(SpiaRegs,"SpiaRegsFile"); +#endif +volatile struct SPI_REGS SpiaRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("SysCtrlRegsFile") +#else +#pragma DATA_SECTION(SysCtrlRegs,"SysCtrlRegsFile"); +#endif +volatile struct SYS_CTRL_REGS SysCtrlRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("DevEmuRegsFile") +#else +#pragma DATA_SECTION(DevEmuRegs,"DevEmuRegsFile"); +#endif +volatile struct DEV_EMU_REGS DevEmuRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("CsmRegsFile") +#else +#pragma DATA_SECTION(CsmRegs,"CsmRegsFile"); +#endif +volatile struct CSM_REGS CsmRegs; + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("CsmPwlFile") +#else +#pragma DATA_SECTION(CsmPwl,"CsmPwlFile"); +#endif +volatile struct CSM_PWL CsmPwl; + + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("FlashRegsFile") +#else +#pragma DATA_SECTION(FlashRegs,"FlashRegsFile"); +#endif +volatile struct FLASH_REGS FlashRegs; + +#if DSP28_F2812 +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("XintfRegsFile") +#else +#pragma DATA_SECTION(XintfRegs,"XintfRegsFile"); +#endif +volatile struct XINTF_REGS XintfRegs; +#endif + +//---------------------------------------- +#ifdef __cplusplus +#pragma DATA_SECTION("XIntruptRegsFile") +#else +#pragma DATA_SECTION(XIntruptRegs,"XIntruptRegsFile"); +#endif +volatile struct XINTRUPT_REGS XIntruptRegs; + + + +// The following are provided to support alternate notation +// that was used in an early version of the header files + +#define ADCRegs AdcRegs +#define CPUTimer0Regs CpuTimer0Regs +#define CPUTimer1Regs CpuTimer1Regs +#define CPUTimer2Regs CpuTimer2Regs +#define ECANARegs ECanaRegs +#define ECANAMboxes ECanaMboxes +#define EVARegs EvaRegs +#define GPIODataRegs GpioDataRegs +#define GPIOMuxRegs GpioMuxRegs +#define MCBSPARegs McbspaRegs +#define PIECtrlRegs PieCtrlRegs +#define PIEVectTable PieVectTable +#define SCIARegs SciaRegs +#define SCIBRegs ScibRegs +#define SYSCtrlRegs SysCtrlRegs +#define DEVEmuRegs DevEmuRegs +#define CSMRegs CsmRegs +#define CSMPwl CsmPwl +#define FLASHRegs FlashRegs +#define XINTFRegs XintfRegs +#define XINTRUPTRegs XIntruptRegs + + + + + + + + + diff --git a/c/protocan-boot/vendor/ti/f2812/source/DSP281x_PieCtrl.c b/c/protocan-boot/vendor/ti/f2812/source/DSP281x_PieCtrl.c new file mode 100644 index 0000000..8d38af6 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/source/DSP281x_PieCtrl.c @@ -0,0 +1,84 @@ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 29, 2005 11:09:05 $ +//########################################################################### +// +// FILE: DSP281x_PieCtrl.c +// +// TITLE: DSP281x Device PIE Control Register Initialization Functions. +// + +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#include "DSP281x_Device.h" // DSP281x Headerfile Include File +#include "DSP281x_Examples.h" // DSP281x Examples Include File + +//--------------------------------------------------------------------------- +// InitPieCtrl: +//--------------------------------------------------------------------------- +// This function initializes the PIE control registers to a known state. +// +void InitPieCtrl(void) +{ + // Disable Interrupts at the CPU level: + DINT; + + // Disable the PIE + PieCtrlRegs.PIECRTL.bit.ENPIE = 0; + + // Clear all PIEIER registers: + PieCtrlRegs.PIEIER1.all = 0; + PieCtrlRegs.PIEIER2.all = 0; + PieCtrlRegs.PIEIER3.all = 0; + PieCtrlRegs.PIEIER4.all = 0; + PieCtrlRegs.PIEIER5.all = 0; + PieCtrlRegs.PIEIER6.all = 0; + PieCtrlRegs.PIEIER7.all = 0; + PieCtrlRegs.PIEIER8.all = 0; + PieCtrlRegs.PIEIER9.all = 0; + PieCtrlRegs.PIEIER10.all = 0; + PieCtrlRegs.PIEIER11.all = 0; + PieCtrlRegs.PIEIER12.all = 0; + + // Clear all PIEIFR registers: + PieCtrlRegs.PIEIFR1.all = 0; + PieCtrlRegs.PIEIFR2.all = 0; + PieCtrlRegs.PIEIFR3.all = 0; + PieCtrlRegs.PIEIFR4.all = 0; + PieCtrlRegs.PIEIFR5.all = 0; + PieCtrlRegs.PIEIFR6.all = 0; + PieCtrlRegs.PIEIFR7.all = 0; + PieCtrlRegs.PIEIFR8.all = 0; + PieCtrlRegs.PIEIFR9.all = 0; + PieCtrlRegs.PIEIFR10.all = 0; + PieCtrlRegs.PIEIFR11.all = 0; + PieCtrlRegs.PIEIFR12.all = 0; + + +} + +//--------------------------------------------------------------------------- +// EnableInterrupts: +//--------------------------------------------------------------------------- +// This function enables the PIE module and CPU interrupts +// +void EnableInterrupts() +{ + + // Enable the PIE + PieCtrlRegs.PIECRTL.bit.ENPIE = 1; + + // Enables PIE to drive a pulse into the CPU + PieCtrlRegs.PIEACK.all = 0xFFFF; + + // Enable Interrupts at the CPU level + EINT; + +} + + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/source/DSP281x_SysCtrl.c b/c/protocan-boot/vendor/ti/f2812/source/DSP281x_SysCtrl.c new file mode 100644 index 0000000..9db37eb --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/source/DSP281x_SysCtrl.c @@ -0,0 +1,295 @@ +// TI File $Revision: /main/3 $ +// Checkin $Date: April 4, 2007 13:20:29 $ +//########################################################################### +// +// FILE: DSP281x_SysCtrl.c +// +// TITLE: DSP281x Device System Control Initialization & Support Functions. +// +// DESCRIPTION: +// +// Example initialization of system resources. +// +//########################################################################### +// $TI Release: DSP281x C/C++ Header Files V1.20 $ +// $Release Date: July 27, 2009 $ +//########################################################################### + +#include "DSP281x_Device.h" // DSP281x Headerfile Include File +#include "DSP281x_Examples.h" // DSP281x Examples Include File + +// Functions that will be run from RAM need to be assigned to +// a different section. This section will then be mapped to a load and +// run address using the linker cmd file. + +#pragma CODE_SECTION(InitFlash, "ramfuncs"); + +#pragma DATA_SECTION(HSPCLK,".fast_vars1"); +float SYSCLKOUT, LSPCLK, HSPCLK; + +//--------------------------------------------------------------------------- +// InitSysCtrl: +//--------------------------------------------------------------------------- +// This function initializes the System Control registers to a known state. +// - Disables the watchdog +// - Set the PLLCR for proper SYSCLKOUT frequency +// - Set the pre-scaler for the high and low frequency peripheral clocks +// - Enable the clocks to the peripherals + +void InitSysCtrl(void) +{ + +// On F2812/F2810 TMX samples prior to rev C this initialization was +// required. For Rev C and after this is no longer required +/* + EALLOW; + DevEmuRegs.M0RAMDFT = 0x0300; + DevEmuRegs.M1RAMDFT = 0x0300; + DevEmuRegs.L0RAMDFT = 0x0300; + DevEmuRegs.L1RAMDFT = 0x0300; + DevEmuRegs.H0RAMDFT = 0x0300; + EDIS; +*/ + // Disable the watchdog + DisableDog(); + + // Initialize the PLLCR to 0xA + InitPll(0xA); + + // Initialize the peripheral clocks + InitPeripheralClocks(); +} + + +//--------------------------------------------------------------------------- +// Example: InitFlash: +//--------------------------------------------------------------------------- +// This function initializes the Flash Control registers + +// CAUTION +// This function MUST be executed out of RAM. Executing it +// out of OTP/Flash will yield unpredictable results + +void InitFlash(void) +{ + + + + EALLOW; + //Enable Flash Pipeline mode to improve performance + //of code executed from Flash. + FlashRegs.FOPT.bit.ENPIPE = 1; + + // CAUTION + //Minimum waitstates required for the flash operating + //at a given CPU rate must be characterized by TI. + //Refer to the datasheet for the latest information. + + //Set the Random Waitstate for the Flash + FlashRegs.FBANKWAIT.bit.RANDWAIT = 5; + + //Set the Paged Waitstate for the Flash + FlashRegs.FBANKWAIT.bit.PAGEWAIT = 5; + + // CAUTION + //Minimum cycles required to move between power states + //at a given CPU rate must be characterized by TI. + //Refer to the datasheet for the latest information. + + //For now use the default count + //Set number of cycles to transition from sleep to standby + FlashRegs.FSTDBYWAIT.bit.STDBYWAIT = 0x01FF; + + //Set number of cycles to transition from standby to active + FlashRegs.FACTIVEWAIT.bit.ACTIVEWAIT = 0x01FF; + +// new add!!! + + FlashRegs.FPWR.bit.PWR = 3; // Pump and bank set to active mode + FlashRegs.FSTATUS.bit.V3STAT = 1; // Clear the 3VSTAT bit + FlashRegs.FOTPWAIT.bit.OTPWAIT = 8; // OTP waitstates + +///////// + + EDIS; + + //Force a pipeline flush to ensure that the write to + //the last register configured occurs before returning. + + asm(" RPT #7 || NOP"); +} + + +//--------------------------------------------------------------------------- +// Example: KickDog: +//--------------------------------------------------------------------------- +// This function resets the watchdog timer. +// Enable this function for using KickDog in the application + +void KickDog(void) +{ + EALLOW; + SysCtrlRegs.WDKEY = 0x0055; + SysCtrlRegs.WDKEY = 0x00AA; + EDIS; +} + +//--------------------------------------------------------------------------- +// Example: DisableDog: +//--------------------------------------------------------------------------- +// This function disables the watchdog timer. + +void DisableDog(void) +{ + EALLOW; + SysCtrlRegs.WDCR= 0x0068; + EDIS; +} + +//--------------------------------------------------------------------------- +// Example: InitPll: +//--------------------------------------------------------------------------- +// This function initializes the PLLCR register. + +void InitPll(Uint16 val) +{ + float Val; + volatile Uint16 iVol; + + Val = (val)?val:1; + Val = XCLKIN * (Val / 2); + SYSCLKOUT = Val; + + + + if (SysCtrlRegs.PLLCR.bit.DIV != val) + { + EALLOW; + SysCtrlRegs.PLLCR.bit.DIV = val; + EDIS; + + // Optional: Wait for PLL to lock. + // During this time the CPU will switch to OSCCLK/2 until the PLL is + // stable. Once the PLL is stable the CPU will switch to the new PLL value. + // + // This switch time is 131072 CLKIN cycles as of Rev C silicon. + // + // Code is not required to sit and wait for the PLL to lock. + // However, if the code does anything that is timing critical, + // and requires the correct clock be locked, then it is best to + // wait until this switching has completed. + + // If this function is run from waitstated memory, then the loop count can + // be reduced as long as the minimum switch time is still met. + + // iVol is volatile so the compiler will not optimize this loop out + // + // The watchdog should be disabled before this loop, or fed within + // the loop. + + DisableDog(); + + // Wait lock cycles. + // Note, This loop is tuned to 0-waitstate RAM memory. If this + // function is run from wait-stated memory such as Flash or XINTF, + // then the number of times through the loop can be reduced + // accordingly. + for(iVol= 0; iVol< ( (131072/2)/12 ); iVol++) + { + + } + } +} + +//-------------------------------------------------------------------------- +// Example: InitPeripheralClocks: +//--------------------------------------------------------------------------- +// This function initializes the clocks to the peripheral modules. +// First the high and low clock prescalers are set +// Second the clocks are enabled to each peripheral. +// To reduce power, leave clocks to unused peripherals disabled +// Note: If a peripherals clock is not enabled then you cannot +// read or write to the registers for that peripheral + +void InitPeripheralClocks(void) +{ + float Val; + + EALLOW; +// HISPCP/LOSPCP prescale register settings, normally it will be set to default values + SysCtrlRegs.HISPCP.all = 0x002;//0x0002; + SysCtrlRegs.LOSPCP.all = 0x0000;//0x4 + + + Val = (SysCtrlRegs.HISPCP.all)? + SysCtrlRegs.HISPCP.all*2 : 1; + Val = SYSCLKOUT / Val; + + HSPCLK = Val; + + Val = (SysCtrlRegs.LOSPCP.all)? + SysCtrlRegs.LOSPCP.all*2 : 1; + Val = SYSCLKOUT / Val; + LSPCLK = Val; + +// Peripheral clock enables set for the selected peripherals. + SysCtrlRegs.PCLKCR.bit.EVAENCLK=1; + SysCtrlRegs.PCLKCR.bit.EVBENCLK=1; + SysCtrlRegs.PCLKCR.bit.SCIAENCLK=1; + SysCtrlRegs.PCLKCR.bit.SCIBENCLK=1; + SysCtrlRegs.PCLKCR.bit.MCBSPENCLK=1; + SysCtrlRegs.PCLKCR.bit.SPIENCLK=1; + SysCtrlRegs.PCLKCR.bit.ECANENCLK=1; + SysCtrlRegs.PCLKCR.bit.ADCENCLK=1; + EDIS; +} + +//--------------------------------------------------------------------------- +// Example: CsmUnlock: +//--------------------------------------------------------------------------- +// This function unlocks the CSM. User must replace 0xFFFF's with current +// password for the DSP. Returns 1 if unlock is successful. + +#define STATUS_FAIL 0 +#define STATUS_SUCCESS 1 + +Uint16 CsmUnlock() +{ + volatile Uint16 temp; + + // Load the key registers with the current password. The 0xFFFF's are dummy + // passwords. User should replace them with the correct password for the DSP. + + EALLOW; + CsmRegs.KEY0 = 0xFFFF; + CsmRegs.KEY1 = 0xFFFF; + CsmRegs.KEY2 = 0xFFFF; + CsmRegs.KEY3 = 0xFFFF; + CsmRegs.KEY4 = 0xFFFF; + CsmRegs.KEY5 = 0xFFFF; + CsmRegs.KEY6 = 0xFFFF; + CsmRegs.KEY7 = 0xFFFF; + EDIS; + + // Perform a dummy read of the password locations + // if they match the key values, the CSM will unlock + + temp = CsmPwl.PSWD0; + temp = CsmPwl.PSWD1; + temp = CsmPwl.PSWD2; + temp = CsmPwl.PSWD3; + temp = CsmPwl.PSWD4; + temp = CsmPwl.PSWD5; + temp = CsmPwl.PSWD6; + temp = CsmPwl.PSWD7; + + // If the CSM unlocked, return succes, otherwise return + // failure. + if (CsmRegs.CSMSCR.bit.SECURE == 0) return STATUS_SUCCESS; + else return STATUS_FAIL; + +} + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f2812/source/DSP281x_usDelay.asm b/c/protocan-boot/vendor/ti/f2812/source/DSP281x_usDelay.asm new file mode 100644 index 0000000..e1b644e --- /dev/null +++ b/c/protocan-boot/vendor/ti/f2812/source/DSP281x_usDelay.asm @@ -0,0 +1,71 @@ +;// TI File $Revision: /main/2 $ +;// Checkin $Date: April 29, 2005 11:01:42 $ +;//########################################################################### +;// +;// FILE: DSP281x_usDelay.asm +;// +;// TITLE: Simple delay function +;// +;// DESCRIPTION: +;// +;// This is a simple delay function that can be used to insert a specified +;// delay into code. +;// +;// This function is only accurate if executed from internal zero-waitstate +;// SARAM. If it is executed from waitstate memory then the delay will be +;// longer then specified. +;// +;// To use this function: +;// +;// 1 - update the CPU clock speed in the DSP281x_Examples.h +;// file. For example: +;// #define CPU_CLOCK_SPEED 6.6667L // for a 150MHz CPU clock speed +;// +;// 2 - Call this function by using the DELAY_US(A) macro +;// that is defined in the DSP28_Device.h file. This macro +;// will convert the number of microseconds specified +;// into a loop count for use with this function. +;// This count will be based on the CPU frequency you specify. +;// +;// 3 - For the most accurate delay +;// - Execute this function in 0 waitstate RAM. +;// - Disable interrupts before calling the function +;// If you do not disable interrupts, then think of +;// this as an "at least" delay function as the actual +;// delay may be longer. +;// +;// The C assembly call from the DELAY_US(time) macro will +;// look as follows: +;// +;// extern void Delay(long LoopCount); +;// +;// MOV AL,#LowLoopCount +;// MOV AH,#HighLoopCount +;// LCR _Delay +;// +;// Or as follows (if count is less then 16-bits): +;// +;// MOV ACC,#LoopCount +;// LCR _Delay +;// +;// +;//########################################################################### +;// $TI Release: DSP281x C/C++ Header Files V1.20 $ +;// $Release Date: July 27, 2009 $ +;//########################################################################### + .def _DSP28x_usDelay + .sect ".fast_run" + + .global __DSP28x_usDelay +_DSP28x_usDelay: + SUB ACC,#1 + BF _DSP28x_usDelay,GEQ ;; Loop if ACC >= 0 + LRETR + +;There is a 9/10 cycle overhead and each loop +;takes five cycles. The LoopCount is given by +;the following formula: +; DELAY_CPU_CYCLES = 9 + 5*LoopCount +; LoopCount = (DELAY_CPU_CYCLES - 9) / 5 +; The macro DELAY_US(A) performs this calculation for you +;================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/cmd/DSP2833x_Headers_nonBIOS.cmd b/c/protocan-boot/vendor/ti/f28335/cmd/DSP2833x_Headers_nonBIOS.cmd new file mode 100644 index 0000000..d16ae33 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/cmd/DSP2833x_Headers_nonBIOS.cmd @@ -0,0 +1,240 @@ +/* Поставляемое TI описание Headers_nonBIOS для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +/* +// TI File $Revision: /main/8 $ +// Checkin $Date: June 2, 2008 11:12:24 $ +//########################################################################### +// +// FILE: DSP2833x_Headers_nonBIOS.cmd +// +// TITLE: DSP2833x Peripheral registers linker command file +// +// DESCRIPTION: +// +// This file is for use in Non-BIOS applications. +// +// Linker command file to place the peripheral structures +// used within the DSP2833x headerfiles into the correct memory +// mapped locations. +// +// This version of the file includes the PieVectorTable structure. +// For BIOS applications, please use the DSP2833x_Headers_BIOS.cmd file +// which does not include the PieVectorTable structure. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### +*/ + +/* Начинает описание физических блоков памяти для линкера. */ +MEMORY +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + PAGE 0: /* Program Memory */ /* Выбирает страницу адресного пространства линкера: 0 — программа, 1 — данные. */ + + PAGE 1: /* Data Memory */ /* Выбирает страницу адресного пространства линкера: 0 — программа, 1 — данные. */ + + DEV_EMU : origin = 0x000880, length = 0x000180 /* device emulation registers */ /* Записывает origin значением 0x000880, length = 0x000180; данные origin. */ + FLASH_REGS : origin = 0x000A80, length = 0x000060 /* FLASH registers */ /* Записывает origin значением 0x000A80, length = 0x000060; данные origin. */ + CSM : origin = 0x000AE0, length = 0x000010 /* code security module registers */ /* Записывает origin значением 0x000AE0, length = 0x000010; данные origin. */ + + ADC_MIRROR : origin = 0x000B00, length = 0x000010 /* ADC Results register mirror */ /* Записывает origin значением 0x000B00, length = 0x000010; данные origin. */ + + XINTF : origin = 0x000B20, length = 0x000020 /* external interface registers */ /* Записывает origin значением 0x000B20, length = 0x000020; данные origin. */ + + CPU_TIMER0 : origin = 0x000C00, length = 0x000008 /* CPU Timer0 registers */ /* Записывает origin значением 0x000C00, length = 0x000008; данные origin. */ + CPU_TIMER1 : origin = 0x000C08, length = 0x000008 /* CPU Timer0 registers (CPU Timer1 & Timer2 reserved TI use)*/ /* Записывает origin значением 0x000C08, length = 0x000008; данные origin. */ + CPU_TIMER2 : origin = 0x000C10, length = 0x000008 /* CPU Timer0 registers (CPU Timer1 & Timer2 reserved TI use)*/ /* Записывает origin значением 0x000C10, length = 0x000008; данные origin. */ + + PIE_CTRL : origin = 0x000CE0, length = 0x000020 /* PIE control registers */ /* Записывает origin значением 0x000CE0, length = 0x000020; данные origin. */ + PIE_VECT : origin = 0x000D00, length = 0x000100 /* PIE Vector Table */ /* Записывает origin значением 0x000D00, length = 0x000100; данные origin. */ + + DMA : origin = 0x001000, length = 0x000200 /* DMA registers */ /* Записывает origin значением 0x001000, length = 0x000200; данные origin. */ + + MCBSPA : origin = 0x005000, length = 0x000040 /* McBSP-A registers */ /* Записывает origin значением 0x005000, length = 0x000040; данные origin. */ + MCBSPB : origin = 0x005040, length = 0x000040 /* McBSP-B registers */ /* Записывает origin значением 0x005040, length = 0x000040; данные origin. */ + + ECANA : origin = 0x006000, length = 0x000040 /* eCAN-A control and status registers */ /* Записывает origin значением 0x006000, length = 0x000040; данные origin. */ + ECANA_LAM : origin = 0x006040, length = 0x000040 /* eCAN-A local acceptance masks */ /* Записывает origin значением 0x006040, length = 0x000040; данные origin. */ + ECANA_MOTS : origin = 0x006080, length = 0x000040 /* eCAN-A message object time stamps */ /* Записывает origin значением 0x006080, length = 0x000040; данные origin. */ + ECANA_MOTO : origin = 0x0060C0, length = 0x000040 /* eCAN-A object time-out registers */ /* Записывает origin значением 0x0060C0, length = 0x000040; данные origin. */ + ECANA_MBOX : origin = 0x006100, length = 0x000100 /* eCAN-A mailboxes */ /* Записывает origin значением 0x006100, length = 0x000100; данные origin. */ + + ECANB : origin = 0x006200, length = 0x000040 /* eCAN-B control and status registers */ /* Записывает origin значением 0x006200, length = 0x000040; данные origin. */ + ECANB_LAM : origin = 0x006240, length = 0x000040 /* eCAN-B local acceptance masks */ /* Записывает origin значением 0x006240, length = 0x000040; данные origin. */ + ECANB_MOTS : origin = 0x006280, length = 0x000040 /* eCAN-B message object time stamps */ /* Записывает origin значением 0x006280, length = 0x000040; данные origin. */ + ECANB_MOTO : origin = 0x0062C0, length = 0x000040 /* eCAN-B object time-out registers */ /* Записывает origin значением 0x0062C0, length = 0x000040; данные origin. */ + ECANB_MBOX : origin = 0x006300, length = 0x000100 /* eCAN-B mailboxes */ /* Записывает origin значением 0x006300, length = 0x000100; данные origin. */ + + EPWM1 : origin = 0x006800, length = 0x000022 /* Enhanced PWM 1 registers */ /* Записывает origin значением 0x006800, length = 0x000022; данные origin. */ + EPWM2 : origin = 0x006840, length = 0x000022 /* Enhanced PWM 2 registers */ /* Записывает origin значением 0x006840, length = 0x000022; данные origin. */ + EPWM3 : origin = 0x006880, length = 0x000022 /* Enhanced PWM 3 registers */ /* Записывает origin значением 0x006880, length = 0x000022; данные origin. */ + EPWM4 : origin = 0x0068C0, length = 0x000022 /* Enhanced PWM 4 registers */ /* Записывает origin значением 0x0068C0, length = 0x000022; данные origin. */ + EPWM5 : origin = 0x006900, length = 0x000022 /* Enhanced PWM 5 registers */ /* Записывает origin значением 0x006900, length = 0x000022; данные origin. */ + EPWM6 : origin = 0x006940, length = 0x000022 /* Enhanced PWM 6 registers */ /* Записывает origin значением 0x006940, length = 0x000022; данные origin. */ + + ECAP1 : origin = 0x006A00, length = 0x000020 /* Enhanced Capture 1 registers */ /* Записывает origin значением 0x006A00, length = 0x000020; данные origin. */ + ECAP2 : origin = 0x006A20, length = 0x000020 /* Enhanced Capture 2 registers */ /* Записывает origin значением 0x006A20, length = 0x000020; данные origin. */ + ECAP3 : origin = 0x006A40, length = 0x000020 /* Enhanced Capture 3 registers */ /* Записывает origin значением 0x006A40, length = 0x000020; данные origin. */ + ECAP4 : origin = 0x006A60, length = 0x000020 /* Enhanced Capture 4 registers */ /* Записывает origin значением 0x006A60, length = 0x000020; данные origin. */ + ECAP5 : origin = 0x006A80, length = 0x000020 /* Enhanced Capture 5 registers */ /* Записывает origin значением 0x006A80, length = 0x000020; данные origin. */ + ECAP6 : origin = 0x006AA0, length = 0x000020 /* Enhanced Capture 6 registers */ /* Записывает origin значением 0x006AA0, length = 0x000020; данные origin. */ + + EQEP1 : origin = 0x006B00, length = 0x000040 /* Enhanced QEP 1 registers */ /* Записывает origin значением 0x006B00, length = 0x000040; данные origin. */ + EQEP2 : origin = 0x006B40, length = 0x000040 /* Enhanced QEP 2 registers */ /* Записывает origin значением 0x006B40, length = 0x000040; данные origin. */ + + GPIOCTRL : origin = 0x006F80, length = 0x000040 /* GPIO control registers */ /* Записывает origin значением 0x006F80, length = 0x000040; данные origin. */ + GPIODAT : origin = 0x006FC0, length = 0x000020 /* GPIO data registers */ /* Записывает origin значением 0x006FC0, length = 0x000020; данные origin. */ + GPIOINT : origin = 0x006FE0, length = 0x000020 /* GPIO interrupt/LPM registers */ /* Записывает origin значением 0x006FE0, length = 0x000020; данные origin. */ + + SYSTEM : origin = 0x007010, length = 0x000020 /* System control registers */ /* Записывает origin значением 0x007010, length = 0x000020; данные origin. */ + SPIA : origin = 0x007040, length = 0x000010 /* SPI-A registers */ /* Записывает origin значением 0x007040, length = 0x000010; данные origin. */ + SCIA : origin = 0x007050, length = 0x000010 /* SCI-A registers */ /* Записывает origin значением 0x007050, length = 0x000010; данные origin. */ + XINTRUPT : origin = 0x007070, length = 0x000010 /* external interrupt registers */ /* Записывает origin значением 0x007070, length = 0x000010; данные origin. */ + + ADC : origin = 0x007100, length = 0x000020 /* ADC registers */ /* Записывает origin значением 0x007100, length = 0x000020; данные origin. */ + + SCIB : origin = 0x007750, length = 0x000010 /* SCI-B registers */ /* Записывает origin значением 0x007750, length = 0x000010; данные origin. */ + + SCIC : origin = 0x007770, length = 0x000010 /* SCI-C registers */ /* Записывает origin значением 0x007770, length = 0x000010; данные origin. */ + + I2CA : origin = 0x007900, length = 0x000040 /* I2C-A registers */ /* Записывает origin значением 0x007900, length = 0x000040; данные origin. */ + + CSM_PWL : origin = 0x33FFF8, length = 0x000008 /* Part of FLASHA. CSM password locations. */ /* Записывает origin значением 0x33FFF8, length = 0x000008; данные origin. */ + + PARTID : origin = 0x380090, length = 0x000001 /* Part ID register location */ /* Записывает origin значением 0x380090, length = 0x000001; данные origin. */ +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + + +/* Начинает описание размещения секций объектных файлов для линкера. */ +SECTIONS +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Записывает PAGE значением 1; данные PAGE. */ + PieVectTableFile : > PIE_VECT, PAGE = 1 + +/*** Peripheral Frame 0 Register Structures ***/ + /* Записывает PAGE значением 1; данные PAGE. */ + DevEmuRegsFile : > DEV_EMU, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + FlashRegsFile : > FLASH_REGS, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + CsmRegsFile : > CSM, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + AdcMirrorFile : > ADC_MIRROR, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + XintfRegsFile : > XINTF, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + CpuTimer0RegsFile : > CPU_TIMER0, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + CpuTimer1RegsFile : > CPU_TIMER1, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + CpuTimer2RegsFile : > CPU_TIMER2, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + PieCtrlRegsFile : > PIE_CTRL, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + DmaRegsFile : > DMA, PAGE = 1 + +/*** Peripheral Frame 3 Register Structures ***/ + /* Записывает PAGE значением 1; данные PAGE. */ + McbspaRegsFile : > MCBSPA, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + McbspbRegsFile : > MCBSPB, PAGE = 1 + +/*** Peripheral Frame 1 Register Structures ***/ + /* Записывает PAGE значением 1; данные PAGE. */ + ECanaRegsFile : > ECANA, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECanaLAMRegsFile : > ECANA_LAM PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECanaMboxesFile : > ECANA_MBOX PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECanaMOTSRegsFile : > ECANA_MOTS PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECanaMOTORegsFile : > ECANA_MOTO PAGE = 1 + + /* Записывает PAGE значением 1; данные PAGE. */ + ECanbRegsFile : > ECANB, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECanbLAMRegsFile : > ECANB_LAM PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECanbMboxesFile : > ECANB_MBOX PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECanbMOTSRegsFile : > ECANB_MOTS PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECanbMOTORegsFile : > ECANB_MOTO PAGE = 1 + + /* Записывает PAGE значением 1; данные PAGE. */ + EPwm1RegsFile : > EPWM1 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + EPwm2RegsFile : > EPWM2 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + EPwm3RegsFile : > EPWM3 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + EPwm4RegsFile : > EPWM4 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + EPwm5RegsFile : > EPWM5 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + EPwm6RegsFile : > EPWM6 PAGE = 1 + + /* Записывает PAGE значением 1; данные PAGE. */ + ECap1RegsFile : > ECAP1 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECap2RegsFile : > ECAP2 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECap3RegsFile : > ECAP3 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECap4RegsFile : > ECAP4 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECap5RegsFile : > ECAP5 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ECap6RegsFile : > ECAP6 PAGE = 1 + + /* Записывает PAGE значением 1; данные PAGE. */ + EQep1RegsFile : > EQEP1 PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + EQep2RegsFile : > EQEP2 PAGE = 1 + + /* Записывает PAGE значением 1; данные PAGE. */ + GpioCtrlRegsFile : > GPIOCTRL PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + GpioDataRegsFile : > GPIODAT PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + GpioIntRegsFile : > GPIOINT PAGE = 1 + +/*** Peripheral Frame 2 Register Structures ***/ + /* Записывает PAGE значением 1; данные PAGE. */ + SysCtrlRegsFile : > SYSTEM, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + SpiaRegsFile : > SPIA, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + SciaRegsFile : > SCIA, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + XIntruptRegsFile : > XINTRUPT, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + AdcRegsFile : > ADC, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ScibRegsFile : > SCIB, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + ScicRegsFile : > SCIC, PAGE = 1 + /* Записывает PAGE значением 1; данные PAGE. */ + I2caRegsFile : > I2CA, PAGE = 1 + +/*** Code Security Module Register Structures ***/ + /* Записывает PAGE значением 1; данные PAGE. */ + CsmPwlFile : > CSM_PWL, PAGE = 1 + +/*** Device Part ID Register Structures ***/ + /* Записывает PAGE значением 1; данные PAGE. */ + PartIdRegsFile : > PARTID, PAGE = 1 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + + +/* +//=========================================================================== +// End of file. +//=========================================================================== +*/ diff --git a/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_DefaultIsr.h b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_DefaultIsr.h new file mode 100644 index 0000000..648872d --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_DefaultIsr.h @@ -0,0 +1,236 @@ +/* Поставляемое TI описание DefaultIsr для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/1 $ +// Checkin $Date: August 18, 2006 13:45:37 $ +//########################################################################### +// +// FILE: DSP2833x_DefaultIsr.h +// +// TITLE: DSP2833x Devices Default Interrupt Service Routines Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_DEFAULT_ISR_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_DEFAULT_ISR_H +/* Определяет защитный символ или переключатель DSP2833x_DEFAULT_ISR_H для последующей компиляции. */ +#define DSP2833x_DEFAULT_ISR_H + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +//--------------------------------------------------------------------------- +// Default Interrupt Service Routine Declarations: +// +// The following function prototypes are for the +// default ISR routines used with the default PIE vector table. +// This default vector table is found in the DSP2833x_PieVect.h +// file. +// + +// Non-Peripheral Interrupts: +/* Объявляет обработчик INT13_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void INT13_ISR(void); // XINT13 or CPU-Timer 1 +/* Объявляет обработчик INT14_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void INT14_ISR(void); // CPU-Timer2 +/* Объявляет обработчик DATALOG_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void DATALOG_ISR(void); // Datalogging interrupt +/* Объявляет обработчик RTOSINT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void RTOSINT_ISR(void); // RTOS interrupt +/* Объявляет обработчик EMUINT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EMUINT_ISR(void); // Emulation interrupt +/* Объявляет обработчик NMI_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void NMI_ISR(void); // Non-maskable interrupt +/* Объявляет обработчик ILLEGAL_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ILLEGAL_ISR(void); // Illegal operation TRAP +/* Объявляет обработчик USER1_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER1_ISR(void); // User Defined trap 1 +/* Объявляет обработчик USER2_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER2_ISR(void); // User Defined trap 2 +/* Объявляет обработчик USER3_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER3_ISR(void); // User Defined trap 3 +/* Объявляет обработчик USER4_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER4_ISR(void); // User Defined trap 4 +/* Объявляет обработчик USER5_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER5_ISR(void); // User Defined trap 5 +/* Объявляет обработчик USER6_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER6_ISR(void); // User Defined trap 6 +/* Объявляет обработчик USER7_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER7_ISR(void); // User Defined trap 7 +/* Объявляет обработчик USER8_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER8_ISR(void); // User Defined trap 8 +/* Объявляет обработчик USER9_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER9_ISR(void); // User Defined trap 9 +/* Объявляет обработчик USER10_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER10_ISR(void); // User Defined trap 10 +/* Объявляет обработчик USER11_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER11_ISR(void); // User Defined trap 11 +/* Объявляет обработчик USER12_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void USER12_ISR(void); // User Defined trap 12 + +// Group 1 PIE Interrupt Service Routines: +/* Объявляет обработчик SEQ1INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void SEQ1INT_ISR(void); // ADC Sequencer 1 ISR +/* Объявляет обработчик SEQ2INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void SEQ2INT_ISR(void); // ADC Sequencer 2 ISR +/* Объявляет обработчик XINT1_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void XINT1_ISR(void); // External interrupt 1 +/* Объявляет обработчик XINT2_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void XINT2_ISR(void); // External interrupt 2 +/* Объявляет обработчик ADCINT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ADCINT_ISR(void); // ADC +/* Объявляет обработчик TINT0_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void TINT0_ISR(void); // Timer 0 +/* Объявляет обработчик WAKEINT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void WAKEINT_ISR(void); // WD + +// Group 2 PIE Interrupt Service Routines: +/* Объявляет обработчик EPWM1_TZINT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM1_TZINT_ISR(void); // EPWM-1 +/* Объявляет обработчик EPWM2_TZINT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM2_TZINT_ISR(void); // EPWM-2 +/* Объявляет обработчик EPWM3_TZINT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM3_TZINT_ISR(void); // EPWM-3 +/* Объявляет обработчик EPWM4_TZINT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM4_TZINT_ISR(void); // EPWM-4 +/* Объявляет обработчик EPWM5_TZINT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM5_TZINT_ISR(void); // EPWM-5 +/* Объявляет обработчик EPWM6_TZINT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM6_TZINT_ISR(void); // EPWM-6 + +// Group 3 PIE Interrupt Service Routines: +/* Объявляет обработчик EPWM1_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM1_INT_ISR(void); // EPWM-1 +/* Объявляет обработчик EPWM2_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM2_INT_ISR(void); // EPWM-2 +/* Объявляет обработчик EPWM3_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM3_INT_ISR(void); // EPWM-3 +/* Объявляет обработчик EPWM4_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM4_INT_ISR(void); // EPWM-4 +/* Объявляет обработчик EPWM5_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM5_INT_ISR(void); // EPWM-5 +/* Объявляет обработчик EPWM6_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EPWM6_INT_ISR(void); // EPWM-6 + +// Group 4 PIE Interrupt Service Routines: +/* Объявляет обработчик ECAP1_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ECAP1_INT_ISR(void); // ECAP-1 +/* Объявляет обработчик ECAP2_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ECAP2_INT_ISR(void); // ECAP-2 +/* Объявляет обработчик ECAP3_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ECAP3_INT_ISR(void); // ECAP-3 +/* Объявляет обработчик ECAP4_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ECAP4_INT_ISR(void); // ECAP-4 +/* Объявляет обработчик ECAP5_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ECAP5_INT_ISR(void); // ECAP-5 +/* Объявляет обработчик ECAP6_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ECAP6_INT_ISR(void); // ECAP-6 + +// Group 5 PIE Interrupt Service Routines: +/* Объявляет обработчик EQEP1_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EQEP1_INT_ISR(void); // EQEP-1 +/* Объявляет обработчик EQEP2_INT_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void EQEP2_INT_ISR(void); // EQEP-2 + +// Group 6 PIE Interrupt Service Routines: +/* Объявляет обработчик SPIRXINTA_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void SPIRXINTA_ISR(void); // SPI-A +/* Объявляет обработчик SPITXINTA_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void SPITXINTA_ISR(void); // SPI-A +/* Объявляет обработчик MRINTA_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void MRINTA_ISR(void); // McBSP-A +/* Объявляет обработчик MXINTA_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void MXINTA_ISR(void); // McBSP-A +/* Объявляет обработчик MRINTB_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void MRINTB_ISR(void); // McBSP-B +/* Объявляет обработчик MXINTB_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void MXINTB_ISR(void); // McBSP-B + +// Group 7 PIE Interrupt Service Routines: +/* Объявляет обработчик DINTCH1_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void DINTCH1_ISR(void); // DMA-Channel 1 +/* Объявляет обработчик DINTCH2_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void DINTCH2_ISR(void); // DMA-Channel 2 +/* Объявляет обработчик DINTCH3_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void DINTCH3_ISR(void); // DMA-Channel 3 +/* Объявляет обработчик DINTCH4_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void DINTCH4_ISR(void); // DMA-Channel 4 +/* Объявляет обработчик DINTCH5_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void DINTCH5_ISR(void); // DMA-Channel 5 +/* Объявляет обработчик DINTCH6_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void DINTCH6_ISR(void); // DMA-Channel 6 + +// Group 8 PIE Interrupt Service Routines: +/* Объявляет обработчик I2CINT1A_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void I2CINT1A_ISR(void); // I2C-A +/* Объявляет обработчик I2CINT2A_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void I2CINT2A_ISR(void); // I2C-A +/* Объявляет обработчик SCIRXINTC_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void SCIRXINTC_ISR(void); // SCI-C +/* Объявляет обработчик SCITXINTC_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void SCITXINTC_ISR(void); // SCI-C + +// Group 9 PIE Interrupt Service Routines: +/* Объявляет обработчик SCIRXINTA_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void SCIRXINTA_ISR(void); // SCI-A +/* Объявляет обработчик SCITXINTA_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void SCITXINTA_ISR(void); // SCI-A +/* Объявляет обработчик SCIRXINTB_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void SCIRXINTB_ISR(void); // SCI-B +/* Объявляет обработчик SCITXINTB_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void SCITXINTB_ISR(void); // SCI-B +/* Объявляет обработчик ECAN0INTA_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ECAN0INTA_ISR(void); // eCAN-A +/* Объявляет обработчик ECAN1INTA_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ECAN1INTA_ISR(void); // eCAN-A +/* Объявляет обработчик ECAN0INTB_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ECAN0INTB_ISR(void); // eCAN-B +/* Объявляет обработчик ECAN1INTB_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void ECAN1INTB_ISR(void); // eCAN-B + +// Group 10 PIE Interrupt Service Routines: + +// Group 11 PIE Interrupt Service Routines: + +// Group 12 PIE Interrupt Service Routines: +/* Объявляет обработчик XINT3_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void XINT3_ISR(void); // External interrupt 3 +/* Объявляет обработчик XINT4_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void XINT4_ISR(void); // External interrupt 4 +/* Объявляет обработчик XINT5_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void XINT5_ISR(void); // External interrupt 5 +/* Объявляет обработчик XINT6_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void XINT6_ISR(void); // External interrupt 6 +/* Объявляет обработчик XINT7_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void XINT7_ISR(void); // External interrupt 7 +/* Объявляет обработчик LVF_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void LVF_ISR(void); // Latched overflow flag +/* Объявляет обработчик LUF_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void LUF_ISR(void); // Latched underflow flag + +// Catch-all for Reserved Locations For testing purposes: +/* Объявляет интерфейс функции PIE_RESERVED; реализация вызывается через этот прототип. */ +interrupt void PIE_RESERVED(void); // Reserved for test +/* Объявляет обработчик rsvd_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void rsvd_ISR(void); // for test +/* Объявляет обработчик INT_NOTUSED_ISR; обслуживает источник прерывания и его аппаратные флаги. */ +interrupt void INT_NOTUSED_ISR(void); // for unused interrupts + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_DEFAULT_ISR_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_Dma_defines.h b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_Dma_defines.h new file mode 100644 index 0000000..a327969 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_Dma_defines.h @@ -0,0 +1,125 @@ +/* Поставляемое TI описание Dma_defines для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/2 $ +// Checkin $Date: August 14, 2007 16:32:29 $ +//########################################################################### +// +// FILE: DSP2833x_Dma_defines.h +// +// TITLE: #defines used in DMA examples +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_DMA_DEFINES_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_DMA_DEFINES_H +/* Определяет защитный символ или переключатель DSP2833x_DMA_DEFINES_H для последующей компиляции. */ +#define DSP2833x_DMA_DEFINES_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +// MODE +//========================== +// PERINTSEL bits +/* Задаёт DMA_SEQ1INT = 1; DMA 1 INT. */ +#define DMA_SEQ1INT 1 +/* Задаёт DMA_SEQ2INT = 2; DMA 2 INT. */ +#define DMA_SEQ2INT 2 +/* Задаёт DMA_XINT1 = 3; DMA 1. */ +#define DMA_XINT1 3 +/* Задаёт DMA_XINT2 = 4; DMA 2. */ +#define DMA_XINT2 4 +/* Задаёт DMA_XINT3 = 5; DMA 3. */ +#define DMA_XINT3 5 +/* Задаёт DMA_XINT4 = 6; DMA 4. */ +#define DMA_XINT4 6 +/* Задаёт DMA_XINT5 = 7; DMA 5. */ +#define DMA_XINT5 7 +/* Задаёт DMA_XINT6 = 8; DMA 6. */ +#define DMA_XINT6 8 +/* Задаёт DMA_XINT7 = 9; DMA 7. */ +#define DMA_XINT7 9 +/* Задаёт DMA_XINT13 = 10; DMA 13. */ +#define DMA_XINT13 10 +/* Задаёт DMA_TINT0 = 11; DMA 0. */ +#define DMA_TINT0 11 +/* Задаёт DMA_TINT1 = 12; DMA 1. */ +#define DMA_TINT1 12 +/* Задаёт DMA_TINT2 = 13; DMA 2. */ +#define DMA_TINT2 13 +/* Задаёт DMA_MXEVTA = 14; DMA MXEVTA. */ +#define DMA_MXEVTA 14 +/* Задаёт DMA_MREVTA = 15; DMA MREVTA. */ +#define DMA_MREVTA 15 +/* Задаёт DMA_MXREVTB = 16; DMA MXREVTB. */ +#define DMA_MXREVTB 16 +/* Задаёт DMA_MREVTB = 17; DMA MREVTB. */ +#define DMA_MREVTB 17 +// OVERINTE bit +/* Задаёт OVRFLOW_DISABLE = 0x0; OVRFLOW запрет. */ +#define OVRFLOW_DISABLE 0x0 +/* Задаёт OVEFLOW_ENABLE = 0x1; OVEFLOW разрешение. */ +#define OVEFLOW_ENABLE 0x1 +// PERINTE bit +/* Задаёт PERINT_DISABLE = 0x0; PERINT запрет. */ +#define PERINT_DISABLE 0x0 +/* Задаёт PERINT_ENABLE = 0x1; PERINT разрешение. */ +#define PERINT_ENABLE 0x1 +// CHINTMODE bits +/* Задаёт CHINT_BEGIN = 0x0; данные CHINT_BEGIN. */ +#define CHINT_BEGIN 0x0 +/* Задаёт CHINT_END = 0x1; данные CHINT_END. */ +#define CHINT_END 0x1 +// ONESHOT bits +/* Задаёт ONESHOT_DISABLE = 0x0; ONESHOT запрет. */ +#define ONESHOT_DISABLE 0x0 +/* Задаёт ONESHOT_ENABLE = 0x1; ONESHOT разрешение. */ +#define ONESHOT_ENABLE 0x1 +// CONTINOUS bit +/* Задаёт CONT_DISABLE = 0x0; CONT запрет. */ +#define CONT_DISABLE 0x0 +/* Задаёт CONT_ENABLE = 0x1; CONT разрешение. */ +#define CONT_ENABLE 0x1 +// SYNCE bit +/* Задаёт SYNC_DISABLE = 0x0; синхронизация запрет. */ +#define SYNC_DISABLE 0x0 +/* Задаёт SYNC_ENABLE = 0x1; синхронизация разрешение. */ +#define SYNC_ENABLE 0x1 +// SYNCSEL bit +/* Задаёт SYNC_SRC = 0x0; синхронизация SRC. */ +#define SYNC_SRC 0x0 +/* Задаёт SYNC_DST = 0x1; синхронизация DST. */ +#define SYNC_DST 0x1 +// DATASIZE bit +/* Задаёт SIXTEEN_BIT = 0x0; SIXTEEN бит. */ +#define SIXTEEN_BIT 0x0 +/* Задаёт THIRTYTWO_BIT = 0x1; THIRTYTWO бит. */ +#define THIRTYTWO_BIT 0x1 +// CHINTE bit +/* Задаёт CHINT_DISABLE = 0x0; CHINT запрет. */ +#define CHINT_DISABLE 0x0 +/* Задаёт CHINT_ENABLE = 0x1; CHINT разрешение. */ +#define CHINT_ENABLE 0x1 + + + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // - end of DSP2833x_EPWM_DEFINES_H + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_EPwm_defines.h b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_EPwm_defines.h new file mode 100644 index 0000000..0084f16 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_EPwm_defines.h @@ -0,0 +1,253 @@ +/* Поставляемое TI описание EPwm_defines для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/1 $ +// Checkin $Date: August 18, 2006 13:45:39 $ +//########################################################################### +// +// FILE: DSP2833x_EPwm_defines.h +// +// TITLE: #defines used in ePWM examples examples +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_EPWM_DEFINES_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_EPWM_DEFINES_H +/* Определяет защитный символ или переключатель DSP2833x_EPWM_DEFINES_H для последующей компиляции. */ +#define DSP2833x_EPWM_DEFINES_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +// TBCTL (Time-Base Control) +//========================== +// CTRMODE bits +/* Задаёт TB_COUNT_UP = 0x0; TB число UP. */ +#define TB_COUNT_UP 0x0 +/* Задаёт TB_COUNT_DOWN = 0x1; TB число DOWN. */ +#define TB_COUNT_DOWN 0x1 +/* Задаёт TB_COUNT_UPDOWN = 0x2; TB число UPDOWN. */ +#define TB_COUNT_UPDOWN 0x2 +/* Задаёт TB_FREEZE = 0x3; данные TB_FREEZE. */ +#define TB_FREEZE 0x3 +// PHSEN bit +/* Задаёт TB_DISABLE = 0x0; TB запрет. */ +#define TB_DISABLE 0x0 +/* Задаёт TB_ENABLE = 0x1; TB разрешение. */ +#define TB_ENABLE 0x1 +// PRDLD bit +/* Задаёт TB_SHADOW = 0x0; данные TB_SHADOW. */ +#define TB_SHADOW 0x0 +/* Задаёт TB_IMMEDIATE = 0x1; данные TB_IMMEDIATE. */ +#define TB_IMMEDIATE 0x1 +// SYNCOSEL bits +/* Задаёт TB_SYNC_IN = 0x0; TB синхронизация IN. */ +#define TB_SYNC_IN 0x0 +/* Задаёт TB_CTR_ZERO = 0x1; данные TB_CTR_ZERO. */ +#define TB_CTR_ZERO 0x1 +/* Задаёт TB_CTR_CMPB = 0x2; данные TB_CTR_CMPB. */ +#define TB_CTR_CMPB 0x2 +/* Задаёт TB_SYNC_DISABLE = 0x3; TB синхронизация запрет. */ +#define TB_SYNC_DISABLE 0x3 +// HSPCLKDIV and CLKDIV bits +/* Задаёт TB_DIV1 = 0x0; данные TB_DIV1. */ +#define TB_DIV1 0x0 +/* Задаёт TB_DIV2 = 0x1; данные TB_DIV2. */ +#define TB_DIV2 0x1 +/* Задаёт TB_DIV4 = 0x2; данные TB_DIV4. */ +#define TB_DIV4 0x2 +// PHSDIR bit +/* Задаёт TB_DOWN = 0x0; данные TB_DOWN. */ +#define TB_DOWN 0x0 +/* Задаёт TB_UP = 0x1; данные TB_UP. */ +#define TB_UP 0x1 + +// CMPCTL (Compare Control) +//========================== +// LOADAMODE and LOADBMODE bits +/* Задаёт CC_CTR_ZERO = 0x0; данные CC_CTR_ZERO. */ +#define CC_CTR_ZERO 0x0 +/* Задаёт CC_CTR_PRD = 0x1; данные CC_CTR_PRD. */ +#define CC_CTR_PRD 0x1 +/* Задаёт CC_CTR_ZERO_PRD = 0x2; данные CC_CTR_ZERO_PRD. */ +#define CC_CTR_ZERO_PRD 0x2 +/* Задаёт CC_LD_DISABLE = 0x3; CC LD запрет. */ +#define CC_LD_DISABLE 0x3 +// SHDWAMODE and SHDWBMODE bits +/* Задаёт CC_SHADOW = 0x0; данные CC_SHADOW. */ +#define CC_SHADOW 0x0 +/* Задаёт CC_IMMEDIATE = 0x1; данные CC_IMMEDIATE. */ +#define CC_IMMEDIATE 0x1 + +// AQCTLA and AQCTLB (Action Qualifier Control) +//============================================= +// ZRO, PRD, CAU, CAD, CBU, CBD bits +/* Задаёт AQ_NO_ACTION = 0x0; данные AQ_NO_ACTION. */ +#define AQ_NO_ACTION 0x0 +/* Задаёт AQ_CLEAR = 0x1; AQ очистка. */ +#define AQ_CLEAR 0x1 +/* Задаёт AQ_SET = 0x2; AQ установка. */ +#define AQ_SET 0x2 +/* Задаёт AQ_TOGGLE = 0x3; данные AQ_TOGGLE. */ +#define AQ_TOGGLE 0x3 + +// DBCTL (Dead-Band Control) +//========================== +// OUT MODE bits +/* Задаёт DB_DISABLE = 0x0; DB запрет. */ +#define DB_DISABLE 0x0 +/* Задаёт DBA_ENABLE = 0x1; DBA разрешение. */ +#define DBA_ENABLE 0x1 +/* Задаёт DBB_ENABLE = 0x2; DBB разрешение. */ +#define DBB_ENABLE 0x2 +/* Задаёт DB_FULL_ENABLE = 0x3; DB FULL разрешение. */ +#define DB_FULL_ENABLE 0x3 +// POLSEL bits +/* Задаёт DB_ACTV_HI = 0x0; данные DB_ACTV_HI. */ +#define DB_ACTV_HI 0x0 +/* Задаёт DB_ACTV_LOC = 0x1; данные DB_ACTV_LOC. */ +#define DB_ACTV_LOC 0x1 +/* Задаёт DB_ACTV_HIC = 0x2; данные DB_ACTV_HIC. */ +#define DB_ACTV_HIC 0x2 +/* Задаёт DB_ACTV_LO = 0x3; данные DB_ACTV_LO. */ +#define DB_ACTV_LO 0x3 +// IN MODE +/* Задаёт DBA_ALL = 0x0; данные DBA_ALL. */ +#define DBA_ALL 0x0 +/* Задаёт DBB_RED_DBA_FED = 0x1; данные DBB_RED_DBA_FED. */ +#define DBB_RED_DBA_FED 0x1 +/* Задаёт DBA_RED_DBB_FED = 0x2; данные DBA_RED_DBB_FED. */ +#define DBA_RED_DBB_FED 0x2 +/* Задаёт DBB_ALL = 0x3; данные DBB_ALL. */ +#define DBB_ALL 0x3 + +// CHPCTL (chopper control) +//========================== +// CHPEN bit +/* Задаёт CHP_DISABLE = 0x0; CHP запрет. */ +#define CHP_DISABLE 0x0 +/* Задаёт CHP_ENABLE = 0x1; CHP разрешение. */ +#define CHP_ENABLE 0x1 +// CHPFREQ bits +/* Задаёт CHP_DIV1 = 0x0; данные CHP_DIV1. */ +#define CHP_DIV1 0x0 +/* Задаёт CHP_DIV2 = 0x1; данные CHP_DIV2. */ +#define CHP_DIV2 0x1 +/* Задаёт CHP_DIV3 = 0x2; данные CHP_DIV3. */ +#define CHP_DIV3 0x2 +/* Задаёт CHP_DIV4 = 0x3; данные CHP_DIV4. */ +#define CHP_DIV4 0x3 +/* Задаёт CHP_DIV5 = 0x4; данные CHP_DIV5. */ +#define CHP_DIV5 0x4 +/* Задаёт CHP_DIV6 = 0x5; данные CHP_DIV6. */ +#define CHP_DIV6 0x5 +/* Задаёт CHP_DIV7 = 0x6; данные CHP_DIV7. */ +#define CHP_DIV7 0x6 +/* Задаёт CHP_DIV8 = 0x7; данные CHP_DIV8. */ +#define CHP_DIV8 0x7 +// CHPDUTY bits +/* Задаёт CHP1_8TH = 0x0; данные CHP1_8TH. */ +#define CHP1_8TH 0x0 +/* Задаёт CHP2_8TH = 0x1; данные CHP2_8TH. */ +#define CHP2_8TH 0x1 +/* Задаёт CHP3_8TH = 0x2; данные CHP3_8TH. */ +#define CHP3_8TH 0x2 +/* Задаёт CHP4_8TH = 0x3; данные CHP4_8TH. */ +#define CHP4_8TH 0x3 +/* Задаёт CHP5_8TH = 0x4; данные CHP5_8TH. */ +#define CHP5_8TH 0x4 +/* Задаёт CHP6_8TH = 0x5; данные CHP6_8TH. */ +#define CHP6_8TH 0x5 +/* Задаёт CHP7_8TH = 0x6; данные CHP7_8TH. */ +#define CHP7_8TH 0x6 + +// TZSEL (Trip Zone Select) +//========================== +// CBCn and OSHTn bits +/* Задаёт TZ_DISABLE = 0x0; TZ запрет. */ +#define TZ_DISABLE 0x0 +/* Задаёт TZ_ENABLE = 0x1; TZ разрешение. */ +#define TZ_ENABLE 0x1 + +// TZCTL (Trip Zone Control) +//========================== +// TZA and TZB bits +/* Задаёт TZ_HIZ = 0x0; данные TZ_HIZ. */ +#define TZ_HIZ 0x0 +/* Задаёт TZ_FORCE_HI = 0x1; TZ принудительная установка HI. */ +#define TZ_FORCE_HI 0x1 +/* Задаёт TZ_FORCE_LO = 0x2; TZ принудительная установка LO. */ +#define TZ_FORCE_LO 0x2 +/* Задаёт TZ_NO_CHANGE = 0x3; данные TZ_NO_CHANGE. */ +#define TZ_NO_CHANGE 0x3 + +// ETSEL (Event Trigger Select) +//============================= +/* Задаёт ET_CTR_ZERO = 0x1; данные ET_CTR_ZERO. */ +#define ET_CTR_ZERO 0x1 +/* Задаёт ET_CTR_PRD = 0x2; данные ET_CTR_PRD. */ +#define ET_CTR_PRD 0x2 +/* Задаёт ET_CTRU_CMPA = 0x4; данные ET_CTRU_CMPA. */ +#define ET_CTRU_CMPA 0x4 +/* Задаёт ET_CTRD_CMPA = 0x5; данные ET_CTRD_CMPA. */ +#define ET_CTRD_CMPA 0x5 +/* Задаёт ET_CTRU_CMPB = 0x6; данные ET_CTRU_CMPB. */ +#define ET_CTRU_CMPB 0x6 +/* Задаёт ET_CTRD_CMPB = 0x7; данные ET_CTRD_CMPB. */ +#define ET_CTRD_CMPB 0x7 + +// ETPS (Event Trigger Pre-scale) +//=============================== +// INTPRD, SOCAPRD, SOCBPRD bits +/* Задаёт ET_DISABLE = 0x0; ET запрет. */ +#define ET_DISABLE 0x0 +/* Задаёт ET_1ST = 0x1; данные ET_1ST. */ +#define ET_1ST 0x1 +/* Задаёт ET_2ND = 0x2; данные ET_2ND. */ +#define ET_2ND 0x2 +/* Задаёт ET_3RD = 0x3; данные ET_3RD. */ +#define ET_3RD 0x3 + + +//-------------------------------- +// HRPWM (High Resolution PWM) +//================================ +// HRCNFG +/* Задаёт HR_Disable = 0x0; HR запрет. */ +#define HR_Disable 0x0 +/* Задаёт HR_REP = 0x1; данные HR_REP. */ +#define HR_REP 0x1 +/* Задаёт HR_FEP = 0x2; данные HR_FEP. */ +#define HR_FEP 0x2 +/* Задаёт HR_BEP = 0x3; данные HR_BEP. */ +#define HR_BEP 0x3 + +/* Задаёт HR_CMP = 0x0; данные HR_CMP. */ +#define HR_CMP 0x0 +/* Задаёт HR_PHS = 0x1; данные HR_PHS. */ +#define HR_PHS 0x1 + +/* Задаёт HR_CTR_ZERO = 0x0; данные HR_CTR_ZERO. */ +#define HR_CTR_ZERO 0x0 +/* Задаёт HR_CTR_PRD = 0x1; данные HR_CTR_PRD. */ +#define HR_CTR_PRD 0x1 + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // - end of DSP2833x_EPWM_DEFINES_H + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_Examples.h b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_Examples.h new file mode 100644 index 0000000..eaa6500 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_Examples.h @@ -0,0 +1,176 @@ +/* Поставляемое TI описание Examples для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/9 $ +// Checkin $Date: July 2, 2008 14:31:12 $ +//########################################################################### +// +// FILE: DSP2833x_Examples.h +// +// TITLE: DSP2833x Device Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_EXAMPLES_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_EXAMPLES_H +/* Определяет защитный символ или переключатель DSP2833x_EXAMPLES_H для последующей компиляции. */ +#define DSP2833x_EXAMPLES_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +/*----------------------------------------------------------------------------- + Specify the PLL control register (PLLCR) and divide select (DIVSEL) value. +-----------------------------------------------------------------------------*/ +//#define DSP28_DIVSEL 0 // Enable /4 for SYSCLKOUT +//#define DSP28_DIVSEL 1 // Enable /4 for SYSCKOUT +/* Задаёт DSP28_DIVSEL = 2; данные DSP28_DIVSEL. */ +#define DSP28_DIVSEL 2 // Enable /2 for SYSCLKOUT +//#define DSP28_DIVSEL 3 // Enable /1 for SYSCLKOUT + +/* Задаёт DSP28_PLLCR = CLKMULT*2; данные DSP28_PLLCR. */ +#define DSP28_PLLCR CLKMULT*2 + +//#define DSP28_PLLCR 10 +//#define DSP28_PLLCR 9 +//#define DSP28_PLLCR 8 +//#define DSP28_PLLCR 7 +//#define DSP28_PLLCR 6 +//#define DSP28_PLLCR 5 +//#define DSP28_PLLCR 4 +//#define DSP28_PLLCR 3 +//#define DSP28_PLLCR 2 +//#define DSP28_PLLCR 1 +//#define DSP28_PLLCR 0 // PLL is bypassed in this mode +//---------------------------------------------------------------------------- + + +/*----------------------------------------------------------------------------- + Specify the clock rate of the CPU (SYSCLKOUT) in nS. + + Take into account the input clock frequency and the PLL multiplier + selected in step 1. + + Use one of the values provided, or define your own. + The trailing L is required tells the compiler to treat + the number as a 64-bit value. + + Only one statement should be uncommented. + + Example 1:150 MHz devices: + CLKIN is a 30MHz crystal. + + In step 1 the user specified PLLCR = 0xA for a + 150Mhz CPU clock (SYSCLKOUT = 150MHz). + + In this case, the CPU_RATE will be 6.667L + Uncomment the line: #define CPU_RATE 6.667L + + Example 2: 100 MHz devices: + CLKIN is a 20MHz crystal. + + In step 1 the user specified PLLCR = 0xA for a + 100Mhz CPU clock (SYSCLKOUT = 100MHz). + + In this case, the CPU_RATE will be 10.000L + Uncomment the line: #define CPU_RATE 10.000L +-----------------------------------------------------------------------------*/ +/* Задаёт CPU_RATE = 6.667L; данные CPU_RATE. */ +#define CPU_RATE 6.667L // for a 150MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 7.143L // for a 140MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 8.333L // for a 120MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 10.000L // for a 100MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 13.330L // for a 75MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 20.000L // for a 50MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 33.333L // for a 30MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 41.667L // for a 24MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 50.000L // for a 20MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 66.667L // for a 15MHz CPU clock speed (SYSCLKOUT) +//#define CPU_RATE 100.000L // for a 10MHz CPU clock speed (SYSCLKOUT) + +//---------------------------------------------------------------------------- + +/*----------------------------------------------------------------------------- + Target device (in DSP2833x_Device.h) determines CPU frequency + (for examples) - either 150 MHz (for 28335 and 28334) or 100 MHz + (for 28332). User does not have to change anything here. +-----------------------------------------------------------------------------*/ +/* Условие компиляции DSP28_28332: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_28332 // DSP28_28332 device only + /* Задаёт CPU_FRQ_100MHZ = 1; данные CPU_FRQ_100MHZ. */ + #define CPU_FRQ_100MHZ 1 // 100 Mhz CPU Freq (20 MHz input freq) + /* Задаёт CPU_FRQ_150MHZ = 0; данные CPU_FRQ_150MHZ. */ + #define CPU_FRQ_150MHZ 0 +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else + /* Задаёт CPU_FRQ_100MHZ = 0; данные CPU_FRQ_100MHZ. */ + #define CPU_FRQ_100MHZ 0 // DSP28_28335||DSP28_28334 + /* Задаёт CPU_FRQ_150MHZ = 1; данные CPU_FRQ_150MHZ. */ + #define CPU_FRQ_150MHZ 1 // 150 MHz CPU Freq (30 MHz input freq) by DEFAULT +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +//--------------------------------------------------------------------------- +// Include Example Header Files: +// + +/* Подключает "DSP2833x_GlobalPrototypes.h": поставляемое TI описание GlobalPrototypes для семейства C2833x. */ +#include "DSP2833x_GlobalPrototypes.h" // Prototypes for global functions within the + // .c files. + +/* Подключает "DSP2833x_ePwm_defines.h": поставляемое TI описание ePwm_defines для семейства C2833x. */ +#include "DSP2833x_ePwm_defines.h" // Macros used for PWM examples. +/* Подключает "DSP2833x_Dma_defines.h": поставляемое TI описание Dma_defines для семейства C2833x. */ +#include "DSP2833x_Dma_defines.h" // Macros used for DMA examples. +/* Подключает "DSP2833x_I2C_defines.h": поставляемое TI описание I2C_defines для семейства C2833x. */ +#include "DSP2833x_I2C_defines.h" // Macros used for I2C examples. + +/* Задаёт PARTNO_28335 = 0xEF; данные PARTNO_28335. */ +#define PARTNO_28335 0xEF +/* Задаёт PARTNO_28334 = 0xEE; данные PARTNO_28334. */ +#define PARTNO_28334 0xEE +/* Задаёт PARTNO_28332 = 0xED; данные PARTNO_28332. */ +#define PARTNO_28332 0xED +/* Задаёт PARTNO_28235 = 0xE8; данные PARTNO_28235. */ +#define PARTNO_28235 0xE8 +/* Задаёт PARTNO_28234 = 0xE7; данные PARTNO_28234. */ +#define PARTNO_28234 0xE7 +/* Задаёт PARTNO_28232 = 0xE6; данные PARTNO_28232. */ +#define PARTNO_28232 0xE6 + + +// Include files not used with DSP/BIOS +/* Начинает условие: DSP28_BIOS ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP28_BIOS +/* Подключает "DSP2833x_DefaultISR.h": поставляемое TI описание DefaultISR для семейства C2833x. */ +#include "DSP2833x_DefaultISR.h" +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +// DO NOT MODIFY THIS LINE. +/* Задаёт DELAY_US = DSP28x_usDelay(((((long double) A * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L); данные DELAY_US. */ +#define DELAY_US(A) DSP28x_usDelay(((((long double) A * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L) + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_EXAMPLES_H definition + + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_GlobalPrototypes.h b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_GlobalPrototypes.h new file mode 100644 index 0000000..4cd293d --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_GlobalPrototypes.h @@ -0,0 +1,363 @@ +/* Поставляемое TI описание GlobalPrototypes для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/11 $ +// Checkin $Date: May 12, 2008 14:30:08 $ +//########################################################################### +// +// FILE: DSP2833x_GlobalPrototypes.h +// +// TITLE: Global prototypes for DSP2833x Examples +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_GLOBALPROTOTYPES_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_GLOBALPROTOTYPES_H +/* Определяет защитный символ или переключатель DSP2833x_GLOBALPROTOTYPES_H для последующей компиляции. */ +#define DSP2833x_GLOBALPROTOTYPES_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/*---- shared global function prototypes -----------------------------------*/ +/* Объявляет интерфейс функции InitAdc; реализация вызывается через этот прототип. */ +extern void InitAdc(void); + +/* Объявляет интерфейс функции DMAInitialize; реализация вызывается через этот прототип. */ +extern void DMAInitialize(void); +// DMA Channel 1 +/* Объявляет интерфейс функции DMACH1AddrConfig; реализация вызывается через этот прототип. */ +extern void DMACH1AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source); +/* Объявляет интерфейс функции DMACH1BurstConfig; реализация вызывается через этот прототип. */ +extern void DMACH1BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep); +/* Объявляет интерфейс функции DMACH1TransferConfig; реализация вызывается через этот прототип. */ +extern void DMACH1TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep); +/* Объявляет интерфейс функции DMACH1WrapConfig; реализация вызывается через этот прототип. */ +extern void DMACH1WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep); +/* Объявляет интерфейс функции DMACH1ModeConfig; реализация вызывается через этот прототип. */ +extern void DMACH1ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte); +/* Объявляет интерфейс функции StartDMACH1; реализация вызывается через этот прототип. */ +extern void StartDMACH1(void); +// DMA Channel 2 +/* Объявляет интерфейс функции DMACH2AddrConfig; реализация вызывается через этот прототип. */ +extern void DMACH2AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source); +/* Объявляет интерфейс функции DMACH2BurstConfig; реализация вызывается через этот прототип. */ +extern void DMACH2BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep); +/* Объявляет интерфейс функции DMACH2TransferConfig; реализация вызывается через этот прототип. */ +extern void DMACH2TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep); +/* Объявляет интерфейс функции DMACH2WrapConfig; реализация вызывается через этот прототип. */ +extern void DMACH2WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep); +/* Объявляет интерфейс функции DMACH2ModeConfig; реализация вызывается через этот прототип. */ +extern void DMACH2ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte); +/* Объявляет интерфейс функции StartDMACH2; реализация вызывается через этот прототип. */ +extern void StartDMACH2(void); +// DMA Channel 3 +/* Объявляет интерфейс функции DMACH3AddrConfig; реализация вызывается через этот прототип. */ +extern void DMACH3AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source); +/* Объявляет интерфейс функции DMACH3BurstConfig; реализация вызывается через этот прототип. */ +extern void DMACH3BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep); +/* Объявляет интерфейс функции DMACH3TransferConfig; реализация вызывается через этот прототип. */ +extern void DMACH3TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep); +/* Объявляет интерфейс функции DMACH3WrapConfig; реализация вызывается через этот прототип. */ +extern void DMACH3WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep); +/* Объявляет интерфейс функции DMACH3ModeConfig; реализация вызывается через этот прототип. */ +extern void DMACH3ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte); +/* Объявляет интерфейс функции StartDMACH3; реализация вызывается через этот прототип. */ +extern void StartDMACH3(void); +// DMA Channel 4 +/* Объявляет интерфейс функции DMACH4AddrConfig; реализация вызывается через этот прототип. */ +extern void DMACH4AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source); +/* Объявляет интерфейс функции DMACH4BurstConfig; реализация вызывается через этот прототип. */ +extern void DMACH4BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep); +/* Объявляет интерфейс функции DMACH4TransferConfig; реализация вызывается через этот прототип. */ +extern void DMACH4TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep); +/* Объявляет интерфейс функции DMACH4WrapConfig; реализация вызывается через этот прототип. */ +extern void DMACH4WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep); +/* Объявляет интерфейс функции DMACH4ModeConfig; реализация вызывается через этот прототип. */ +extern void DMACH4ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte); +/* Объявляет интерфейс функции StartDMACH4; реализация вызывается через этот прототип. */ +extern void StartDMACH4(void); +// DMA Channel 5 +/* Объявляет интерфейс функции DMACH5AddrConfig; реализация вызывается через этот прототип. */ +extern void DMACH5AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source); +/* Объявляет интерфейс функции DMACH5BurstConfig; реализация вызывается через этот прототип. */ +extern void DMACH5BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep); +/* Объявляет интерфейс функции DMACH5TransferConfig; реализация вызывается через этот прототип. */ +extern void DMACH5TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep); +/* Объявляет интерфейс функции DMACH5WrapConfig; реализация вызывается через этот прототип. */ +extern void DMACH5WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep); +/* Объявляет интерфейс функции DMACH5ModeConfig; реализация вызывается через этот прототип. */ +extern void DMACH5ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte); +/* Объявляет интерфейс функции StartDMACH5; реализация вызывается через этот прототип. */ +extern void StartDMACH5(void); +// DMA Channel 6 +/* Объявляет интерфейс функции DMACH6AddrConfig; реализация вызывается через этот прототип. */ +extern void DMACH6AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source); +/* Объявляет интерфейс функции DMACH6BurstConfig; реализация вызывается через этот прототип. */ +extern void DMACH6BurstConfig(Uint16 bsize,Uint16 srcbstep, int16 desbstep); +/* Объявляет интерфейс функции DMACH6TransferConfig; реализация вызывается через этот прототип. */ +extern void DMACH6TransferConfig(Uint16 tsize, int16 srctstep, int16 deststep); +/* Объявляет интерфейс функции DMACH6WrapConfig; реализация вызывается через этот прототип. */ +extern void DMACH6WrapConfig(Uint16 srcwsize, int16 srcwstep, Uint16 deswsize, int16 deswstep); +/* Объявляет интерфейс функции DMACH6ModeConfig; реализация вызывается через этот прототип. */ +extern void DMACH6ModeConfig(Uint16 persel, Uint16 perinte, Uint16 oneshot, Uint16 cont, Uint16 synce, Uint16 syncsel, Uint16 ovrinte, Uint16 datasize, Uint16 chintmode, Uint16 chinte); +/* Объявляет интерфейс функции StartDMACH6; реализация вызывается через этот прототип. */ +extern void StartDMACH6(void); + +/* Объявляет интерфейс функции InitPeripherals; реализация вызывается через этот прототип. */ +extern void InitPeripherals(void); +/* Условие компиляции DSP28_ECANA: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_ECANA +/* Объявляет интерфейс функции InitECan; реализация вызывается через этот прототип. */ +extern void InitECan(void); +/* Объявляет интерфейс функции InitECana; реализация вызывается через этот прототип. */ +extern void InitECana(void); +/* Объявляет интерфейс функции InitECanGpio; реализация вызывается через этот прототип. */ +extern void InitECanGpio(void); +/* Объявляет интерфейс функции InitECanaGpio; реализация вызывается через этот прототип. */ +extern void InitECanaGpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_ECANA +/* Условие компиляции DSP28_ECANB: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_ECANB +/* Объявляет интерфейс функции InitECanb; реализация вызывается через этот прототип. */ +extern void InitECanb(void); +/* Объявляет интерфейс функции InitECanbGpio; реализация вызывается через этот прототип. */ +extern void InitECanbGpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_ECANB +/* Объявляет интерфейс функции InitECap; реализация вызывается через этот прототип. */ +extern void InitECap(void); +/* Объявляет интерфейс функции InitECapGpio; реализация вызывается через этот прототип. */ +extern void InitECapGpio(void); +/* Объявляет интерфейс функции InitECap1Gpio; реализация вызывается через этот прототип. */ +extern void InitECap1Gpio(void); +/* Объявляет интерфейс функции InitECap2Gpio; реализация вызывается через этот прототип. */ +extern void InitECap2Gpio(void); +/* Условие компиляции DSP28_ECAP3: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_ECAP3 +/* Объявляет интерфейс функции InitECap3Gpio; реализация вызывается через этот прототип. */ +extern void InitECap3Gpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_ECAP3 +/* Условие компиляции DSP28_ECAP4: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_ECAP4 +/* Объявляет интерфейс функции InitECap4Gpio; реализация вызывается через этот прототип. */ +extern void InitECap4Gpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_ECAP4 +/* Условие компиляции DSP28_ECAP5: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_ECAP5 +/* Объявляет интерфейс функции InitECap5Gpio; реализация вызывается через этот прототип. */ +extern void InitECap5Gpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_ECAP5 +/* Условие компиляции DSP28_ECAP6: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_ECAP6 +/* Объявляет интерфейс функции InitECap6Gpio; реализация вызывается через этот прототип. */ +extern void InitECap6Gpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_ECAP6 +/* Объявляет интерфейс функции InitEPwm; реализация вызывается через этот прототип. */ +extern void InitEPwm(void); +/* Объявляет интерфейс функции InitEPwmGpio; реализация вызывается через этот прототип. */ +extern void InitEPwmGpio(void); +/* Объявляет интерфейс функции InitEPwm1Gpio; реализация вызывается через этот прототип. */ +extern void InitEPwm1Gpio(void); +/* Объявляет интерфейс функции InitEPwm2Gpio; реализация вызывается через этот прототип. */ +extern void InitEPwm2Gpio(void); +/* Объявляет интерфейс функции InitEPwm3Gpio; реализация вызывается через этот прототип. */ +extern void InitEPwm3Gpio(void); +/* Условие компиляции DSP28_EPWM4: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_EPWM4 +/* Объявляет интерфейс функции InitEPwm4Gpio; реализация вызывается через этот прототип. */ +extern void InitEPwm4Gpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_EPWM4 +/* Условие компиляции DSP28_EPWM5: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_EPWM5 +/* Объявляет интерфейс функции InitEPwm5Gpio; реализация вызывается через этот прототип. */ +extern void InitEPwm5Gpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_EPWM5 +/* Условие компиляции DSP28_EPWM6: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_EPWM6 +/* Объявляет интерфейс функции InitEPwm6Gpio; реализация вызывается через этот прототип. */ +extern void InitEPwm6Gpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_EPWM6 +/* Условие компиляции DSP28_EQEP1: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_EQEP1 +/* Объявляет интерфейс функции InitEQep; реализация вызывается через этот прототип. */ +extern void InitEQep(void); +/* Объявляет интерфейс функции InitEQepGpio; реализация вызывается через этот прототип. */ +extern void InitEQepGpio(void); +/* Объявляет интерфейс функции InitEQep1Gpio; реализация вызывается через этот прототип. */ +extern void InitEQep1Gpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // if DSP28_EQEP1 +/* Условие компиляции DSP28_EQEP2: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_EQEP2 +/* Объявляет интерфейс функции InitEQep2Gpio; реализация вызывается через этот прототип. */ +extern void InitEQep2Gpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_EQEP2 +/* Объявляет интерфейс функции InitGpio; реализация вызывается через этот прототип. */ +extern void InitGpio(void); +/* Объявляет интерфейс функции InitI2CGpio; реализация вызывается через этот прототип. */ +extern void InitI2CGpio(void); + +/* Объявляет интерфейс функции InitMcbsp; реализация вызывается через этот прототип. */ +extern void InitMcbsp(void); +/* Объявляет интерфейс функции InitMcbspa; реализация вызывается через этот прототип. */ +extern void InitMcbspa(void); +/* Объявляет интерфейс функции delay_loop; реализация вызывается через этот прототип. */ +extern void delay_loop(void); +/* Объявляет интерфейс функции InitMcbspaGpio; реализация вызывается через этот прототип. */ +extern void InitMcbspaGpio(void); +/* Объявляет интерфейс функции InitMcbspa8bit; реализация вызывается через этот прототип. */ +extern void InitMcbspa8bit(void); +/* Объявляет интерфейс функции InitMcbspa12bit; реализация вызывается через этот прототип. */ +extern void InitMcbspa12bit(void); +/* Объявляет интерфейс функции InitMcbspa16bit; реализация вызывается через этот прототип. */ +extern void InitMcbspa16bit(void); +/* Объявляет интерфейс функции InitMcbspa20bit; реализация вызывается через этот прототип. */ +extern void InitMcbspa20bit(void); +/* Объявляет интерфейс функции InitMcbspa24bit; реализация вызывается через этот прототип. */ +extern void InitMcbspa24bit(void); +/* Объявляет интерфейс функции InitMcbspa32bit; реализация вызывается через этот прототип. */ +extern void InitMcbspa32bit(void); +/* Условие компиляции DSP28_MCBSPB: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_MCBSPB +/* Объявляет интерфейс функции InitMcbspb; реализация вызывается через этот прототип. */ +extern void InitMcbspb(void); +/* Объявляет интерфейс функции InitMcbspbGpio; реализация вызывается через этот прототип. */ +extern void InitMcbspbGpio(void); +/* Объявляет интерфейс функции InitMcbspb8bit; реализация вызывается через этот прототип. */ +extern void InitMcbspb8bit(void); +/* Объявляет интерфейс функции InitMcbspb12bit; реализация вызывается через этот прототип. */ +extern void InitMcbspb12bit(void); +/* Объявляет интерфейс функции InitMcbspb16bit; реализация вызывается через этот прототип. */ +extern void InitMcbspb16bit(void); +/* Объявляет интерфейс функции InitMcbspb20bit; реализация вызывается через этот прототип. */ +extern void InitMcbspb20bit(void); +/* Объявляет интерфейс функции InitMcbspb24bit; реализация вызывается через этот прототип. */ +extern void InitMcbspb24bit(void); +/* Объявляет интерфейс функции InitMcbspb32bit; реализация вызывается через этот прототип. */ +extern void InitMcbspb32bit(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_MCBSPB + +/* Объявляет интерфейс функции InitPieCtrl; реализация вызывается через этот прототип. */ +extern void InitPieCtrl(void); +/* Объявляет интерфейс функции InitPieVectTable; реализация вызывается через этот прототип. */ +extern void InitPieVectTable(void); + +/* Объявляет интерфейс функции InitSci; реализация вызывается через этот прототип. */ +extern void InitSci(void); +/* Объявляет интерфейс функции InitSciGpio; реализация вызывается через этот прототип. */ +extern void InitSciGpio(void); +/* Объявляет интерфейс функции InitSciaGpio; реализация вызывается через этот прототип. */ +extern void InitSciaGpio(void); +/* Условие компиляции DSP28_SCIB: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_SCIB +/* Объявляет интерфейс функции InitScibGpio; реализация вызывается через этот прототип. */ +extern void InitScibGpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // endif DSP28_SCIB +/* Условие компиляции DSP28_SCIC: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_SCIC +/* Объявляет интерфейс функции InitScicGpio; реализация вызывается через этот прототип. */ +extern void InitScicGpio(void); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Объявляет интерфейс функции InitSpi; реализация вызывается через этот прототип. */ +extern void InitSpi(void); +/* Объявляет интерфейс функции InitSpiGpio; реализация вызывается через этот прототип. */ +extern void InitSpiGpio(void); +/* Объявляет интерфейс функции InitSpiaGpio; реализация вызывается через этот прототип. */ +extern void InitSpiaGpio(void); +/* Объявляет интерфейс функции InitSysCtrl; реализация вызывается через этот прототип. */ +extern void InitSysCtrl(void); +/* Объявляет интерфейс функции InitTzGpio; реализация вызывается через этот прототип. */ +extern void InitTzGpio(void); +/* Объявляет интерфейс функции InitXIntrupt; реализация вызывается через этот прототип. */ +extern void InitXIntrupt(void); +/* Объявляет интерфейс функции XintfInit; реализация вызывается через этот прототип. */ +extern void XintfInit(void); +/* Объявляет интерфейс функции InitXintf16Gpio; реализация вызывается через этот прототип. */ +extern void InitXintf16Gpio(); +/* Объявляет интерфейс функции InitXintf32Gpio; реализация вызывается через этот прототип. */ +extern void InitXintf32Gpio(); +/* Объявляет интерфейс функции InitPll; реализация вызывается через этот прототип. */ +extern void InitPll(Uint16 pllcr, Uint16 clkindiv); +/* Объявляет интерфейс функции InitPeripheralClocks; реализация вызывается через этот прототип. */ +extern void InitPeripheralClocks(void); +/* Объявляет интерфейс функции EnableInterrupts; реализация вызывается через этот прототип. */ +extern void EnableInterrupts(void); +/* Объявляет интерфейс функции DSP28x_usDelay; реализация вызывается через этот прототип. */ +extern void DSP28x_usDelay(Uint32 Count); +/* Объявляет интерфейс функции ADC_cal; реализация вызывается через этот прототип. */ +extern void ADC_cal (void); +/* Задаёт KickDog = ServiceDog; данные KickDog. */ +#define KickDog ServiceDog // For compatiblity with previous versions +/* Объявляет интерфейс функции ServiceDog; реализация вызывается через этот прототип. */ +extern void ServiceDog(void); +/* Объявляет интерфейс функции DisableDog; реализация вызывается через этот прототип. */ +extern void DisableDog(void); +/* Объявляет интерфейс функции CsmUnlock; реализация вызывается через этот прототип. */ +extern Uint16 CsmUnlock(void); + +// DSP28_DBGIER.asm +/* Объявляет интерфейс функции SetDBGIER; реализация вызывается через этот прототип. */ +extern void SetDBGIER(Uint16 dbgier); + +// CAUTION +// This function MUST be executed out of RAM. Executing it +// out of OTP/Flash will yield unpredictable results +/* Объявляет интерфейс функции InitFlash; реализация вызывается через этот прототип. */ +extern void InitFlash(void); + + +/* Объявляет интерфейс функции MemCopy; реализация вызывается через этот прототип. */ +void MemCopy(Uint16 *SourceAddr, Uint16* SourceEndAddr, Uint16* DestAddr); + + +//--------------------------------------------------------------------------- +// External symbols created by the linker cmd file +// DSP28 examples will use these to relocate code from one LOAD location +// in either Flash or XINTF to a different RUN location in internal +// RAM +/* Объявляет RamfuncsLoadStart — данные RamfuncsLoadStart. Память определена в другом модуле. */ +extern Uint16 RamfuncsLoadStart; +/* Объявляет RamfuncsLoadEnd — данные RamfuncsLoadEnd. Память определена в другом модуле. */ +extern Uint16 RamfuncsLoadEnd; +/* Объявляет RamfuncsRunStart — данные RamfuncsRunStart. Память определена в другом модуле. */ +extern Uint16 RamfuncsRunStart; + +/* Объявляет XintffuncsLoadStart — данные XintffuncsLoadStart. Память определена в другом модуле. */ +extern Uint16 XintffuncsLoadStart; +/* Объявляет XintffuncsLoadEnd — данные XintffuncsLoadEnd. Память определена в другом модуле. */ +extern Uint16 XintffuncsLoadEnd; +/* Объявляет XintffuncsRunStart — данные XintffuncsRunStart. Память определена в другом модуле. */ +extern Uint16 XintffuncsRunStart; + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // - end of DSP2833x_GLOBALPROTOTYPES_H + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_I2c_defines.h b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_I2c_defines.h new file mode 100644 index 0000000..6dfd58d --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_I2c_defines.h @@ -0,0 +1,176 @@ +/* Поставляемое TI описание I2c_defines для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 16, 2008 17:16:47 $ +//########################################################################### +// +// FILE: DSP2833x_I2cExample.h +// +// TITLE: 2833x I2C Example Code Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_I2C_DEFINES_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_I2C_DEFINES_H +/* Определяет защитный символ или переключатель DSP2833x_I2C_DEFINES_H для последующей компиляции. */ +#define DSP2833x_I2C_DEFINES_H + +//-------------------------------------------- +// Defines +//-------------------------------------------- + +// Error Messages +/* Задаёт I2C_ERROR = 0xFFFF; 2 C ошибка. */ +#define I2C_ERROR 0xFFFF +/* Задаёт I2C_ARB_LOST_ERROR = 0x0001; 2 C ARB LOST ошибка. */ +#define I2C_ARB_LOST_ERROR 0x0001 +/* Задаёт I2C_NACK_ERROR = 0x0002; 2 C NACK ошибка. */ +#define I2C_NACK_ERROR 0x0002 +/* Задаёт I2C_BUS_BUSY_ERROR = 0x1000; 2 C BUS BUSY ошибка. */ +#define I2C_BUS_BUSY_ERROR 0x1000 +/* Задаёт I2C_STP_NOT_READY_ERROR = 0x5555; 2 C STP NOT READY ошибка. */ +#define I2C_STP_NOT_READY_ERROR 0x5555 +/* Задаёт I2C_NO_FLAGS = 0xAAAA; 2 C NO флаги. */ +#define I2C_NO_FLAGS 0xAAAA +/* Задаёт I2C_SUCCESS = 0x0000; данные I2C_SUCCESS. */ +#define I2C_SUCCESS 0x0000 + +// Clear Status Flags +/* Задаёт I2C_CLR_AL_BIT = 0x0001; 2 C CLR AL бит. */ +#define I2C_CLR_AL_BIT 0x0001 +/* Задаёт I2C_CLR_NACK_BIT = 0x0002; 2 C CLR NACK бит. */ +#define I2C_CLR_NACK_BIT 0x0002 +/* Задаёт I2C_CLR_ARDY_BIT = 0x0004; 2 C CLR ARDY бит. */ +#define I2C_CLR_ARDY_BIT 0x0004 +/* Задаёт I2C_CLR_RRDY_BIT = 0x0008; 2 C CLR RRDY бит. */ +#define I2C_CLR_RRDY_BIT 0x0008 +/* Задаёт I2C_CLR_SCD_BIT = 0x0020; 2 C CLR SCD бит. */ +#define I2C_CLR_SCD_BIT 0x0020 + +// Interrupt Source Messages +/* Задаёт I2C_NO_ISRC = 0x0000; данные I2C_NO_ISRC. */ +#define I2C_NO_ISRC 0x0000 +/* Задаёт I2C_ARB_ISRC = 0x0001; данные I2C_ARB_ISRC. */ +#define I2C_ARB_ISRC 0x0001 +/* Задаёт I2C_NACK_ISRC = 0x0002; данные I2C_NACK_ISRC. */ +#define I2C_NACK_ISRC 0x0002 +/* Задаёт I2C_ARDY_ISRC = 0x0003; данные I2C_ARDY_ISRC. */ +#define I2C_ARDY_ISRC 0x0003 +/* Задаёт I2C_RX_ISRC = 0x0004; данные I2C_RX_ISRC. */ +#define I2C_RX_ISRC 0x0004 +/* Задаёт I2C_TX_ISRC = 0x0005; данные I2C_TX_ISRC. */ +#define I2C_TX_ISRC 0x0005 +/* Задаёт I2C_SCD_ISRC = 0x0006; данные I2C_SCD_ISRC. */ +#define I2C_SCD_ISRC 0x0006 +/* Задаёт I2C_AAS_ISRC = 0x0007; данные I2C_AAS_ISRC. */ +#define I2C_AAS_ISRC 0x0007 + +// I2CMSG structure defines +/* Задаёт I2C_NO_STOP = 0; данные I2C_NO_STOP. */ +#define I2C_NO_STOP 0 +/* Задаёт I2C_YES_STOP = 1; данные I2C_YES_STOP. */ +#define I2C_YES_STOP 1 +/* Задаёт I2C_RECEIVE = 0; 2 C приём. */ +#define I2C_RECEIVE 0 +/* Задаёт I2C_TRANSMIT = 1; 2 C передача. */ +#define I2C_TRANSMIT 1 +/* Задаёт I2C_MAX_BUFFER_SIZE = 16; 2 C MAX буфер размер. */ +#define I2C_MAX_BUFFER_SIZE 16 + +// I2C Slave State defines +/* Задаёт I2C_NOTSLAVE = 0; данные I2C_NOTSLAVE. */ +#define I2C_NOTSLAVE 0 +/* Задаёт I2C_ADDR_AS_SLAVE = 1; данные I2C_ADDR_AS_SLAVE. */ +#define I2C_ADDR_AS_SLAVE 1 +/* Задаёт I2C_ST_MSG_READY = 2; данные I2C_ST_MSG_READY. */ +#define I2C_ST_MSG_READY 2 + +// I2C Slave Receiver messages defines +/* Задаёт I2C_SND_MSG1 = 1; данные I2C_SND_MSG1. */ +#define I2C_SND_MSG1 1 +/* Задаёт I2C_SND_MSG2 = 2; данные I2C_SND_MSG2. */ +#define I2C_SND_MSG2 2 + +// I2C State defines +/* Задаёт I2C_IDLE = 0; данные I2C_IDLE. */ +#define I2C_IDLE 0 +/* Задаёт I2C_SLAVE_RECEIVER = 1; данные I2C_SLAVE_RECEIVER. */ +#define I2C_SLAVE_RECEIVER 1 +/* Задаёт I2C_SLAVE_TRANSMITTER = 2; данные I2C_SLAVE_TRANSMITTER. */ +#define I2C_SLAVE_TRANSMITTER 2 +/* Задаёт I2C_MASTER_RECEIVER = 3; данные I2C_MASTER_RECEIVER. */ +#define I2C_MASTER_RECEIVER 3 +/* Задаёт I2C_MASTER_TRANSMITTER = 4; данные I2C_MASTER_TRANSMITTER. */ +#define I2C_MASTER_TRANSMITTER 4 + +// I2C Message Commands for I2CMSG struct +/* Задаёт I2C_MSGSTAT_INACTIVE = 0x0000; данные I2C_MSGSTAT_INACTIVE. */ +#define I2C_MSGSTAT_INACTIVE 0x0000 +/* Задаёт I2C_MSGSTAT_SEND_WITHSTOP = 0x0010; данные I2C_MSGSTAT_SEND_WITHSTOP. */ +#define I2C_MSGSTAT_SEND_WITHSTOP 0x0010 +/* Задаёт I2C_MSGSTAT_WRITE_BUSY = 0x0011; 2 C MSGSTAT запись BUSY. */ +#define I2C_MSGSTAT_WRITE_BUSY 0x0011 +/* Задаёт I2C_MSGSTAT_SEND_NOSTOP = 0x0020; данные I2C_MSGSTAT_SEND_NOSTOP. */ +#define I2C_MSGSTAT_SEND_NOSTOP 0x0020 +/* Задаёт I2C_MSGSTAT_SEND_NOSTOP_BUSY = 0x0021; данные I2C_MSGSTAT_SEND_NOSTOP_BUSY. */ +#define I2C_MSGSTAT_SEND_NOSTOP_BUSY 0x0021 +/* Задаёт I2C_MSGSTAT_RESTART = 0x0022; данные I2C_MSGSTAT_RESTART. */ +#define I2C_MSGSTAT_RESTART 0x0022 +/* Задаёт I2C_MSGSTAT_READ_BUSY = 0x0023; 2 C MSGSTAT чтение BUSY. */ +#define I2C_MSGSTAT_READ_BUSY 0x0023 + +// Generic defines +/* Задаёт I2C_TRUE = 1; данные I2C_TRUE. */ +#define I2C_TRUE 1 +/* Задаёт I2C_FALSE = 0; данные I2C_FALSE. */ +#define I2C_FALSE 0 +/* Задаёт I2C_YES = 1; данные I2C_YES. */ +#define I2C_YES 1 +/* Задаёт I2C_NO = 0; данные I2C_NO. */ +#define I2C_NO 0 +/* Задаёт I2C_DUMMY_BYTE = 0; данные I2C_DUMMY_BYTE. */ +#define I2C_DUMMY_BYTE 0 + + +//-------------------------------------------- +// Structures +//-------------------------------------------- + +// I2C Message Structure +/* Описывает структуру I2CMSG; порядок полей определяет расположение данных. */ +struct I2CMSG { + /* Объявляет MsgStatus — Msg состояние. */ + Uint16 MsgStatus; // Word stating what state msg is in: + // I2C_MSGCMD_INACTIVE = do not send msg + // I2C_MSGCMD_BUSY = msg start has been sent, + // awaiting stop + // I2C_MSGCMD_SEND_WITHSTOP = command to send + // master trans msg complete with a stop bit + // I2C_MSGCMD_SEND_NOSTOP = command to send + // master trans msg without the stop bit + // I2C_MSGCMD_RESTART = command to send a restart + // as a master receiver with a stop bit + /* Объявляет SlaveAddress — Slave адрес. */ + Uint16 SlaveAddress; // I2C address of slave msg is intended for + /* Объявляет NumOfBytes — данные NumOfBytes. */ + Uint16 NumOfBytes; // Num of valid bytes in (or to be put in MsgBuffer) + /* Объявляет MemoryHighAddr — данные MemoryHighAddr. */ + Uint16 MemoryHighAddr; // EEPROM address of data associated with msg (high byte) + /* Объявляет MemoryLowAddr — данные MemoryLowAddr. */ + Uint16 MemoryLowAddr; // EEPROM address of data associated with msg (low byte) + /* Объявляет MsgBuffer — Msg буфер. */ + Uint16 MsgBuffer[I2C_MAX_BUFFER_SIZE]; // Array holding msg data - max that + // MAX_BUFFER_SIZE can be is 16 due to + // the FIFO's +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_I2C_DEFINES_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_SWPrioritizedIsrLevels.h b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_SWPrioritizedIsrLevels.h new file mode 100644 index 0000000..67fb657 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/common/include/DSP2833x_SWPrioritizedIsrLevels.h @@ -0,0 +1,10803 @@ +/* Поставляемое TI описание SWPrioritizedIsrLevels для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/2 $ +// Checkin $Date: April 4, 2007 14:25:21 $ +//########################################################################### +// +// FILE: DSP2833x_SWPrioritizedIsrLevels.h +// +// TITLE: DSP28 Devices Software Prioritized Interrupt Service Routine +// Level definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_SW_PRIORITZIED_ISR_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_SW_PRIORITZIED_ISR_H +/* Определяет защитный символ или переключатель DSP2833x_SW_PRIORITZIED_ISR_H для последующей компиляции. */ +#define DSP2833x_SW_PRIORITZIED_ISR_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +//------------------------------------------------------------------------------- +// Interrupt Enable Register Allocation For 2833x Devices: +//------------------------------------------------------------------------------- +// Interrupts can be enabled/disabled using the CPU interrupt enable register +// (IER) and the PIE interrupt enable registers (PIEIER1 to PIEIER12). +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +// Set "Global" Interrupt Priority Level (IER register): +//------------------------------------------------------------------------------- +// The user must set the appropriate priority level for each of the CPU +// interrupts. This is termed as the "global" priority. The priority level +// must be a number between 1 (highest) to 16 (lowest). A value of 0 must +// be entered for reserved interrupts or interrupts that are not used. This +// will also reduce code size by not including ISR's that are not used. +// +// Note: The priority levels below are used to calculate the IER register +// interrupt masks MINT1 to MINT16. +// +// +// Note: The priority levels shown here may not make sense in a +// real application. This is for demonstration purposes only!!! +// +// The user should change these to values that make sense for +// their application. +// +// 0 = not used +// 1 = highest priority +// ... +// 16 = lowest priority +/* Задаёт INT1PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT1PL 2 // Group1 Interrupts (PIEIER1) +/* Задаёт INT2PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT2PL 0 // Group2 Interrupts (PIEIER2) +/* Задаёт INT3PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT3PL 4 // Group3 Interrupts (PIEIER3) +/* Задаёт INT4PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT4PL 2 // Group4 Interrupts (PIEIER4) +/* Задаёт INT5PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT5PL 2 // Group5 Interrupts (PIEIER5) +/* Задаёт INT6PL = 3; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT6PL 3 // Group6 Interrupts (PIEIER6) +/* Задаёт INT7PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT7PL 0 // reserved +/* Задаёт INT8PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT8PL 0 // reserved +/* Задаёт INT9PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT9PL 1 // Group9 Interrupts (PIEIER9) +/* Задаёт INT10PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT10PL 0 // reserved +/* Задаёт INT11PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT11PL 0 // reserved +/* Задаёт INT12PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT12PL 0 // reserved +/* Задаёт INT13PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT13PL 4 // XINT13 +/* Задаёт INT14PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT14PL 4 // INT14 (TINT2) +/* Задаёт INT15PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT15PL 4 // DATALOG +/* Задаёт INT16PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define INT16PL 4 // RTOSINT + +//------------------------------------------------------------------------------- +// Set "Group" Interrupt Priority Level (PIEIER1 to PIEIER12 registers): +//------------------------------------------------------------------------------- +// The user must set the appropriate priority level for each of the PIE +// interrupts. This is termed as the "group" priority. The priority level +// must be a number between 1 (highest) to 8 (lowest). A value of 0 must +// be entered for reserved interrupts or interrupts that are not used. This +// will also reduce code size by not including ISR's that are not used: +// +// Note: The priority levels below are used to calculate the following +// PIEIER register interrupt masks: +// MG11 to MG18 +// MG21 to MG28 +// MG31 to MG38 +// MG41 to MG48 +// MG51 to MG58 +// MG61 to MG68 +// MG71 to MG78 +// MG81 to MG88 +// MG91 to MG98 +// MG101 to MG108 +// MG111 to MG118 +// MG121 to MG128 +// +// Note: The priority levels shown here may not make sense in a +// real application. This is for demonstration purposes only!!! +// +// The user should change these to values that make sense for +// their application. +// +// 0 = not used +// 1 = highest priority +// ... +// 8 = lowest priority +// +/* Задаёт G11PL = 7; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G11PL 7 // SEQ1INT (ADC) +/* Задаёт G12PL = 6; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G12PL 6 // SEQ2INT (ADC) +/* Задаёт G13PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G13PL 0 // reserved +/* Задаёт G14PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G14PL 1 // XINT1 (External) +/* Задаёт G15PL = 3; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G15PL 3 // XINT2 (External) +/* Задаёт G16PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G16PL 2 // ADCINT (ADC) +/* Задаёт G17PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G17PL 1 // TINT0 (CPU Timer 0) +/* Задаёт G18PL = 5; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G18PL 5 // WAKEINT (WD/LPM) + +/* Задаёт G21PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G21PL 4 // EPWM1_TZINT (ePWM1 Trip) +/* Задаёт G22PL = 3; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G22PL 3 // EPWM2_TZINT (ePWM2 Trip) +/* Задаёт G23PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G23PL 2 // EPWM3_TZINT (ePWM3 Trip) +/* Задаёт G24PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G24PL 1 // EPWM4_TZINT (ePWM4 Trip) +/* Задаёт G25PL = 5; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G25PL 5 // EPWM5_TZINT (ePWM5 Trip) +/* Задаёт G26PL = 6; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G26PL 6 // EPWM6_TZINT (ePWM6 Trip) +/* Задаёт G27PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G27PL 0 // reserved +/* Задаёт G28PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G28PL 0 // reserved + +/* Задаёт G31PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G31PL 4 // EPWM1_INT (ePWM1 Int) +/* Задаёт G32PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G32PL 1 // EPWM2_INT (ePWM2 Int) +/* Задаёт G33PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G33PL 1 // EPWM3_INT (ePWM3 Int) +/* Задаёт G34PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G34PL 2 // EPWM4_INT (ePWM4 Int) +/* Задаёт G35PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G35PL 2 // EPWM5_INT (ePWM5 Int) +/* Задаёт G36PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G36PL 1 // EPWM6_INT (ePWM6 Int) +/* Задаёт G37PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G37PL 0 // reserved +/* Задаёт G38PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G38PL 0 // reserved + +/* Задаёт G41PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G41PL 2 // ECAP1_INT (eCAP1 Int) +/* Задаёт G42PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G42PL 1 // ECAP2_INT (eCAP2 Int) +/* Задаёт G43PL = 3; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G43PL 3 // ECAP3_INT (eCAP3 Int) +/* Задаёт G44PL = 3; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G44PL 3 // ECAP4_INT (eCAP4 Int) +/* Задаёт G45PL = 5; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G45PL 5 // ECAP5_INT (eCAP5 Int) +/* Задаёт G46PL = 5; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G46PL 5 // ECAP6_INT (eCAP6 Int) +/* Задаёт G47PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G47PL 0 // reserved +/* Задаёт G48PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G48PL 0 // reserved + +/* Задаёт G51PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G51PL 2 // EQEP1_INT (eQEP1 Int) +/* Задаёт G52PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G52PL 1 // EQEP2_INT (eQEP2 Int) +/* Задаёт G53PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G53PL 0 // reserved +/* Задаёт G54PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G54PL 0 // reserved +/* Задаёт G55PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G55PL 0 // reserved +/* Задаёт G56PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G56PL 0 // reserved +/* Задаёт G57PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G57PL 0 // reserved +/* Задаёт G58PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G58PL 0 // reserved + +/* Задаёт G61PL = 3; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G61PL 3 // SPIRXINTA (SPI-A) +/* Задаёт G62PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G62PL 1 // SPITXINTA (SPI-A) +/* Задаёт G63PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G63PL 4 // MRINTB (McBSP-B) +/* Задаёт G64PL = 6; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G64PL 6 // MXINTB (McBSP-B) +/* Задаёт G65PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G65PL 2 // MRINTA (McBSP-A) +/* Задаёт G66PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G66PL 1 // MXINTA (McBSP-A) +/* Задаёт G67PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G67PL 0 // reserved +/* Задаёт G68PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G68PL 0 // reserved + +/* Задаёт G71PL = 5; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G71PL 5 // DINTCH1 (DMA) +/* Задаёт G72PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G72PL 4 // DINTCH2 (DMA) +/* Задаёт G73PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G73PL 4 // DINTCH3 (DMA) +/* Задаёт G74PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G74PL 2 // DINTCH4 (DMA) +/* Задаёт G75PL = 3; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G75PL 3 // DINTCH5 (DMA) +/* Задаёт G76PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G76PL 1 // DINTCH6 (DMA) +/* Задаёт G77PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G77PL 0 // reserved +/* Задаёт G78PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G78PL 0 // reserved + +/* Задаёт G81PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G81PL 1 // I2CINT1A (I2C-A) +/* Задаёт G82PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G82PL 2 // I2CINT2A (I2C-A) +/* Задаёт G83PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G83PL 0 // reserved +/* Задаёт G84PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G84PL 0 // reserved +/* Задаёт G85PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G85PL 4 // SCIRXINTC (SCI-C) +/* Задаёт G86PL = 3; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G86PL 3 // SCITXINTC (SCI-C) +/* Задаёт G87PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G87PL 0 // reserved +/* Задаёт G88PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G88PL 0 // reserved + +/* Задаёт G91PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G91PL 1 // SCIRXINTA (SCI-A) +/* Задаёт G92PL = 5; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G92PL 5 // SCITXINTA (SCI-A) +/* Задаёт G93PL = 3; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G93PL 3 // SCIRXINTB (SCI-B) +/* Задаёт G94PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G94PL 4 // SCITXINTB (SCI-B) +/* Задаёт G95PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G95PL 1 // ECAN0INTA (ECAN-A) +/* Задаёт G96PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G96PL 1 // ECAN1INTA (ECAN-A) +/* Задаёт G97PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G97PL 2 // ECAN0INTB (ECAN-B) +/* Задаёт G98PL = 4; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G98PL 4 // ECAN1INTB (ECAN-B) + +/* Задаёт G101PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G101PL 0 // reserved +/* Задаёт G102PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G102PL 0 // reserved +/* Задаёт G103PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G103PL 0 // reserved +/* Задаёт G104PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G104PL 0 // reserved +/* Задаёт G105PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G105PL 0 // reserved +/* Задаёт G106PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G106PL 0 // reserved +/* Задаёт G107PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G107PL 0 // reserved +/* Задаёт G108PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G108PL 0 // reserved + +/* Задаёт G111PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G111PL 0 // reserved +/* Задаёт G112PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G112PL 0 // reserved +/* Задаёт G113PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G113PL 0 // reserved +/* Задаёт G114PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G114PL 0 // reserved +/* Задаёт G115PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G115PL 0 // reserved +/* Задаёт G116PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G116PL 0 // reserved +/* Задаёт G117PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G117PL 0 // reserved +/* Задаёт G118PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G118PL 0 // reserved + +/* Задаёт G121PL = 5; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G121PL 5 // XINT3 (External) +/* Задаёт G122PL = 3; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G122PL 3 // XINT4 (External) +/* Задаёт G123PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G123PL 2 // XINT5 (External) +/* Задаёт G124PL = 2; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G124PL 2 // XINT6 (External) +/* Задаёт G125PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G125PL 1 // XINT7 (External) +/* Задаёт G126PL = 0; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G126PL 0 // reserved +/* Задаёт G127PL = 6; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G127PL 6 // LVF (FPA32) +/* Задаёт G128PL = 1; уровень приоритета; 0 отключает источник, меньшее ненулевое число означает более высокий приоритет. */ +#define G128PL 1 // LUF (FPA32) + + +// There should be no need to modify code below this line +//------------------------------------------------------------------------------- +// Automatically generate IER interrupt masks MINT1 to MINT16: +// + +// Beginning of MINT1: +/* Условие компиляции (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL == 0) +/* Задаёт MINT1_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 1_1PL. */ +#define MINT1_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_1PL. */ +#define MINT1_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT1PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT1PL) || (INT2PL == 0) +/* Задаёт MINT1_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 1_2PL. */ +#define MINT1_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_2PL. */ +#define MINT1_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT1PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT1PL) || (INT3PL == 0) +/* Задаёт MINT1_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 1_3PL. */ +#define MINT1_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_3PL. */ +#define MINT1_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT1PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT1PL) || (INT4PL == 0) +/* Задаёт MINT1_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 1_4PL. */ +#define MINT1_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_4PL. */ +#define MINT1_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT1PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT1PL) || (INT5PL == 0) +/* Задаёт MINT1_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 1_5PL. */ +#define MINT1_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_5PL. */ +#define MINT1_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT1PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT1PL) || (INT6PL == 0) +/* Задаёт MINT1_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 1_6PL. */ +#define MINT1_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_6PL. */ +#define MINT1_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT1PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT1PL) || (INT7PL == 0) +/* Задаёт MINT1_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 1_7PL. */ +#define MINT1_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_7PL. */ +#define MINT1_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT1PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT1PL) || (INT8PL == 0) +/* Задаёт MINT1_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 1_8PL. */ +#define MINT1_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_8PL. */ +#define MINT1_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT1PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT1PL) || (INT9PL == 0) +/* Задаёт MINT1_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 1_9PL. */ +#define MINT1_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_9PL. */ +#define MINT1_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT1PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT1PL) || (INT10PL == 0) +/* Задаёт MINT1_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 1_10PL. */ +#define MINT1_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_10PL. */ +#define MINT1_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT1PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT1PL) || (INT11PL == 0) +/* Задаёт MINT1_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 1_11PL. */ +#define MINT1_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_11PL. */ +#define MINT1_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT1PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT1PL) || (INT12PL == 0) +/* Задаёт MINT1_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 1_12PL. */ +#define MINT1_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_12PL. */ +#define MINT1_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT1PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT1PL) || (INT13PL == 0) +/* Задаёт MINT1_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 1_13PL. */ +#define MINT1_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_13PL. */ +#define MINT1_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT1PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT1PL) || (INT14PL == 0) +/* Задаёт MINT1_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 1_14PL. */ +#define MINT1_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_14PL. */ +#define MINT1_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT1PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT1PL) || (INT15PL == 0) +/* Задаёт MINT1_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 1_15PL. */ +#define MINT1_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_15PL. */ +#define MINT1_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT1PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT1PL) || (INT16PL == 0) +/* Задаёт MINT1_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 1_16PL. */ +#define MINT1_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT1_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 1_16PL. */ +#define MINT1_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT1 = (MINT1_1PL & MINT1_2PL & MINT1_3PL & MINT1_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 1. */ +#define MINT1 (MINT1_1PL & MINT1_2PL & MINT1_3PL & MINT1_4PL & \ + MINT1_5PL & MINT1_6PL & MINT1_7PL & MINT1_8PL & /* Продолжает список аргументов, полей или выражение MINT1_5PL & MINT1_6PL & MINT1_7PL & MINT1_8PL &; порядок элементов сохраняется. */ \ + MINT1_9PL & MINT1_10PL & MINT1_11PL & MINT1_12PL & /* Продолжает список аргументов, полей или выражение MINT1_9PL & MINT1_10PL & MINT1_11PL & MINT1_12PL &; порядок элементов сохраняется. */ \ + MINT1_13PL & MINT1_14PL & MINT1_15PL & MINT1_16PL) /* Продолжает список аргументов, полей или выражение MINT1_13PL & MINT1_14PL & MINT1_15PL & MINT1_16PL); порядок элементов сохраняется. */ +// End Of MINT1. + +// Beginning of MINT2: +/* Условие компиляции (INT1PL >= INT2PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT2PL) || (INT1PL == 0) +/* Задаёт MINT2_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 2_1PL. */ +#define MINT2_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_1PL. */ +#define MINT2_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL == 0) +/* Задаёт MINT2_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 2_2PL. */ +#define MINT2_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_2PL. */ +#define MINT2_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT2PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT2PL) || (INT3PL == 0) +/* Задаёт MINT2_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 2_3PL. */ +#define MINT2_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_3PL. */ +#define MINT2_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT2PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT2PL) || (INT4PL == 0) +/* Задаёт MINT2_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 2_4PL. */ +#define MINT2_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_4PL. */ +#define MINT2_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT2PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT2PL) || (INT5PL == 0) +/* Задаёт MINT2_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 2_5PL. */ +#define MINT2_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_5PL. */ +#define MINT2_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT2PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT2PL) || (INT6PL == 0) +/* Задаёт MINT2_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 2_6PL. */ +#define MINT2_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_6PL. */ +#define MINT2_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT2PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT2PL) || (INT7PL == 0) +/* Задаёт MINT2_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 2_7PL. */ +#define MINT2_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_7PL. */ +#define MINT2_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT2PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT2PL) || (INT8PL == 0) +/* Задаёт MINT2_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 2_8PL. */ +#define MINT2_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_8PL. */ +#define MINT2_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT2PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT2PL) || (INT9PL == 0) +/* Задаёт MINT2_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 2_9PL. */ +#define MINT2_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_9PL. */ +#define MINT2_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT2PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT2PL) || (INT10PL == 0) +/* Задаёт MINT2_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 2_10PL. */ +#define MINT2_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_10PL. */ +#define MINT2_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT2PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT2PL) || (INT11PL == 0) +/* Задаёт MINT2_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 2_11PL. */ +#define MINT2_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_11PL. */ +#define MINT2_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT2PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT2PL) || (INT12PL == 0) +/* Задаёт MINT2_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 2_12PL. */ +#define MINT2_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_12PL. */ +#define MINT2_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT2PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT2PL) || (INT13PL == 0) +/* Задаёт MINT2_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 2_13PL. */ +#define MINT2_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_13PL. */ +#define MINT2_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT2PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT2PL) || (INT14PL == 0) +/* Задаёт MINT2_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 2_14PL. */ +#define MINT2_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_14PL. */ +#define MINT2_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT2PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT2PL) || (INT15PL == 0) +/* Задаёт MINT2_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 2_15PL. */ +#define MINT2_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_15PL. */ +#define MINT2_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT2PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT2PL) || (INT16PL == 0) +/* Задаёт MINT2_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 2_16PL. */ +#define MINT2_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT2_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 2_16PL. */ +#define MINT2_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT2 = (MINT2_1PL & MINT2_2PL & MINT2_3PL & MINT2_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 2. */ +#define MINT2 (MINT2_1PL & MINT2_2PL & MINT2_3PL & MINT2_4PL & \ + MINT2_5PL & MINT2_6PL & MINT2_7PL & MINT2_8PL & /* Продолжает список аргументов, полей или выражение MINT2_5PL & MINT2_6PL & MINT2_7PL & MINT2_8PL &; порядок элементов сохраняется. */ \ + MINT2_9PL & MINT2_10PL & MINT2_11PL & MINT2_12PL & /* Продолжает список аргументов, полей или выражение MINT2_9PL & MINT2_10PL & MINT2_11PL & MINT2_12PL &; порядок элементов сохраняется. */ \ + MINT2_13PL & MINT2_14PL & MINT2_15PL & MINT2_16PL) /* Продолжает список аргументов, полей или выражение MINT2_13PL & MINT2_14PL & MINT2_15PL & MINT2_16PL); порядок элементов сохраняется. */ +// End Of MINT2. + +// Beginning of MINT3: +/* Условие компиляции (INT1PL >= INT3PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT3PL) || (INT1PL == 0) +/* Задаёт MINT3_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 3_1PL. */ +#define MINT3_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_1PL. */ +#define MINT3_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT3PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT3PL) || (INT2PL == 0) +/* Задаёт MINT3_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 3_2PL. */ +#define MINT3_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_2PL. */ +#define MINT3_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL == 0) +/* Задаёт MINT3_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 3_3PL. */ +#define MINT3_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_3PL. */ +#define MINT3_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT3PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT3PL) || (INT4PL == 0) +/* Задаёт MINT3_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 3_4PL. */ +#define MINT3_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_4PL. */ +#define MINT3_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT3PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT3PL) || (INT5PL == 0) +/* Задаёт MINT3_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 3_5PL. */ +#define MINT3_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_5PL. */ +#define MINT3_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT3PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT3PL) || (INT6PL == 0) +/* Задаёт MINT3_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 3_6PL. */ +#define MINT3_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_6PL. */ +#define MINT3_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT3PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT3PL) || (INT7PL == 0) +/* Задаёт MINT3_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 3_7PL. */ +#define MINT3_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_7PL. */ +#define MINT3_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT3PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT3PL) || (INT8PL == 0) +/* Задаёт MINT3_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 3_8PL. */ +#define MINT3_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_8PL. */ +#define MINT3_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT3PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT3PL) || (INT9PL == 0) +/* Задаёт MINT3_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 3_9PL. */ +#define MINT3_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_9PL. */ +#define MINT3_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT3PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT3PL) || (INT10PL == 0) +/* Задаёт MINT3_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 3_10PL. */ +#define MINT3_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_10PL. */ +#define MINT3_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT3PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT3PL) || (INT11PL == 0) +/* Задаёт MINT3_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 3_11PL. */ +#define MINT3_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_11PL. */ +#define MINT3_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT3PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT3PL) || (INT12PL == 0) +/* Задаёт MINT3_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 3_12PL. */ +#define MINT3_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_12PL. */ +#define MINT3_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT3PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT3PL) || (INT13PL == 0) +/* Задаёт MINT3_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 3_13PL. */ +#define MINT3_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_13PL. */ +#define MINT3_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT3PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT3PL) || (INT14PL == 0) +/* Задаёт MINT3_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 3_14PL. */ +#define MINT3_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_14PL. */ +#define MINT3_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT3PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT3PL) || (INT15PL == 0) +/* Задаёт MINT3_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 3_15PL. */ +#define MINT3_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_15PL. */ +#define MINT3_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT3PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT3PL) || (INT16PL == 0) +/* Задаёт MINT3_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 3_16PL. */ +#define MINT3_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT3_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 3_16PL. */ +#define MINT3_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT3 = (MINT3_1PL & MINT3_2PL & MINT3_3PL & MINT3_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 3. */ +#define MINT3 (MINT3_1PL & MINT3_2PL & MINT3_3PL & MINT3_4PL & \ + MINT3_5PL & MINT3_6PL & MINT3_7PL & MINT3_8PL & /* Продолжает список аргументов, полей или выражение MINT3_5PL & MINT3_6PL & MINT3_7PL & MINT3_8PL &; порядок элементов сохраняется. */ \ + MINT3_9PL & MINT3_10PL & MINT3_11PL & MINT3_12PL & /* Продолжает список аргументов, полей или выражение MINT3_9PL & MINT3_10PL & MINT3_11PL & MINT3_12PL &; порядок элементов сохраняется. */ \ + MINT3_13PL & MINT3_14PL & MINT3_15PL & MINT3_16PL) /* Продолжает список аргументов, полей или выражение MINT3_13PL & MINT3_14PL & MINT3_15PL & MINT3_16PL); порядок элементов сохраняется. */ +// End Of MINT3. + +// Beginning of MINT4: +/* Условие компиляции (INT1PL >= INT4PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT4PL) || (INT1PL == 0) +/* Задаёт MINT4_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 4_1PL. */ +#define MINT4_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_1PL. */ +#define MINT4_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT4PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT4PL) || (INT2PL == 0) +/* Задаёт MINT4_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 4_2PL. */ +#define MINT4_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_2PL. */ +#define MINT4_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT4PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT4PL) || (INT3PL == 0) +/* Задаёт MINT4_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 4_3PL. */ +#define MINT4_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_3PL. */ +#define MINT4_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL == 0) +/* Задаёт MINT4_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 4_4PL. */ +#define MINT4_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_4PL. */ +#define MINT4_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT4PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT4PL) || (INT5PL == 0) +/* Задаёт MINT4_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 4_5PL. */ +#define MINT4_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_5PL. */ +#define MINT4_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT4PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT4PL) || (INT6PL == 0) +/* Задаёт MINT4_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 4_6PL. */ +#define MINT4_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_6PL. */ +#define MINT4_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT4PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT4PL) || (INT7PL == 0) +/* Задаёт MINT4_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 4_7PL. */ +#define MINT4_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_7PL. */ +#define MINT4_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT4PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT4PL) || (INT8PL == 0) +/* Задаёт MINT4_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 4_8PL. */ +#define MINT4_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_8PL. */ +#define MINT4_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT4PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT4PL) || (INT9PL == 0) +/* Задаёт MINT4_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 4_9PL. */ +#define MINT4_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_9PL. */ +#define MINT4_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT4PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT4PL) || (INT10PL == 0) +/* Задаёт MINT4_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 4_10PL. */ +#define MINT4_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_10PL. */ +#define MINT4_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT4PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT4PL) || (INT11PL == 0) +/* Задаёт MINT4_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 4_11PL. */ +#define MINT4_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_11PL. */ +#define MINT4_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT4PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT4PL) || (INT12PL == 0) +/* Задаёт MINT4_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 4_12PL. */ +#define MINT4_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_12PL. */ +#define MINT4_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT4PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT4PL) || (INT13PL == 0) +/* Задаёт MINT4_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 4_13PL. */ +#define MINT4_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_13PL. */ +#define MINT4_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT4PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT4PL) || (INT14PL == 0) +/* Задаёт MINT4_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 4_14PL. */ +#define MINT4_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_14PL. */ +#define MINT4_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT4PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT4PL) || (INT15PL == 0) +/* Задаёт MINT4_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 4_15PL. */ +#define MINT4_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_15PL. */ +#define MINT4_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT4PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT4PL) || (INT16PL == 0) +/* Задаёт MINT4_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 4_16PL. */ +#define MINT4_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT4_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 4_16PL. */ +#define MINT4_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT4 = (MINT4_1PL & MINT4_2PL & MINT4_3PL & MINT4_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 4. */ +#define MINT4 (MINT4_1PL & MINT4_2PL & MINT4_3PL & MINT4_4PL & \ + MINT4_5PL & MINT4_6PL & MINT4_7PL & MINT4_8PL & /* Продолжает список аргументов, полей или выражение MINT4_5PL & MINT4_6PL & MINT4_7PL & MINT4_8PL &; порядок элементов сохраняется. */ \ + MINT4_9PL & MINT4_10PL & MINT4_11PL & MINT4_12PL & /* Продолжает список аргументов, полей или выражение MINT4_9PL & MINT4_10PL & MINT4_11PL & MINT4_12PL &; порядок элементов сохраняется. */ \ + MINT4_13PL & MINT4_14PL & MINT4_15PL & MINT4_16PL) /* Продолжает список аргументов, полей или выражение MINT4_13PL & MINT4_14PL & MINT4_15PL & MINT4_16PL); порядок элементов сохраняется. */ +// End Of MINT4. + +// Beginning of MINT5: +/* Условие компиляции (INT1PL >= INT5PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT5PL) || (INT1PL == 0) +/* Задаёт MINT5_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 5_1PL. */ +#define MINT5_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_1PL. */ +#define MINT5_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT5PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT5PL) || (INT2PL == 0) +/* Задаёт MINT5_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 5_2PL. */ +#define MINT5_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_2PL. */ +#define MINT5_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT5PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT5PL) || (INT3PL == 0) +/* Задаёт MINT5_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 5_3PL. */ +#define MINT5_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_3PL. */ +#define MINT5_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT5PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT5PL) || (INT4PL == 0) +/* Задаёт MINT5_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 5_4PL. */ +#define MINT5_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_4PL. */ +#define MINT5_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL == 0) +/* Задаёт MINT5_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 5_5PL. */ +#define MINT5_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_5PL. */ +#define MINT5_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT5PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT5PL) || (INT6PL == 0) +/* Задаёт MINT5_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 5_6PL. */ +#define MINT5_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_6PL. */ +#define MINT5_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT5PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT5PL) || (INT7PL == 0) +/* Задаёт MINT5_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 5_7PL. */ +#define MINT5_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_7PL. */ +#define MINT5_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT5PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT5PL) || (INT8PL == 0) +/* Задаёт MINT5_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 5_8PL. */ +#define MINT5_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_8PL. */ +#define MINT5_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT5PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT5PL) || (INT9PL == 0) +/* Задаёт MINT5_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 5_9PL. */ +#define MINT5_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_9PL. */ +#define MINT5_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT5PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT5PL) || (INT10PL == 0) +/* Задаёт MINT5_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 5_10PL. */ +#define MINT5_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_10PL. */ +#define MINT5_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT5PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT5PL) || (INT11PL == 0) +/* Задаёт MINT5_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 5_11PL. */ +#define MINT5_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_11PL. */ +#define MINT5_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT5PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT5PL) || (INT12PL == 0) +/* Задаёт MINT5_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 5_12PL. */ +#define MINT5_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_12PL. */ +#define MINT5_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT5PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT5PL) || (INT13PL == 0) +/* Задаёт MINT5_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 5_13PL. */ +#define MINT5_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_13PL. */ +#define MINT5_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT5PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT5PL) || (INT14PL == 0) +/* Задаёт MINT5_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 5_14PL. */ +#define MINT5_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_14PL. */ +#define MINT5_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT5PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT5PL) || (INT15PL == 0) +/* Задаёт MINT5_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 5_15PL. */ +#define MINT5_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_15PL. */ +#define MINT5_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT5PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT5PL) || (INT16PL == 0) +/* Задаёт MINT5_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 5_16PL. */ +#define MINT5_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT5_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 5_16PL. */ +#define MINT5_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT5 = (MINT5_1PL & MINT5_2PL & MINT5_3PL & MINT5_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 5. */ +#define MINT5 (MINT5_1PL & MINT5_2PL & MINT5_3PL & MINT5_4PL & \ + MINT5_5PL & MINT5_6PL & MINT5_7PL & MINT5_8PL & /* Продолжает список аргументов, полей или выражение MINT5_5PL & MINT5_6PL & MINT5_7PL & MINT5_8PL &; порядок элементов сохраняется. */ \ + MINT5_9PL & MINT5_10PL & MINT5_11PL & MINT5_12PL & /* Продолжает список аргументов, полей или выражение MINT5_9PL & MINT5_10PL & MINT5_11PL & MINT5_12PL &; порядок элементов сохраняется. */ \ + MINT5_13PL & MINT5_14PL & MINT5_15PL & MINT5_16PL) /* Продолжает список аргументов, полей или выражение MINT5_13PL & MINT5_14PL & MINT5_15PL & MINT5_16PL); порядок элементов сохраняется. */ +// End Of MINT5. + +// Beginning of MINT6: +/* Условие компиляции (INT1PL >= INT6PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT6PL) || (INT1PL == 0) +/* Задаёт MINT6_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 6_1PL. */ +#define MINT6_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_1PL. */ +#define MINT6_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT6PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT6PL) || (INT2PL == 0) +/* Задаёт MINT6_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 6_2PL. */ +#define MINT6_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_2PL. */ +#define MINT6_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT6PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT6PL) || (INT3PL == 0) +/* Задаёт MINT6_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 6_3PL. */ +#define MINT6_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_3PL. */ +#define MINT6_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT6PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT6PL) || (INT4PL == 0) +/* Задаёт MINT6_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 6_4PL. */ +#define MINT6_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_4PL. */ +#define MINT6_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT6PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT6PL) || (INT5PL == 0) +/* Задаёт MINT6_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 6_5PL. */ +#define MINT6_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_5PL. */ +#define MINT6_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL == 0) +/* Задаёт MINT6_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 6_6PL. */ +#define MINT6_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_6PL. */ +#define MINT6_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT6PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT6PL) || (INT7PL == 0) +/* Задаёт MINT6_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 6_7PL. */ +#define MINT6_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_7PL. */ +#define MINT6_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT6PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT6PL) || (INT8PL == 0) +/* Задаёт MINT6_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 6_8PL. */ +#define MINT6_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_8PL. */ +#define MINT6_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT6PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT6PL) || (INT9PL == 0) +/* Задаёт MINT6_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 6_9PL. */ +#define MINT6_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_9PL. */ +#define MINT6_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT6PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT6PL) || (INT10PL == 0) +/* Задаёт MINT6_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 6_10PL. */ +#define MINT6_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_10PL. */ +#define MINT6_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT6PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT6PL) || (INT11PL == 0) +/* Задаёт MINT6_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 6_11PL. */ +#define MINT6_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_11PL. */ +#define MINT6_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT6PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT6PL) || (INT12PL == 0) +/* Задаёт MINT6_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 6_12PL. */ +#define MINT6_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_12PL. */ +#define MINT6_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT6PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT6PL) || (INT13PL == 0) +/* Задаёт MINT6_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 6_13PL. */ +#define MINT6_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_13PL. */ +#define MINT6_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT6PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT6PL) || (INT14PL == 0) +/* Задаёт MINT6_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 6_14PL. */ +#define MINT6_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_14PL. */ +#define MINT6_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT6PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT6PL) || (INT15PL == 0) +/* Задаёт MINT6_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 6_15PL. */ +#define MINT6_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_15PL. */ +#define MINT6_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT6PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT6PL) || (INT16PL == 0) +/* Задаёт MINT6_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 6_16PL. */ +#define MINT6_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT6_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 6_16PL. */ +#define MINT6_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT6 = (MINT6_1PL & MINT6_2PL & MINT6_3PL & MINT6_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 6. */ +#define MINT6 (MINT6_1PL & MINT6_2PL & MINT6_3PL & MINT6_4PL & \ + MINT6_5PL & MINT6_6PL & MINT6_7PL & MINT6_8PL & /* Продолжает список аргументов, полей или выражение MINT6_5PL & MINT6_6PL & MINT6_7PL & MINT6_8PL &; порядок элементов сохраняется. */ \ + MINT6_9PL & MINT6_10PL & MINT6_11PL & MINT6_12PL & /* Продолжает список аргументов, полей или выражение MINT6_9PL & MINT6_10PL & MINT6_11PL & MINT6_12PL &; порядок элементов сохраняется. */ \ + MINT6_13PL & MINT6_14PL & MINT6_15PL & MINT6_16PL) /* Продолжает список аргументов, полей или выражение MINT6_13PL & MINT6_14PL & MINT6_15PL & MINT6_16PL); порядок элементов сохраняется. */ +// End Of MINT6. + +// Beginning of MINT7: +/* Условие компиляции (INT1PL >= INT7PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT7PL) || (INT1PL == 0) +/* Задаёт MINT7_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 7_1PL. */ +#define MINT7_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_1PL. */ +#define MINT7_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT7PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT7PL) || (INT2PL == 0) +/* Задаёт MINT7_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 7_2PL. */ +#define MINT7_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_2PL. */ +#define MINT7_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT7PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT7PL) || (INT3PL == 0) +/* Задаёт MINT7_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 7_3PL. */ +#define MINT7_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_3PL. */ +#define MINT7_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT7PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT7PL) || (INT4PL == 0) +/* Задаёт MINT7_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 7_4PL. */ +#define MINT7_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_4PL. */ +#define MINT7_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT7PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT7PL) || (INT5PL == 0) +/* Задаёт MINT7_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 7_5PL. */ +#define MINT7_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_5PL. */ +#define MINT7_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT7PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT7PL) || (INT6PL == 0) +/* Задаёт MINT7_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 7_6PL. */ +#define MINT7_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_6PL. */ +#define MINT7_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL == 0) +/* Задаёт MINT7_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 7_7PL. */ +#define MINT7_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_7PL. */ +#define MINT7_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT7PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT7PL) || (INT8PL == 0) +/* Задаёт MINT7_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 7_8PL. */ +#define MINT7_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_8PL. */ +#define MINT7_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT7PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT7PL) || (INT9PL == 0) +/* Задаёт MINT7_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 7_9PL. */ +#define MINT7_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_9PL. */ +#define MINT7_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT7PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT7PL) || (INT10PL == 0) +/* Задаёт MINT7_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 7_10PL. */ +#define MINT7_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_10PL. */ +#define MINT7_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT7PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT7PL) || (INT11PL == 0) +/* Задаёт MINT7_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 7_11PL. */ +#define MINT7_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_11PL. */ +#define MINT7_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT7PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT7PL) || (INT12PL == 0) +/* Задаёт MINT7_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 7_12PL. */ +#define MINT7_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_12PL. */ +#define MINT7_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT7PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT7PL) || (INT13PL == 0) +/* Задаёт MINT7_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 7_13PL. */ +#define MINT7_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_13PL. */ +#define MINT7_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT7PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT7PL) || (INT14PL == 0) +/* Задаёт MINT7_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 7_14PL. */ +#define MINT7_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_14PL. */ +#define MINT7_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT7PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT7PL) || (INT15PL == 0) +/* Задаёт MINT7_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 7_15PL. */ +#define MINT7_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_15PL. */ +#define MINT7_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT7PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT7PL) || (INT16PL == 0) +/* Задаёт MINT7_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 7_16PL. */ +#define MINT7_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT7_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 7_16PL. */ +#define MINT7_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT7 = (MINT7_1PL & MINT7_2PL & MINT7_3PL & MINT7_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 7. */ +#define MINT7 (MINT7_1PL & MINT7_2PL & MINT7_3PL & MINT7_4PL & \ + MINT7_5PL & MINT7_6PL & MINT7_7PL & MINT7_8PL & /* Продолжает список аргументов, полей или выражение MINT7_5PL & MINT7_6PL & MINT7_7PL & MINT7_8PL &; порядок элементов сохраняется. */ \ + MINT7_9PL & MINT7_10PL & MINT7_11PL & MINT7_12PL & /* Продолжает список аргументов, полей или выражение MINT7_9PL & MINT7_10PL & MINT7_11PL & MINT7_12PL &; порядок элементов сохраняется. */ \ + MINT7_13PL & MINT7_14PL & MINT7_15PL & MINT7_16PL) /* Продолжает список аргументов, полей или выражение MINT7_13PL & MINT7_14PL & MINT7_15PL & MINT7_16PL); порядок элементов сохраняется. */ +// End Of MINT7. + +// Beginning of MINT8: +/* Условие компиляции (INT1PL >= INT8PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT8PL) || (INT1PL == 0) +/* Задаёт MINT8_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 8_1PL. */ +#define MINT8_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_1PL. */ +#define MINT8_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT8PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT8PL) || (INT2PL == 0) +/* Задаёт MINT8_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 8_2PL. */ +#define MINT8_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_2PL. */ +#define MINT8_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT8PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT8PL) || (INT3PL == 0) +/* Задаёт MINT8_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 8_3PL. */ +#define MINT8_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_3PL. */ +#define MINT8_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT8PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT8PL) || (INT4PL == 0) +/* Задаёт MINT8_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 8_4PL. */ +#define MINT8_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_4PL. */ +#define MINT8_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT8PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT8PL) || (INT5PL == 0) +/* Задаёт MINT8_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 8_5PL. */ +#define MINT8_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_5PL. */ +#define MINT8_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT8PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT8PL) || (INT6PL == 0) +/* Задаёт MINT8_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 8_6PL. */ +#define MINT8_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_6PL. */ +#define MINT8_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT8PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT8PL) || (INT7PL == 0) +/* Задаёт MINT8_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 8_7PL. */ +#define MINT8_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_7PL. */ +#define MINT8_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL == 0) +/* Задаёт MINT8_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 8_8PL. */ +#define MINT8_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_8PL. */ +#define MINT8_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT8PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT8PL) || (INT9PL == 0) +/* Задаёт MINT8_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 8_9PL. */ +#define MINT8_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_9PL. */ +#define MINT8_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT8PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT8PL) || (INT10PL == 0) +/* Задаёт MINT8_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 8_10PL. */ +#define MINT8_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_10PL. */ +#define MINT8_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT8PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT8PL) || (INT11PL == 0) +/* Задаёт MINT8_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 8_11PL. */ +#define MINT8_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_11PL. */ +#define MINT8_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT8PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT8PL) || (INT12PL == 0) +/* Задаёт MINT8_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 8_12PL. */ +#define MINT8_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_12PL. */ +#define MINT8_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT8PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT8PL) || (INT13PL == 0) +/* Задаёт MINT8_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 8_13PL. */ +#define MINT8_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_13PL. */ +#define MINT8_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT8PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT8PL) || (INT14PL == 0) +/* Задаёт MINT8_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 8_14PL. */ +#define MINT8_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_14PL. */ +#define MINT8_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT8PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT8PL) || (INT15PL == 0) +/* Задаёт MINT8_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 8_15PL. */ +#define MINT8_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_15PL. */ +#define MINT8_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT8PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT8PL) || (INT16PL == 0) +/* Задаёт MINT8_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 8_16PL. */ +#define MINT8_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT8_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 8_16PL. */ +#define MINT8_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT8 = (MINT8_1PL & MINT8_2PL & MINT8_3PL & MINT8_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 8. */ +#define MINT8 (MINT8_1PL & MINT8_2PL & MINT8_3PL & MINT8_4PL & \ + MINT8_5PL & MINT8_6PL & MINT8_7PL & MINT8_8PL & /* Продолжает список аргументов, полей или выражение MINT8_5PL & MINT8_6PL & MINT8_7PL & MINT8_8PL &; порядок элементов сохраняется. */ \ + MINT8_9PL & MINT8_10PL & MINT8_11PL & MINT8_12PL & /* Продолжает список аргументов, полей или выражение MINT8_9PL & MINT8_10PL & MINT8_11PL & MINT8_12PL &; порядок элементов сохраняется. */ \ + MINT8_13PL & MINT8_14PL & MINT8_15PL & MINT8_16PL) /* Продолжает список аргументов, полей или выражение MINT8_13PL & MINT8_14PL & MINT8_15PL & MINT8_16PL); порядок элементов сохраняется. */ +// End Of MINT8. + +// Beginning of MINT9: +/* Условие компиляции (INT1PL >= INT9PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT9PL) || (INT1PL == 0) +/* Задаёт MINT9_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 9_1PL. */ +#define MINT9_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_1PL. */ +#define MINT9_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT9PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT9PL) || (INT2PL == 0) +/* Задаёт MINT9_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 9_2PL. */ +#define MINT9_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_2PL. */ +#define MINT9_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT9PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT9PL) || (INT3PL == 0) +/* Задаёт MINT9_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 9_3PL. */ +#define MINT9_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_3PL. */ +#define MINT9_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT9PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT9PL) || (INT4PL == 0) +/* Задаёт MINT9_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 9_4PL. */ +#define MINT9_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_4PL. */ +#define MINT9_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT9PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT9PL) || (INT5PL == 0) +/* Задаёт MINT9_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 9_5PL. */ +#define MINT9_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_5PL. */ +#define MINT9_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT9PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT9PL) || (INT6PL == 0) +/* Задаёт MINT9_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 9_6PL. */ +#define MINT9_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_6PL. */ +#define MINT9_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT9PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT9PL) || (INT7PL == 0) +/* Задаёт MINT9_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 9_7PL. */ +#define MINT9_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_7PL. */ +#define MINT9_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT9PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT9PL) || (INT8PL == 0) +/* Задаёт MINT9_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 9_8PL. */ +#define MINT9_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_8PL. */ +#define MINT9_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL == 0) +/* Задаёт MINT9_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 9_9PL. */ +#define MINT9_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_9PL. */ +#define MINT9_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT9PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT9PL) || (INT10PL == 0) +/* Задаёт MINT9_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 9_10PL. */ +#define MINT9_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_10PL. */ +#define MINT9_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT9PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT9PL) || (INT11PL == 0) +/* Задаёт MINT9_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 9_11PL. */ +#define MINT9_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_11PL. */ +#define MINT9_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT9PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT9PL) || (INT12PL == 0) +/* Задаёт MINT9_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 9_12PL. */ +#define MINT9_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_12PL. */ +#define MINT9_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT9PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT9PL) || (INT13PL == 0) +/* Задаёт MINT9_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 9_13PL. */ +#define MINT9_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_13PL. */ +#define MINT9_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT9PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT9PL) || (INT14PL == 0) +/* Задаёт MINT9_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 9_14PL. */ +#define MINT9_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_14PL. */ +#define MINT9_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT9PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT9PL) || (INT15PL == 0) +/* Задаёт MINT9_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 9_15PL. */ +#define MINT9_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_15PL. */ +#define MINT9_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT9PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT9PL) || (INT16PL == 0) +/* Задаёт MINT9_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 9_16PL. */ +#define MINT9_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT9_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 9_16PL. */ +#define MINT9_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT9 = (MINT9_1PL & MINT9_2PL & MINT9_3PL & MINT9_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 9. */ +#define MINT9 (MINT9_1PL & MINT9_2PL & MINT9_3PL & MINT9_4PL & \ + MINT9_5PL & MINT9_6PL & MINT9_7PL & MINT9_8PL & /* Продолжает список аргументов, полей или выражение MINT9_5PL & MINT9_6PL & MINT9_7PL & MINT9_8PL &; порядок элементов сохраняется. */ \ + MINT9_9PL & MINT9_10PL & MINT9_11PL & MINT9_12PL & /* Продолжает список аргументов, полей или выражение MINT9_9PL & MINT9_10PL & MINT9_11PL & MINT9_12PL &; порядок элементов сохраняется. */ \ + MINT9_13PL & MINT9_14PL & MINT9_15PL & MINT9_16PL) /* Продолжает список аргументов, полей или выражение MINT9_13PL & MINT9_14PL & MINT9_15PL & MINT9_16PL); порядок элементов сохраняется. */ +// End Of MINT9. + +// Beginning of MINT10: +/* Условие компиляции (INT1PL >= INT10PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT10PL) || (INT1PL == 0) +/* Задаёт MINT10_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 10_1PL. */ +#define MINT10_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_1PL. */ +#define MINT10_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT10PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT10PL) || (INT2PL == 0) +/* Задаёт MINT10_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 10_2PL. */ +#define MINT10_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_2PL. */ +#define MINT10_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT10PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT10PL) || (INT3PL == 0) +/* Задаёт MINT10_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 10_3PL. */ +#define MINT10_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_3PL. */ +#define MINT10_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT10PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT10PL) || (INT4PL == 0) +/* Задаёт MINT10_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 10_4PL. */ +#define MINT10_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_4PL. */ +#define MINT10_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT10PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT10PL) || (INT5PL == 0) +/* Задаёт MINT10_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 10_5PL. */ +#define MINT10_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_5PL. */ +#define MINT10_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT10PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT10PL) || (INT6PL == 0) +/* Задаёт MINT10_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 10_6PL. */ +#define MINT10_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_6PL. */ +#define MINT10_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT10PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT10PL) || (INT7PL == 0) +/* Задаёт MINT10_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 10_7PL. */ +#define MINT10_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_7PL. */ +#define MINT10_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT10PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT10PL) || (INT8PL == 0) +/* Задаёт MINT10_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 10_8PL. */ +#define MINT10_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_8PL. */ +#define MINT10_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT10PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT10PL) || (INT9PL == 0) +/* Задаёт MINT10_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 10_9PL. */ +#define MINT10_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_9PL. */ +#define MINT10_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL == 0) +/* Задаёт MINT10_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 10_10PL. */ +#define MINT10_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_10PL. */ +#define MINT10_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT10PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT10PL) || (INT11PL == 0) +/* Задаёт MINT10_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 10_11PL. */ +#define MINT10_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_11PL. */ +#define MINT10_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT10PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT10PL) || (INT12PL == 0) +/* Задаёт MINT10_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 10_12PL. */ +#define MINT10_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_12PL. */ +#define MINT10_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT10PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT10PL) || (INT13PL == 0) +/* Задаёт MINT10_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 10_13PL. */ +#define MINT10_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_13PL. */ +#define MINT10_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT10PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT10PL) || (INT14PL == 0) +/* Задаёт MINT10_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 10_14PL. */ +#define MINT10_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_14PL. */ +#define MINT10_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT10PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT10PL) || (INT15PL == 0) +/* Задаёт MINT10_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 10_15PL. */ +#define MINT10_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_15PL. */ +#define MINT10_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT10PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT10PL) || (INT16PL == 0) +/* Задаёт MINT10_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 10_16PL. */ +#define MINT10_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT10_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 10_16PL. */ +#define MINT10_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT10 = (MINT10_1PL & MINT10_2PL & MINT10_3PL & MINT10_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 10. */ +#define MINT10 (MINT10_1PL & MINT10_2PL & MINT10_3PL & MINT10_4PL & \ + MINT10_5PL & MINT10_6PL & MINT10_7PL & MINT10_8PL & /* Продолжает список аргументов, полей или выражение MINT10_5PL & MINT10_6PL & MINT10_7PL & MINT10_8PL &; порядок элементов сохраняется. */ \ + MINT10_9PL & MINT10_10PL & MINT10_11PL & MINT10_12PL & /* Продолжает список аргументов, полей или выражение MINT10_9PL & MINT10_10PL & MINT10_11PL & MINT10_12PL &; порядок элементов сохраняется. */ \ + MINT10_13PL & MINT10_14PL & MINT10_15PL & MINT10_16PL) /* Продолжает список аргументов, полей или выражение MINT10_13PL & MINT10_14PL & MINT10_15PL & MINT10_16PL); порядок элементов сохраняется. */ +// End Of MINT10. + +// Beginning of MINT11: +/* Условие компиляции (INT1PL >= INT11PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT11PL) || (INT1PL == 0) +/* Задаёт MINT11_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 11_1PL. */ +#define MINT11_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_1PL. */ +#define MINT11_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT11PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT11PL) || (INT2PL == 0) +/* Задаёт MINT11_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 11_2PL. */ +#define MINT11_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_2PL. */ +#define MINT11_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT11PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT11PL) || (INT3PL == 0) +/* Задаёт MINT11_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 11_3PL. */ +#define MINT11_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_3PL. */ +#define MINT11_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT11PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT11PL) || (INT4PL == 0) +/* Задаёт MINT11_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 11_4PL. */ +#define MINT11_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_4PL. */ +#define MINT11_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT11PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT11PL) || (INT5PL == 0) +/* Задаёт MINT11_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 11_5PL. */ +#define MINT11_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_5PL. */ +#define MINT11_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT11PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT11PL) || (INT6PL == 0) +/* Задаёт MINT11_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 11_6PL. */ +#define MINT11_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_6PL. */ +#define MINT11_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT11PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT11PL) || (INT7PL == 0) +/* Задаёт MINT11_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 11_7PL. */ +#define MINT11_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_7PL. */ +#define MINT11_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT11PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT11PL) || (INT8PL == 0) +/* Задаёт MINT11_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 11_8PL. */ +#define MINT11_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_8PL. */ +#define MINT11_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT11PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT11PL) || (INT9PL == 0) +/* Задаёт MINT11_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 11_9PL. */ +#define MINT11_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_9PL. */ +#define MINT11_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT11PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT11PL) || (INT10PL == 0) +/* Задаёт MINT11_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 11_10PL. */ +#define MINT11_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_10PL. */ +#define MINT11_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL == 0) +/* Задаёт MINT11_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 11_11PL. */ +#define MINT11_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_11PL. */ +#define MINT11_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT11PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT11PL) || (INT12PL == 0) +/* Задаёт MINT11_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 11_12PL. */ +#define MINT11_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_12PL. */ +#define MINT11_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT11PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT11PL) || (INT13PL == 0) +/* Задаёт MINT11_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 11_13PL. */ +#define MINT11_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_13PL. */ +#define MINT11_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT11PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT11PL) || (INT14PL == 0) +/* Задаёт MINT11_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 11_14PL. */ +#define MINT11_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_14PL. */ +#define MINT11_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT11PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT11PL) || (INT15PL == 0) +/* Задаёт MINT11_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 11_15PL. */ +#define MINT11_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_15PL. */ +#define MINT11_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT11PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT11PL) || (INT16PL == 0) +/* Задаёт MINT11_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 11_16PL. */ +#define MINT11_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT11_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 11_16PL. */ +#define MINT11_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT11 = (MINT11_1PL & MINT11_2PL & MINT11_3PL & MINT11_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 11. */ +#define MINT11 (MINT11_1PL & MINT11_2PL & MINT11_3PL & MINT11_4PL & \ + MINT11_5PL & MINT11_6PL & MINT11_7PL & MINT11_8PL & /* Продолжает список аргументов, полей или выражение MINT11_5PL & MINT11_6PL & MINT11_7PL & MINT11_8PL &; порядок элементов сохраняется. */ \ + MINT11_9PL & MINT11_10PL & MINT11_11PL & MINT11_12PL & /* Продолжает список аргументов, полей или выражение MINT11_9PL & MINT11_10PL & MINT11_11PL & MINT11_12PL &; порядок элементов сохраняется. */ \ + MINT11_13PL & MINT11_14PL & MINT11_15PL & MINT11_16PL) /* Продолжает список аргументов, полей или выражение MINT11_13PL & MINT11_14PL & MINT11_15PL & MINT11_16PL); порядок элементов сохраняется. */ +// End Of MINT11. + +// Beginning of MINT12: +/* Условие компиляции (INT1PL >= INT12PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT12PL) || (INT1PL == 0) +/* Задаёт MINT12_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 12_1PL. */ +#define MINT12_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_1PL. */ +#define MINT12_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT12PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT12PL) || (INT2PL == 0) +/* Задаёт MINT12_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 12_2PL. */ +#define MINT12_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_2PL. */ +#define MINT12_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT12PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT12PL) || (INT3PL == 0) +/* Задаёт MINT12_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 12_3PL. */ +#define MINT12_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_3PL. */ +#define MINT12_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT12PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT12PL) || (INT4PL == 0) +/* Задаёт MINT12_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 12_4PL. */ +#define MINT12_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_4PL. */ +#define MINT12_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT12PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT12PL) || (INT5PL == 0) +/* Задаёт MINT12_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 12_5PL. */ +#define MINT12_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_5PL. */ +#define MINT12_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT12PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT12PL) || (INT6PL == 0) +/* Задаёт MINT12_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 12_6PL. */ +#define MINT12_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_6PL. */ +#define MINT12_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT12PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT12PL) || (INT7PL == 0) +/* Задаёт MINT12_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 12_7PL. */ +#define MINT12_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_7PL. */ +#define MINT12_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT12PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT12PL) || (INT8PL == 0) +/* Задаёт MINT12_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 12_8PL. */ +#define MINT12_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_8PL. */ +#define MINT12_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT12PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT12PL) || (INT9PL == 0) +/* Задаёт MINT12_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 12_9PL. */ +#define MINT12_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_9PL. */ +#define MINT12_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT12PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT12PL) || (INT10PL == 0) +/* Задаёт MINT12_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 12_10PL. */ +#define MINT12_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_10PL. */ +#define MINT12_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT12PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT12PL) || (INT11PL == 0) +/* Задаёт MINT12_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 12_11PL. */ +#define MINT12_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_11PL. */ +#define MINT12_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL == 0) +/* Задаёт MINT12_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 12_12PL. */ +#define MINT12_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_12PL. */ +#define MINT12_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT12PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT12PL) || (INT13PL == 0) +/* Задаёт MINT12_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 12_13PL. */ +#define MINT12_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_13PL. */ +#define MINT12_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT12PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT12PL) || (INT14PL == 0) +/* Задаёт MINT12_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 12_14PL. */ +#define MINT12_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_14PL. */ +#define MINT12_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT12PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT12PL) || (INT15PL == 0) +/* Задаёт MINT12_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 12_15PL. */ +#define MINT12_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_15PL. */ +#define MINT12_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT12PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT12PL) || (INT16PL == 0) +/* Задаёт MINT12_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 12_16PL. */ +#define MINT12_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT12_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 12_16PL. */ +#define MINT12_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT12 = (MINT12_1PL & MINT12_2PL & MINT12_3PL & MINT12_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 12. */ +#define MINT12 (MINT12_1PL & MINT12_2PL & MINT12_3PL & MINT12_4PL & \ + MINT12_5PL & MINT12_6PL & MINT12_7PL & MINT12_8PL & /* Продолжает список аргументов, полей или выражение MINT12_5PL & MINT12_6PL & MINT12_7PL & MINT12_8PL &; порядок элементов сохраняется. */ \ + MINT12_9PL & MINT12_10PL & MINT12_11PL & MINT12_12PL & /* Продолжает список аргументов, полей или выражение MINT12_9PL & MINT12_10PL & MINT12_11PL & MINT12_12PL &; порядок элементов сохраняется. */ \ + MINT12_13PL & MINT12_14PL & MINT12_15PL & MINT12_16PL) /* Продолжает список аргументов, полей или выражение MINT12_13PL & MINT12_14PL & MINT12_15PL & MINT12_16PL); порядок элементов сохраняется. */ +// End Of MINT12. + +// Beginning of MINT13: +/* Условие компиляции (INT1PL >= INT13PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT13PL) || (INT1PL == 0) +/* Задаёт MINT13_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 13_1PL. */ +#define MINT13_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_1PL. */ +#define MINT13_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT13PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT13PL) || (INT2PL == 0) +/* Задаёт MINT13_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 13_2PL. */ +#define MINT13_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_2PL. */ +#define MINT13_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT13PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT13PL) || (INT3PL == 0) +/* Задаёт MINT13_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 13_3PL. */ +#define MINT13_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_3PL. */ +#define MINT13_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT13PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT13PL) || (INT4PL == 0) +/* Задаёт MINT13_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 13_4PL. */ +#define MINT13_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_4PL. */ +#define MINT13_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT13PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT13PL) || (INT5PL == 0) +/* Задаёт MINT13_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 13_5PL. */ +#define MINT13_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_5PL. */ +#define MINT13_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT13PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT13PL) || (INT6PL == 0) +/* Задаёт MINT13_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 13_6PL. */ +#define MINT13_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_6PL. */ +#define MINT13_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT13PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT13PL) || (INT7PL == 0) +/* Задаёт MINT13_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 13_7PL. */ +#define MINT13_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_7PL. */ +#define MINT13_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT13PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT13PL) || (INT8PL == 0) +/* Задаёт MINT13_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 13_8PL. */ +#define MINT13_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_8PL. */ +#define MINT13_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT13PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT13PL) || (INT9PL == 0) +/* Задаёт MINT13_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 13_9PL. */ +#define MINT13_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_9PL. */ +#define MINT13_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT13PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT13PL) || (INT10PL == 0) +/* Задаёт MINT13_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 13_10PL. */ +#define MINT13_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_10PL. */ +#define MINT13_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT13PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT13PL) || (INT11PL == 0) +/* Задаёт MINT13_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 13_11PL. */ +#define MINT13_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_11PL. */ +#define MINT13_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT13_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 13_12PL. */ +#define MINT13_12PL ~(1 << 11) + +/* Условие компиляции (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL == 0) +/* Задаёт MINT13_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 13_13PL. */ +#define MINT13_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_13PL. */ +#define MINT13_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT13PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT13PL) || (INT14PL == 0) +/* Задаёт MINT13_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 13_14PL. */ +#define MINT13_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_14PL. */ +#define MINT13_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT13PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT13PL) || (INT15PL == 0) +/* Задаёт MINT13_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 13_15PL. */ +#define MINT13_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_15PL. */ +#define MINT13_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT13PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT13PL) || (INT16PL == 0) +/* Задаёт MINT13_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 13_16PL. */ +#define MINT13_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT13_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 13_16PL. */ +#define MINT13_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT13 = (MINT13_1PL & MINT13_2PL & MINT13_3PL & MINT13_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 13. */ +#define MINT13 (MINT13_1PL & MINT13_2PL & MINT13_3PL & MINT13_4PL & \ + MINT13_5PL & MINT13_6PL & MINT13_7PL & MINT13_8PL & /* Продолжает список аргументов, полей или выражение MINT13_5PL & MINT13_6PL & MINT13_7PL & MINT13_8PL &; порядок элементов сохраняется. */ \ + MINT13_9PL & MINT13_10PL & MINT13_11PL & MINT13_12PL & /* Продолжает список аргументов, полей или выражение MINT13_9PL & MINT13_10PL & MINT13_11PL & MINT13_12PL &; порядок элементов сохраняется. */ \ + MINT13_13PL & MINT13_14PL & MINT13_15PL & MINT13_16PL) /* Продолжает список аргументов, полей или выражение MINT13_13PL & MINT13_14PL & MINT13_15PL & MINT13_16PL); порядок элементов сохраняется. */ +// End Of MINT13. + +// Beginning of MINT14: +/* Условие компиляции (INT1PL >= INT14PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT14PL) || (INT1PL == 0) +/* Задаёт MINT14_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 14_1PL. */ +#define MINT14_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_1PL. */ +#define MINT14_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT14PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT14PL) || (INT2PL == 0) +/* Задаёт MINT14_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 14_2PL. */ +#define MINT14_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_2PL. */ +#define MINT14_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT14PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT14PL) || (INT3PL == 0) +/* Задаёт MINT14_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 14_3PL. */ +#define MINT14_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_3PL. */ +#define MINT14_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT14PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT14PL) || (INT4PL == 0) +/* Задаёт MINT14_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 14_4PL. */ +#define MINT14_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_4PL. */ +#define MINT14_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT14PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT14PL) || (INT5PL == 0) +/* Задаёт MINT14_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 14_5PL. */ +#define MINT14_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_5PL. */ +#define MINT14_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT14PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT14PL) || (INT6PL == 0) +/* Задаёт MINT14_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 14_6PL. */ +#define MINT14_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_6PL. */ +#define MINT14_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT14PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT14PL) || (INT7PL == 0) +/* Задаёт MINT14_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 14_7PL. */ +#define MINT14_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_7PL. */ +#define MINT14_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT14PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT14PL) || (INT8PL == 0) +/* Задаёт MINT14_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 14_8PL. */ +#define MINT14_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_8PL. */ +#define MINT14_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT14PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT14PL) || (INT9PL == 0) +/* Задаёт MINT14_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 14_9PL. */ +#define MINT14_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_9PL. */ +#define MINT14_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT14PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT14PL) || (INT10PL == 0) +/* Задаёт MINT14_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 14_10PL. */ +#define MINT14_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_10PL. */ +#define MINT14_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT14PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT14PL) || (INT11PL == 0) +/* Задаёт MINT14_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 14_11PL. */ +#define MINT14_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_11PL. */ +#define MINT14_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT14PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT14PL) || (INT12PL == 0) +/* Задаёт MINT14_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 14_12PL. */ +#define MINT14_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_12PL. */ +#define MINT14_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT14PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT14PL) || (INT13PL == 0) +/* Задаёт MINT14_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 14_13PL. */ +#define MINT14_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_13PL. */ +#define MINT14_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT14_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 14_14PL. */ +#define MINT14_14PL ~(1 << 13) + +/* Условие компиляции (INT15PL >= INT14PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT14PL) || (INT15PL == 0) +/* Задаёт MINT14_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 14_15PL. */ +#define MINT14_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_15PL. */ +#define MINT14_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT16PL >= INT14PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT14PL) || (INT16PL == 0) +/* Задаёт MINT14_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 14_16PL. */ +#define MINT14_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT14_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 14_16PL. */ +#define MINT14_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT14 = (MINT14_1PL & MINT14_2PL & MINT14_3PL & MINT14_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 14. */ +#define MINT14 (MINT14_1PL & MINT14_2PL & MINT14_3PL & MINT14_4PL & \ + MINT14_5PL & MINT14_6PL & MINT14_7PL & MINT14_8PL & /* Продолжает список аргументов, полей или выражение MINT14_5PL & MINT14_6PL & MINT14_7PL & MINT14_8PL &; порядок элементов сохраняется. */ \ + MINT14_9PL & MINT14_10PL & MINT14_11PL & MINT14_12PL & /* Продолжает список аргументов, полей или выражение MINT14_9PL & MINT14_10PL & MINT14_11PL & MINT14_12PL &; порядок элементов сохраняется. */ \ + MINT14_13PL & MINT14_14PL & MINT14_15PL & MINT14_16PL) /* Продолжает список аргументов, полей или выражение MINT14_13PL & MINT14_14PL & MINT14_15PL & MINT14_16PL); порядок элементов сохраняется. */ +// End Of MINT14. + +// Beginning of MINT15: +/* Условие компиляции (INT1PL >= INT15PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT15PL) || (INT1PL == 0) +/* Задаёт MINT15_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 15_1PL. */ +#define MINT15_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_1PL. */ +#define MINT15_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT15PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT15PL) || (INT2PL == 0) +/* Задаёт MINT15_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 15_2PL. */ +#define MINT15_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_2PL. */ +#define MINT15_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT15PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT15PL) || (INT3PL == 0) +/* Задаёт MINT15_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 15_3PL. */ +#define MINT15_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_3PL. */ +#define MINT15_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT15PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT15PL) || (INT4PL == 0) +/* Задаёт MINT15_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 15_4PL. */ +#define MINT15_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_4PL. */ +#define MINT15_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT15PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT15PL) || (INT5PL == 0) +/* Задаёт MINT15_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 15_5PL. */ +#define MINT15_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_5PL. */ +#define MINT15_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT15PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT15PL) || (INT6PL == 0) +/* Задаёт MINT15_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 15_6PL. */ +#define MINT15_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_6PL. */ +#define MINT15_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT15PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT15PL) || (INT7PL == 0) +/* Задаёт MINT15_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 15_7PL. */ +#define MINT15_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_7PL. */ +#define MINT15_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT15PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT15PL) || (INT8PL == 0) +/* Задаёт MINT15_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 15_8PL. */ +#define MINT15_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_8PL. */ +#define MINT15_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT15PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT15PL) || (INT9PL == 0) +/* Задаёт MINT15_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 15_9PL. */ +#define MINT15_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_9PL. */ +#define MINT15_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT15PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT15PL) || (INT10PL == 0) +/* Задаёт MINT15_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 15_10PL. */ +#define MINT15_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_10PL. */ +#define MINT15_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT15PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT15PL) || (INT11PL == 0) +/* Задаёт MINT15_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 15_11PL. */ +#define MINT15_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_11PL. */ +#define MINT15_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT15PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT15PL) || (INT12PL == 0) +/* Задаёт MINT15_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 15_12PL. */ +#define MINT15_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_12PL. */ +#define MINT15_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT15PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT15PL) || (INT13PL == 0) +/* Задаёт MINT15_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 15_13PL. */ +#define MINT15_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_13PL. */ +#define MINT15_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT15PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT15PL) || (INT14PL == 0) +/* Задаёт MINT15_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 15_14PL. */ +#define MINT15_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_14PL. */ +#define MINT15_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT15_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 15_15PL. */ +#define MINT15_15PL ~(1 << 14) + +/* Условие компиляции (INT16PL >= INT15PL) или (INT16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT16PL >= INT15PL) || (INT16PL == 0) +/* Задаёт MINT15_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 15_16PL. */ +#define MINT15_16PL ~(1 << 15) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT15_16PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 15_16PL. */ +#define MINT15_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT15 = (MINT15_1PL & MINT15_2PL & MINT15_3PL & MINT15_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 15. */ +#define MINT15 (MINT15_1PL & MINT15_2PL & MINT15_3PL & MINT15_4PL & \ + MINT15_5PL & MINT15_6PL & MINT15_7PL & MINT15_8PL & /* Продолжает список аргументов, полей или выражение MINT15_5PL & MINT15_6PL & MINT15_7PL & MINT15_8PL &; порядок элементов сохраняется. */ \ + MINT15_9PL & MINT15_10PL & MINT15_11PL & MINT15_12PL & /* Продолжает список аргументов, полей или выражение MINT15_9PL & MINT15_10PL & MINT15_11PL & MINT15_12PL &; порядок элементов сохраняется. */ \ + MINT15_13PL & MINT15_14PL & MINT15_15PL & MINT15_16PL) /* Продолжает список аргументов, полей или выражение MINT15_13PL & MINT15_14PL & MINT15_15PL & MINT15_16PL); порядок элементов сохраняется. */ +// End Of MINT15. + +// Beginning of MINT16: +/* Условие компиляции (INT1PL >= INT16PL) или (INT1PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT1PL >= INT16PL) || (INT1PL == 0) +/* Задаёт MINT16_1PL = ~(1 << 0); маска разрешённых прерываний ядра для приоритетного обработчика 16_1PL. */ +#define MINT16_1PL ~(1 << 0) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_1PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_1PL. */ +#define MINT16_1PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT2PL >= INT16PL) или (INT2PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT2PL >= INT16PL) || (INT2PL == 0) +/* Задаёт MINT16_2PL = ~(1 << 1); маска разрешённых прерываний ядра для приоритетного обработчика 16_2PL. */ +#define MINT16_2PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_2PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_2PL. */ +#define MINT16_2PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT3PL >= INT16PL) или (INT3PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT3PL >= INT16PL) || (INT3PL == 0) +/* Задаёт MINT16_3PL = ~(1 << 2); маска разрешённых прерываний ядра для приоритетного обработчика 16_3PL. */ +#define MINT16_3PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_3PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_3PL. */ +#define MINT16_3PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT4PL >= INT16PL) или (INT4PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT4PL >= INT16PL) || (INT4PL == 0) +/* Задаёт MINT16_4PL = ~(1 << 3); маска разрешённых прерываний ядра для приоритетного обработчика 16_4PL. */ +#define MINT16_4PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_4PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_4PL. */ +#define MINT16_4PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT5PL >= INT16PL) или (INT5PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT5PL >= INT16PL) || (INT5PL == 0) +/* Задаёт MINT16_5PL = ~(1 << 4); маска разрешённых прерываний ядра для приоритетного обработчика 16_5PL. */ +#define MINT16_5PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_5PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_5PL. */ +#define MINT16_5PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT6PL >= INT16PL) или (INT6PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT6PL >= INT16PL) || (INT6PL == 0) +/* Задаёт MINT16_6PL = ~(1 << 5); маска разрешённых прерываний ядра для приоритетного обработчика 16_6PL. */ +#define MINT16_6PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_6PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_6PL. */ +#define MINT16_6PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT7PL >= INT16PL) или (INT7PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT7PL >= INT16PL) || (INT7PL == 0) +/* Задаёт MINT16_7PL = ~(1 << 6); маска разрешённых прерываний ядра для приоритетного обработчика 16_7PL. */ +#define MINT16_7PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_7PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_7PL. */ +#define MINT16_7PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT8PL >= INT16PL) или (INT8PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT8PL >= INT16PL) || (INT8PL == 0) +/* Задаёт MINT16_8PL = ~(1 << 7); маска разрешённых прерываний ядра для приоритетного обработчика 16_8PL. */ +#define MINT16_8PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_8PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_8PL. */ +#define MINT16_8PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT9PL >= INT16PL) или (INT9PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT9PL >= INT16PL) || (INT9PL == 0) +/* Задаёт MINT16_9PL = ~(1 << 8); маска разрешённых прерываний ядра для приоритетного обработчика 16_9PL. */ +#define MINT16_9PL ~(1 << 8) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_9PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_9PL. */ +#define MINT16_9PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT10PL >= INT16PL) или (INT10PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT10PL >= INT16PL) || (INT10PL == 0) +/* Задаёт MINT16_10PL = ~(1 << 9); маска разрешённых прерываний ядра для приоритетного обработчика 16_10PL. */ +#define MINT16_10PL ~(1 << 9) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_10PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_10PL. */ +#define MINT16_10PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT11PL >= INT16PL) или (INT11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT11PL >= INT16PL) || (INT11PL == 0) +/* Задаёт MINT16_11PL = ~(1 << 10); маска разрешённых прерываний ядра для приоритетного обработчика 16_11PL. */ +#define MINT16_11PL ~(1 << 10) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_11PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_11PL. */ +#define MINT16_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT12PL >= INT16PL) или (INT12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT12PL >= INT16PL) || (INT12PL == 0) +/* Задаёт MINT16_12PL = ~(1 << 11); маска разрешённых прерываний ядра для приоритетного обработчика 16_12PL. */ +#define MINT16_12PL ~(1 << 11) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_12PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_12PL. */ +#define MINT16_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT13PL >= INT16PL) или (INT13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT13PL >= INT16PL) || (INT13PL == 0) +/* Задаёт MINT16_13PL = ~(1 << 12); маска разрешённых прерываний ядра для приоритетного обработчика 16_13PL. */ +#define MINT16_13PL ~(1 << 12) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_13PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_13PL. */ +#define MINT16_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT14PL >= INT16PL) или (INT14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT14PL >= INT16PL) || (INT14PL == 0) +/* Задаёт MINT16_14PL = ~(1 << 13); маска разрешённых прерываний ядра для приоритетного обработчика 16_14PL. */ +#define MINT16_14PL ~(1 << 13) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_14PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_14PL. */ +#define MINT16_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (INT15PL >= INT16PL) или (INT15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (INT15PL >= INT16PL) || (INT15PL == 0) +/* Задаёт MINT16_15PL = ~(1 << 14); маска разрешённых прерываний ядра для приоритетного обработчика 16_15PL. */ +#define MINT16_15PL ~(1 << 14) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MINT16_15PL = 0xFFFF; маска разрешённых прерываний ядра для приоритетного обработчика 16_15PL. */ +#define MINT16_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MINT16_16PL = ~(1 << 15); маска разрешённых прерываний ядра для приоритетного обработчика 16_16PL. */ +#define MINT16_16PL ~(1 << 15) + +/* Задаёт MINT16 = (MINT16_1PL & MINT16_2PL & MINT16_3PL & MINT16_4PL &; маска разрешённых прерываний ядра для приоритетного обработчика 16. */ +#define MINT16 (MINT16_1PL & MINT16_2PL & MINT16_3PL & MINT16_4PL & \ + MINT16_5PL & MINT16_6PL & MINT16_7PL & MINT16_8PL & /* Продолжает список аргументов, полей или выражение MINT16_5PL & MINT16_6PL & MINT16_7PL & MINT16_8PL &; порядок элементов сохраняется. */ \ + MINT16_9PL & MINT16_10PL & MINT16_11PL & MINT16_12PL & /* Продолжает список аргументов, полей или выражение MINT16_9PL & MINT16_10PL & MINT16_11PL & MINT16_12PL &; порядок элементов сохраняется. */ \ + MINT16_13PL & MINT16_14PL & MINT16_15PL & MINT16_16PL) /* Продолжает список аргументов, полей или выражение MINT16_13PL & MINT16_14PL & MINT16_15PL & MINT16_16PL); порядок элементов сохраняется. */ +// End Of MINT16. + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG11 to MG18: + +// Beginning of MG11: +/* Условие компиляции (G12PL >= G11PL) или (G12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G12PL >= G11PL) || (G12PL == 0) +/* Задаёт MG11_12PL = ~(1 << 1); данные MG11_12PL. */ +#define MG11_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG11_12PL = 0xFFFF; данные MG11_12PL. */ +#define MG11_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (G13PL >= G11PL) или (G13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G13PL >= G11PL) || (G13PL == 0) +/* Задаёт MG11_13PL = ~(1 << 2); данные MG11_13PL. */ +#define MG11_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG11_13PL = 0xFFFF; данные MG11_13PL. */ +#define MG11_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (G14PL >= G11PL) или (G14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G14PL >= G11PL) || (G14PL == 0) +/* Задаёт MG11_14PL = ~(1 << 3); данные MG11_14PL. */ +#define MG11_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG11_14PL = 0xFFFF; данные MG11_14PL. */ +#define MG11_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (G15PL >= G11PL) или (G15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G15PL >= G11PL) || (G15PL == 0) +/* Задаёт MG11_15PL = ~(1 << 4); данные MG11_15PL. */ +#define MG11_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG11_15PL = 0xFFFF; данные MG11_15PL. */ +#define MG11_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (G16PL >= G11PL) или (G16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G16PL >= G11PL) || (G16PL == 0) +/* Задаёт MG11_16PL = ~(1 << 5); данные MG11_16PL. */ +#define MG11_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG11_16PL = 0xFFFF; данные MG11_16PL. */ +#define MG11_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (G17PL >= G11PL) или (G17PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G17PL >= G11PL) || (G17PL == 0) +/* Задаёт MG11_17PL = ~(1 << 6); данные MG11_17PL. */ +#define MG11_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG11_17PL = 0xFFFF; данные MG11_17PL. */ +#define MG11_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции (G18PL >= G11PL) или (G18PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G18PL >= G11PL) || (G18PL == 0) +/* Задаёт MG11_18PL = ~(1 << 7); данные MG11_18PL. */ +#define MG11_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG11_18PL = 0xFFFF; данные MG11_18PL. */ +#define MG11_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Задаёт MG11_11PL = 0x00FE; данные MG11_11PL. */ +#define MG11_11PL 0x00FE +/* Задаёт MG11 = (MG11_11PL & MG11_12PL & MG11_13PL & MG11_14PL &; маска разрешённых прерываний внутри группы PIE 11. */ +#define MG11 (MG11_11PL & MG11_12PL & MG11_13PL & MG11_14PL & \ + MG11_15PL & MG11_16PL & MG11_17PL & MG11_18PL) /* Продолжает список аргументов, полей или выражение MG11_15PL & MG11_16PL & MG11_17PL & MG11_18PL); порядок элементов сохраняется. */ +// End of MG11: + +// Beginning of MG12: +/* Условие компиляции (G11PL >= G12PL) или (G11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G11PL >= G12PL) || (G11PL == 0) +/* Задаёт MG12_11PL = ~(1); данные MG12_11PL. */ +#define MG12_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG12_11PL = 0xFFFF; данные MG12_11PL. */ +#define MG12_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G13PL >= G12PL) или (G13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G13PL >= G12PL) || (G13PL == 0) +/* Задаёт MG12_13PL = ~(1 << 2); данные MG12_13PL. */ +#define MG12_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG12_13PL = 0xFFFF; данные MG12_13PL. */ +#define MG12_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G14PL >= G12PL) или (G14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G14PL >= G12PL) || (G14PL == 0) +/* Задаёт MG12_14PL = ~(1 << 3); данные MG12_14PL. */ +#define MG12_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG12_14PL = 0xFFFF; данные MG12_14PL. */ +#define MG12_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G15PL >= G12PL) или (G15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G15PL >= G12PL) || (G15PL == 0) +/* Задаёт MG12_15PL = ~(1 << 4); данные MG12_15PL. */ +#define MG12_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG12_15PL = 0xFFFF; данные MG12_15PL. */ +#define MG12_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G16PL >= G12PL) или (G16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G16PL >= G12PL) || (G16PL == 0) +/* Задаёт MG12_16PL = ~(1 << 5); данные MG12_16PL. */ +#define MG12_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG12_16PL = 0xFFFF; данные MG12_16PL. */ +#define MG12_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G17PL >= G12PL) или (G17PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G17PL >= G12PL) || (G17PL == 0) +/* Задаёт MG12_17PL = ~(1 << 6); данные MG12_17PL. */ +#define MG12_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG12_17PL = 0xFFFF; данные MG12_17PL. */ +#define MG12_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G18PL >= G12PL) или (G18PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G18PL >= G12PL) || (G18PL == 0) +/* Задаёт MG12_18PL = ~(1 << 7); данные MG12_18PL. */ +#define MG12_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG12_18PL = 0xFFFF; данные MG12_18PL. */ +#define MG12_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG12_12PL = 0x00FD; данные MG12_12PL. */ +#define MG12_12PL 0x00FD +/* Задаёт MG12 = (MG12_11PL & MG12_12PL & MG12_13PL & MG12_14PL &; маска разрешённых прерываний внутри группы PIE 12. */ +#define MG12 (MG12_11PL & MG12_12PL & MG12_13PL & MG12_14PL & \ + MG12_15PL & MG12_16PL & MG12_17PL & MG12_18PL) /* Продолжает список аргументов, полей или выражение MG12_15PL & MG12_16PL & MG12_17PL & MG12_18PL); порядок элементов сохраняется. */ +// End of MG12: + +// Beginning of MG13: +/* Условие компиляции (G11PL >= G13PL) или (G11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G11PL >= G13PL) || (G11PL == 0) +/* Задаёт MG13_11PL = ~(1); данные MG13_11PL. */ +#define MG13_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG13_11PL = 0xFFFF; данные MG13_11PL. */ +#define MG13_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G12PL >= G13PL) или (G12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G12PL >= G13PL) || (G12PL == 0) +/* Задаёт MG13_12PL = ~(1 << 1); данные MG13_12PL. */ +#define MG13_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG13_12PL = 0xFFFF; данные MG13_12PL. */ +#define MG13_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G14PL >= G13PL) или (G14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G14PL >= G13PL) || (G14PL == 0) +/* Задаёт MG13_14PL = ~(1 << 3); данные MG13_14PL. */ +#define MG13_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG13_14PL = 0xFFFF; данные MG13_14PL. */ +#define MG13_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G15PL >= G13PL) или (G15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G15PL >= G13PL) || (G15PL == 0) +/* Задаёт MG13_15PL = ~(1 << 4); данные MG13_15PL. */ +#define MG13_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG13_15PL = 0xFFFF; данные MG13_15PL. */ +#define MG13_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G16PL >= G13PL) или (G16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G16PL >= G13PL) || (G16PL == 0) +/* Задаёт MG13_16PL = ~(1 << 5); данные MG13_16PL. */ +#define MG13_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG13_16PL = 0xFFFF; данные MG13_16PL. */ +#define MG13_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G17PL >= G13PL) или (G17PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G17PL >= G13PL) || (G17PL == 0) +/* Задаёт MG13_17PL = ~(1 << 6); данные MG13_17PL. */ +#define MG13_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG13_17PL = 0xFFFF; данные MG13_17PL. */ +#define MG13_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G18PL >= G13PL) или (G18PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G18PL >= G13PL) || (G18PL == 0) +/* Задаёт MG13_18PL = ~(1 << 7); данные MG13_18PL. */ +#define MG13_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG13_18PL = 0xFFFF; данные MG13_18PL. */ +#define MG13_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG13_13PL = 0x00FB; данные MG13_13PL. */ +#define MG13_13PL 0x00FB +/* Задаёт MG13 = (MG13_11PL & MG13_12PL & MG13_13PL & MG13_14PL &; маска разрешённых прерываний внутри группы PIE 13. */ +#define MG13 (MG13_11PL & MG13_12PL & MG13_13PL & MG13_14PL & \ + MG13_15PL & MG13_16PL & MG13_17PL & MG13_18PL) /* Продолжает список аргументов, полей или выражение MG13_15PL & MG13_16PL & MG13_17PL & MG13_18PL); порядок элементов сохраняется. */ +// End of MG13: + +// Beginning of MG14: +/* Условие компиляции (G11PL >= G14PL) или (G11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G11PL >= G14PL) || (G11PL == 0) +/* Задаёт MG14_11PL = ~(1); данные MG14_11PL. */ +#define MG14_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG14_11PL = 0xFFFF; данные MG14_11PL. */ +#define MG14_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G12PL >= G14PL) или (G12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G12PL >= G14PL) || (G12PL == 0) +/* Задаёт MG14_12PL = ~(1 << 1); данные MG14_12PL. */ +#define MG14_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG14_12PL = 0xFFFF; данные MG14_12PL. */ +#define MG14_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G13PL >= G14PL) или (G13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G13PL >= G14PL) || (G13PL == 0) +/* Задаёт MG14_13PL = ~(1 << 2); данные MG14_13PL. */ +#define MG14_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG14_13PL = 0xFFFF; данные MG14_13PL. */ +#define MG14_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G15PL >= G14PL) или (G15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G15PL >= G14PL) || (G15PL == 0) +/* Задаёт MG14_15PL = ~(1 << 4); данные MG14_15PL. */ +#define MG14_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG14_15PL = 0xFFFF; данные MG14_15PL. */ +#define MG14_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G16PL >= G14PL) или (G16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G16PL >= G14PL) || (G16PL == 0) +/* Задаёт MG14_16PL = ~(1 << 5); данные MG14_16PL. */ +#define MG14_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG14_16PL = 0xFFFF; данные MG14_16PL. */ +#define MG14_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G17PL >= G14PL) или (G17PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G17PL >= G14PL) || (G17PL == 0) +/* Задаёт MG14_17PL = ~(1 << 6); данные MG14_17PL. */ +#define MG14_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG14_17PL = 0xFFFF; данные MG14_17PL. */ +#define MG14_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G18PL >= G14PL) или (G18PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G18PL >= G14PL) || (G18PL == 0) +/* Задаёт MG14_18PL = ~(1 << 7); данные MG14_18PL. */ +#define MG14_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG14_18PL = 0xFFFF; данные MG14_18PL. */ +#define MG14_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG14_14PL = 0x00F7; данные MG14_14PL. */ +#define MG14_14PL 0x00F7 +/* Задаёт MG14 = (MG14_11PL & MG14_12PL & MG14_13PL & MG14_14PL &; маска разрешённых прерываний внутри группы PIE 14. */ +#define MG14 (MG14_11PL & MG14_12PL & MG14_13PL & MG14_14PL & \ + MG14_15PL & MG14_16PL & MG14_17PL & MG14_18PL) /* Продолжает список аргументов, полей или выражение MG14_15PL & MG14_16PL & MG14_17PL & MG14_18PL); порядок элементов сохраняется. */ +// End of MG14: + +// Beginning of MG15: +/* Условие компиляции (G11PL >= G15PL) или (G11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G11PL >= G15PL) || (G11PL == 0) +/* Задаёт MG15_11PL = ~(1); данные MG15_11PL. */ +#define MG15_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG15_11PL = 0xFFFF; данные MG15_11PL. */ +#define MG15_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G12PL >= G15PL) или (G12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G12PL >= G15PL) || (G12PL == 0) +/* Задаёт MG15_12PL = ~(1 << 1); данные MG15_12PL. */ +#define MG15_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG15_12PL = 0xFFFF; данные MG15_12PL. */ +#define MG15_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G13PL >= G15PL) или (G13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G13PL >= G15PL) || (G13PL == 0) +/* Задаёт MG15_13PL = ~(1 << 2); данные MG15_13PL. */ +#define MG15_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG15_13PL = 0xFFFF; данные MG15_13PL. */ +#define MG15_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G14PL >= G15PL) или (G14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G14PL >= G15PL) || (G14PL == 0) +/* Задаёт MG15_14PL = ~(1 << 3); данные MG15_14PL. */ +#define MG15_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG15_14PL = 0xFFFF; данные MG15_14PL. */ +#define MG15_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G16PL >= G15PL) или (G16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G16PL >= G15PL) || (G16PL == 0) +/* Задаёт MG15_16PL = ~(1 << 5); данные MG15_16PL. */ +#define MG15_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG15_16PL = 0xFFFF; данные MG15_16PL. */ +#define MG15_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G17PL >= G15PL) или (G17PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G17PL >= G15PL) || (G17PL == 0) +/* Задаёт MG15_17PL = ~(1 << 6); данные MG15_17PL. */ +#define MG15_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG15_17PL = 0xFFFF; данные MG15_17PL. */ +#define MG15_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G18PL >= G15PL) или (G18PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G18PL >= G15PL) || (G18PL == 0) +/* Задаёт MG15_18PL = ~(1 << 7); данные MG15_18PL. */ +#define MG15_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG15_18PL = 0xFFFF; данные MG15_18PL. */ +#define MG15_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG15_15PL = 0x00EF; данные MG15_15PL. */ +#define MG15_15PL 0x00EF +/* Задаёт MG15 = (MG15_11PL & MG15_12PL & MG15_13PL & MG15_14PL &; маска разрешённых прерываний внутри группы PIE 15. */ +#define MG15 (MG15_11PL & MG15_12PL & MG15_13PL & MG15_14PL & \ + MG15_15PL & MG15_16PL & MG15_17PL & MG15_18PL) /* Продолжает список аргументов, полей или выражение MG15_15PL & MG15_16PL & MG15_17PL & MG15_18PL); порядок элементов сохраняется. */ +// End of MG15: + +// Beginning of MG16: +/* Условие компиляции (G11PL >= G16PL) или (G11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G11PL >= G16PL) || (G11PL == 0) +/* Задаёт MG16_11PL = ~(1); данные MG16_11PL. */ +#define MG16_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG16_11PL = 0xFFFF; данные MG16_11PL. */ +#define MG16_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G12PL >= G16PL) или (G12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G12PL >= G16PL) || (G12PL == 0) +/* Задаёт MG16_12PL = ~(1 << 1); данные MG16_12PL. */ +#define MG16_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG16_12PL = 0xFFFF; данные MG16_12PL. */ +#define MG16_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G13PL >= G16PL) или (G13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G13PL >= G16PL) || (G13PL == 0) +/* Задаёт MG16_13PL = ~(1 << 2); данные MG16_13PL. */ +#define MG16_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG16_13PL = 0xFFFF; данные MG16_13PL. */ +#define MG16_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G14PL >= G16PL) или (G14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G14PL >= G16PL) || (G14PL == 0) +/* Задаёт MG16_14PL = ~(1 << 3); данные MG16_14PL. */ +#define MG16_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG16_14PL = 0xFFFF; данные MG16_14PL. */ +#define MG16_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G15PL >= G16PL) или (G15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G15PL >= G16PL) || (G15PL == 0) +/* Задаёт MG16_15PL = ~(1 << 4); данные MG16_15PL. */ +#define MG16_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG16_15PL = 0xFFFF; данные MG16_15PL. */ +#define MG16_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G17PL >= G16PL) или (G17PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G17PL >= G16PL) || (G17PL == 0) +/* Задаёт MG16_17PL = ~(1 << 6); данные MG16_17PL. */ +#define MG16_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG16_17PL = 0xFFFF; данные MG16_17PL. */ +#define MG16_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G18PL >= G16PL) или (G18PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G18PL >= G16PL) || (G18PL == 0) +/* Задаёт MG16_18PL = ~(1 << 7); данные MG16_18PL. */ +#define MG16_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG16_18PL = 0xFFFF; данные MG16_18PL. */ +#define MG16_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG16_16PL = 0x00DF; данные MG16_16PL. */ +#define MG16_16PL 0x00DF +/* Задаёт MG16 = (MG16_11PL & MG16_12PL & MG16_13PL & MG16_14PL &; маска разрешённых прерываний внутри группы PIE 16. */ +#define MG16 (MG16_11PL & MG16_12PL & MG16_13PL & MG16_14PL & \ + MG16_15PL & MG16_16PL & MG16_17PL & MG16_18PL) /* Продолжает список аргументов, полей или выражение MG16_15PL & MG16_16PL & MG16_17PL & MG16_18PL); порядок элементов сохраняется. */ +// End of MG16: + +// Beginning of MG17: +/* Условие компиляции (G11PL >= G17PL) или (G11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G11PL >= G17PL) || (G11PL == 0) +/* Задаёт MG17_11PL = ~(1); данные MG17_11PL. */ +#define MG17_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG17_11PL = 0xFFFF; данные MG17_11PL. */ +#define MG17_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G12PL >= G17PL) или (G12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G12PL >= G17PL) || (G12PL == 0) +/* Задаёт MG17_12PL = ~(1 << 1); данные MG17_12PL. */ +#define MG17_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG17_12PL = 0xFFFF; данные MG17_12PL. */ +#define MG17_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G13PL >= G17PL) или (G13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G13PL >= G17PL) || (G13PL == 0) +/* Задаёт MG17_13PL = ~(1 << 2); данные MG17_13PL. */ +#define MG17_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG17_13PL = 0xFFFF; данные MG17_13PL. */ +#define MG17_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G14PL >= G17PL) или (G14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G14PL >= G17PL) || (G14PL == 0) +/* Задаёт MG17_14PL = ~(1 << 3); данные MG17_14PL. */ +#define MG17_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG17_14PL = 0xFFFF; данные MG17_14PL. */ +#define MG17_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G15PL >= G17PL) или (G15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G15PL >= G17PL) || (G15PL == 0) +/* Задаёт MG17_15PL = ~(1 << 4); данные MG17_15PL. */ +#define MG17_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG17_15PL = 0xFFFF; данные MG17_15PL. */ +#define MG17_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G16PL >= G17PL) или (G16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G16PL >= G17PL) || (G16PL == 0) +/* Задаёт MG17_16PL = ~(1 << 5); данные MG17_16PL. */ +#define MG17_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG17_16PL = 0xFFFF; данные MG17_16PL. */ +#define MG17_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G18PL >= G17PL) или (G18PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G18PL >= G17PL) || (G18PL == 0) +/* Задаёт MG17_18PL = ~(1 << 7); данные MG17_18PL. */ +#define MG17_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG17_18PL = 0xFFFF; данные MG17_18PL. */ +#define MG17_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG17_17PL = 0x00BF; данные MG17_17PL. */ +#define MG17_17PL 0x00BF +/* Задаёт MG17 = (MG17_11PL & MG17_12PL & MG17_13PL & MG17_14PL &; маска разрешённых прерываний внутри группы PIE 17. */ +#define MG17 (MG17_11PL & MG17_12PL & MG17_13PL & MG17_14PL & \ + MG17_15PL & MG17_16PL & MG17_17PL & MG17_18PL) /* Продолжает список аргументов, полей или выражение MG17_15PL & MG17_16PL & MG17_17PL & MG17_18PL); порядок элементов сохраняется. */ +// End of MG17: + +// Beginning of MG18: +/* Условие компиляции (G11PL >= G18PL) или (G11PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G11PL >= G18PL) || (G11PL == 0) +/* Задаёт MG18_11PL = ~(1); данные MG18_11PL. */ +#define MG18_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG18_11PL = 0xFFFF; данные MG18_11PL. */ +#define MG18_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G12PL >= G18PL) или (G12PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G12PL >= G18PL) || (G12PL == 0) +/* Задаёт MG18_12PL = ~(1 << 1); данные MG18_12PL. */ +#define MG18_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG18_12PL = 0xFFFF; данные MG18_12PL. */ +#define MG18_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G13PL >= G18PL) или (G13PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G13PL >= G18PL) || (G13PL == 0) +/* Задаёт MG18_13PL = ~(1 << 2); данные MG18_13PL. */ +#define MG18_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG18_13PL = 0xFFFF; данные MG18_13PL. */ +#define MG18_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G14PL >= G18PL) или (G14PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G14PL >= G18PL) || (G14PL == 0) +/* Задаёт MG18_14PL = ~(1 << 3); данные MG18_14PL. */ +#define MG18_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG18_14PL = 0xFFFF; данные MG18_14PL. */ +#define MG18_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G15PL >= G18PL) или (G15PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G15PL >= G18PL) || (G15PL == 0) +/* Задаёт MG18_15PL = ~(1 << 4); данные MG18_15PL. */ +#define MG18_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG18_15PL = 0xFFFF; данные MG18_15PL. */ +#define MG18_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G16PL >= G18PL) или (G16PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G16PL >= G18PL) || (G16PL == 0) +/* Задаёт MG18_16PL = ~(1 << 5); данные MG18_16PL. */ +#define MG18_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG18_16PL = 0xFFFF; данные MG18_16PL. */ +#define MG18_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G17PL >= G18PL) или (G17PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G17PL >= G18PL) || (G17PL == 0) +/* Задаёт MG18_17PL = ~(1 << 6); данные MG18_17PL. */ +#define MG18_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG18_17PL = 0xFFFF; данные MG18_17PL. */ +#define MG18_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG18_18PL = 0x007F; данные MG18_18PL. */ +#define MG18_18PL 0x007F +/* Задаёт MG18 = (MG18_11PL & MG18_12PL & MG18_13PL & MG18_14PL &; маска разрешённых прерываний внутри группы PIE 18. */ +#define MG18 (MG18_11PL & MG18_12PL & MG18_13PL & MG18_14PL & \ + MG18_15PL & MG18_16PL & MG18_17PL & MG18_18PL) /* Продолжает список аргументов, полей или выражение MG18_15PL & MG18_16PL & MG18_17PL & MG18_18PL); порядок элементов сохраняется. */ +// End of MG18: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG21 to MG28: +// + +// Beginning of MG21: +/* Условие компиляции (G22PL >= G21PL) или (G22PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G22PL >= G21PL) || (G22PL == 0) +/* Задаёт MG21_12PL = ~(1 << 1); данные MG21_12PL. */ +#define MG21_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG21_12PL = 0xFFFF; данные MG21_12PL. */ +#define MG21_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G23PL >= G21PL) или (G23PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G23PL >= G21PL) || (G23PL == 0) +/* Задаёт MG21_13PL = ~(1 << 2); данные MG21_13PL. */ +#define MG21_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG21_13PL = 0xFFFF; данные MG21_13PL. */ +#define MG21_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G24PL >= G21PL) или (G24PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G24PL >= G21PL) || (G24PL == 0) +/* Задаёт MG21_14PL = ~(1 << 3); данные MG21_14PL. */ +#define MG21_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG21_14PL = 0xFFFF; данные MG21_14PL. */ +#define MG21_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G25PL >= G21PL) или (G25PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G25PL >= G21PL) || (G25PL == 0) +/* Задаёт MG21_15PL = ~(1 << 4); данные MG21_15PL. */ +#define MG21_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG21_15PL = 0xFFFF; данные MG21_15PL. */ +#define MG21_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G26PL >= G21PL) или (G26PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G26PL >= G21PL) || (G26PL == 0) +/* Задаёт MG21_16PL = ~(1 << 5); данные MG21_16PL. */ +#define MG21_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG21_16PL = 0xFFFF; данные MG21_16PL. */ +#define MG21_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G27PL >= G21PL) или (G27PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G27PL >= G21PL) || (G27PL == 0) +/* Задаёт MG21_17PL = ~(1 << 6); данные MG21_17PL. */ +#define MG21_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG21_17PL = 0xFFFF; данные MG21_17PL. */ +#define MG21_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G28PL >= G21PL) или (G28PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G28PL >= G21PL) || (G28PL == 0) +/* Задаёт MG21_18PL = ~(1 << 7); данные MG21_18PL. */ +#define MG21_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG21_18PL = 0xFFFF; данные MG21_18PL. */ +#define MG21_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG21_11PL = 0x00FE; данные MG21_11PL. */ +#define MG21_11PL 0x00FE +/* Задаёт MG21 = (MG21_11PL & MG21_12PL & MG21_13PL & MG21_14PL &; маска разрешённых прерываний внутри группы PIE 21. */ +#define MG21 (MG21_11PL & MG21_12PL & MG21_13PL & MG21_14PL & \ + MG21_15PL & MG21_16PL & MG21_17PL & MG21_18PL) /* Продолжает список аргументов, полей или выражение MG21_15PL & MG21_16PL & MG21_17PL & MG21_18PL); порядок элементов сохраняется. */ +// End of MG21: + +// Beginning of MG22: +/* Условие компиляции (G21PL >= G22PL) или (G21PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G21PL >= G22PL) || (G21PL == 0) +/* Задаёт MG22_11PL = ~(1); данные MG22_11PL. */ +#define MG22_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG22_11PL = 0xFFFF; данные MG22_11PL. */ +#define MG22_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G23PL >= G22PL) или (G23PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G23PL >= G22PL) || (G23PL == 0) +/* Задаёт MG22_13PL = ~(1 << 2); данные MG22_13PL. */ +#define MG22_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG22_13PL = 0xFFFF; данные MG22_13PL. */ +#define MG22_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G24PL >= G22PL) или (G24PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G24PL >= G22PL) || (G24PL == 0) +/* Задаёт MG22_14PL = ~(1 << 3); данные MG22_14PL. */ +#define MG22_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG22_14PL = 0xFFFF; данные MG22_14PL. */ +#define MG22_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G25PL >= G22PL) или (G25PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G25PL >= G22PL) || (G25PL == 0) +/* Задаёт MG22_15PL = ~(1 << 4); данные MG22_15PL. */ +#define MG22_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG22_15PL = 0xFFFF; данные MG22_15PL. */ +#define MG22_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G26PL >= G22PL) или (G26PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G26PL >= G22PL) || (G26PL == 0) +/* Задаёт MG22_16PL = ~(1 << 5); данные MG22_16PL. */ +#define MG22_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG22_16PL = 0xFFFF; данные MG22_16PL. */ +#define MG22_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G27PL >= G22PL) или (G27PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G27PL >= G22PL) || (G27PL == 0) +/* Задаёт MG22_17PL = ~(1 << 6); данные MG22_17PL. */ +#define MG22_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG22_17PL = 0xFFFF; данные MG22_17PL. */ +#define MG22_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G28PL >= G22PL) или (G28PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G28PL >= G22PL) || (G28PL == 0) +/* Задаёт MG22_18PL = ~(1 << 7); данные MG22_18PL. */ +#define MG22_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG22_18PL = 0xFFFF; данные MG22_18PL. */ +#define MG22_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG22_12PL = 0x00FD; данные MG22_12PL. */ +#define MG22_12PL 0x00FD +/* Задаёт MG22 = (MG22_11PL & MG22_12PL & MG22_13PL & MG22_14PL &; маска разрешённых прерываний внутри группы PIE 22. */ +#define MG22 (MG22_11PL & MG22_12PL & MG22_13PL & MG22_14PL & \ + MG22_15PL & MG22_16PL & MG22_17PL & MG22_18PL) /* Продолжает список аргументов, полей или выражение MG22_15PL & MG22_16PL & MG22_17PL & MG22_18PL); порядок элементов сохраняется. */ +// End of MG22: + +// Beginning of MG23: +/* Условие компиляции (G21PL >= G23PL) или (G21PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G21PL >= G23PL) || (G21PL == 0) +/* Задаёт MG23_11PL = ~(1); данные MG23_11PL. */ +#define MG23_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG23_11PL = 0xFFFF; данные MG23_11PL. */ +#define MG23_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G22PL >= G23PL) или (G22PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G22PL >= G23PL) || (G22PL == 0) +/* Задаёт MG23_12PL = ~(1 << 1); данные MG23_12PL. */ +#define MG23_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG23_12PL = 0xFFFF; данные MG23_12PL. */ +#define MG23_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G24PL >= G23PL) или (G24PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G24PL >= G23PL) || (G24PL == 0) +/* Задаёт MG23_14PL = ~(1 << 3); данные MG23_14PL. */ +#define MG23_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG23_14PL = 0xFFFF; данные MG23_14PL. */ +#define MG23_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G25PL >= G23PL) или (G25PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G25PL >= G23PL) || (G25PL == 0) +/* Задаёт MG23_15PL = ~(1 << 4); данные MG23_15PL. */ +#define MG23_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG23_15PL = 0xFFFF; данные MG23_15PL. */ +#define MG23_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G26PL >= G23PL) или (G26PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G26PL >= G23PL) || (G26PL == 0) +/* Задаёт MG23_16PL = ~(1 << 5); данные MG23_16PL. */ +#define MG23_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG23_16PL = 0xFFFF; данные MG23_16PL. */ +#define MG23_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G27PL >= G23PL) или (G27PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G27PL >= G23PL) || (G27PL == 0) +/* Задаёт MG23_17PL = ~(1 << 6); данные MG23_17PL. */ +#define MG23_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG23_17PL = 0xFFFF; данные MG23_17PL. */ +#define MG23_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G28PL >= G23PL) или (G28PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G28PL >= G23PL) || (G28PL == 0) +/* Задаёт MG23_18PL = ~(1 << 7); данные MG23_18PL. */ +#define MG23_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG23_18PL = 0xFFFF; данные MG23_18PL. */ +#define MG23_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG23_13PL = 0x00FB; данные MG23_13PL. */ +#define MG23_13PL 0x00FB +/* Задаёт MG23 = (MG23_11PL & MG23_12PL & MG23_13PL & MG23_14PL &; маска разрешённых прерываний внутри группы PIE 23. */ +#define MG23 (MG23_11PL & MG23_12PL & MG23_13PL & MG23_14PL & \ + MG23_15PL & MG23_16PL & MG23_17PL & MG23_18PL) /* Продолжает список аргументов, полей или выражение MG23_15PL & MG23_16PL & MG23_17PL & MG23_18PL); порядок элементов сохраняется. */ +// End of MG23: + +// Beginning of MG24: +/* Условие компиляции (G21PL >= G24PL) или (G21PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G21PL >= G24PL) || (G21PL == 0) +/* Задаёт MG24_11PL = ~(1); данные MG24_11PL. */ +#define MG24_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG24_11PL = 0xFFFF; данные MG24_11PL. */ +#define MG24_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G22PL >= G24PL) или (G22PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G22PL >= G24PL) || (G22PL == 0) +/* Задаёт MG24_12PL = ~(1 << 1); данные MG24_12PL. */ +#define MG24_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG24_12PL = 0xFFFF; данные MG24_12PL. */ +#define MG24_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G23PL >= G24PL) или (G23PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G23PL >= G24PL) || (G23PL == 0) +/* Задаёт MG24_13PL = ~(1 << 2); данные MG24_13PL. */ +#define MG24_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG24_13PL = 0xFFFF; данные MG24_13PL. */ +#define MG24_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G25PL >= G24PL) или (G25PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G25PL >= G24PL) || (G25PL == 0) +/* Задаёт MG24_15PL = ~(1 << 4); данные MG24_15PL. */ +#define MG24_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG24_15PL = 0xFFFF; данные MG24_15PL. */ +#define MG24_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G26PL >= G24PL) или (G26PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G26PL >= G24PL) || (G26PL == 0) +/* Задаёт MG24_16PL = ~(1 << 5); данные MG24_16PL. */ +#define MG24_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG24_16PL = 0xFFFF; данные MG24_16PL. */ +#define MG24_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G27PL >= G24PL) или (G27PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G27PL >= G24PL) || (G27PL == 0) +/* Задаёт MG24_17PL = ~(1 << 6); данные MG24_17PL. */ +#define MG24_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG24_17PL = 0xFFFF; данные MG24_17PL. */ +#define MG24_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G28PL >= G24PL) или (G28PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G28PL >= G24PL) || (G28PL == 0) +/* Задаёт MG24_18PL = ~(1 << 7); данные MG24_18PL. */ +#define MG24_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG24_18PL = 0xFFFF; данные MG24_18PL. */ +#define MG24_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG24_14PL = 0x00F7; данные MG24_14PL. */ +#define MG24_14PL 0x00F7 +/* Задаёт MG24 = (MG24_11PL & MG24_12PL & MG24_13PL & MG24_14PL &; маска разрешённых прерываний внутри группы PIE 24. */ +#define MG24 (MG24_11PL & MG24_12PL & MG24_13PL & MG24_14PL & \ + MG24_15PL & MG24_16PL & MG24_17PL & MG24_18PL) /* Продолжает список аргументов, полей или выражение MG24_15PL & MG24_16PL & MG24_17PL & MG24_18PL); порядок элементов сохраняется. */ +// End of MG24: + +// Beginning of MG25: +/* Условие компиляции (G21PL >= G25PL) или (G21PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G21PL >= G25PL) || (G21PL == 0) +/* Задаёт MG25_11PL = ~(1); данные MG25_11PL. */ +#define MG25_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG25_11PL = 0xFFFF; данные MG25_11PL. */ +#define MG25_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G22PL >= G25PL) или (G22PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G22PL >= G25PL) || (G22PL == 0) +/* Задаёт MG25_12PL = ~(1 << 1); данные MG25_12PL. */ +#define MG25_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG25_12PL = 0xFFFF; данные MG25_12PL. */ +#define MG25_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G23PL >= G25PL) или (G23PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G23PL >= G25PL) || (G23PL == 0) +/* Задаёт MG25_13PL = ~(1 << 2); данные MG25_13PL. */ +#define MG25_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG25_13PL = 0xFFFF; данные MG25_13PL. */ +#define MG25_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G24PL >= G25PL) или (G24PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G24PL >= G25PL) || (G24PL == 0) +/* Задаёт MG25_14PL = ~(1 << 3); данные MG25_14PL. */ +#define MG25_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG25_14PL = 0xFFFF; данные MG25_14PL. */ +#define MG25_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G26PL >= G25PL) или (G26PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G26PL >= G25PL) || (G26PL == 0) +/* Задаёт MG25_16PL = ~(1 << 5); данные MG25_16PL. */ +#define MG25_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG25_16PL = 0xFFFF; данные MG25_16PL. */ +#define MG25_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G27PL >= G25PL) или (G27PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G27PL >= G25PL) || (G27PL == 0) +/* Задаёт MG25_17PL = ~(1 << 6); данные MG25_17PL. */ +#define MG25_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG25_17PL = 0xFFFF; данные MG25_17PL. */ +#define MG25_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G28PL >= G25PL) или (G28PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G28PL >= G25PL) || (G28PL == 0) +/* Задаёт MG25_18PL = ~(1 << 7); данные MG25_18PL. */ +#define MG25_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG25_18PL = 0xFFFF; данные MG25_18PL. */ +#define MG25_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG25_15PL = 0x00EF; данные MG25_15PL. */ +#define MG25_15PL 0x00EF +/* Задаёт MG25 = (MG25_11PL & MG25_12PL & MG25_13PL & MG25_14PL &; маска разрешённых прерываний внутри группы PIE 25. */ +#define MG25 (MG25_11PL & MG25_12PL & MG25_13PL & MG25_14PL & \ + MG25_15PL & MG25_16PL & MG25_17PL & MG25_18PL) /* Продолжает список аргументов, полей или выражение MG25_15PL & MG25_16PL & MG25_17PL & MG25_18PL); порядок элементов сохраняется. */ +// End of MG25: + +// Beginning of MG26: +/* Условие компиляции (G21PL >= G26PL) или (G21PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G21PL >= G26PL) || (G21PL == 0) +/* Задаёт MG26_11PL = ~(1); данные MG26_11PL. */ +#define MG26_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG26_11PL = 0xFFFF; данные MG26_11PL. */ +#define MG26_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G22PL >= G26PL) или (G22PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G22PL >= G26PL) || (G22PL == 0) +/* Задаёт MG26_12PL = ~(1 << 1); данные MG26_12PL. */ +#define MG26_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG26_12PL = 0xFFFF; данные MG26_12PL. */ +#define MG26_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G23PL >= G26PL) или (G23PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G23PL >= G26PL) || (G23PL == 0) +/* Задаёт MG26_13PL = ~(1 << 2); данные MG26_13PL. */ +#define MG26_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG26_13PL = 0xFFFF; данные MG26_13PL. */ +#define MG26_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G24PL >= G26PL) или (G24PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G24PL >= G26PL) || (G24PL == 0) +/* Задаёт MG26_14PL = ~(1 << 3); данные MG26_14PL. */ +#define MG26_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG26_14PL = 0xFFFF; данные MG26_14PL. */ +#define MG26_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G25PL >= G26PL) или (G25PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G25PL >= G26PL) || (G25PL == 0) +/* Задаёт MG26_15PL = ~(1 << 4); данные MG26_15PL. */ +#define MG26_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG26_15PL = 0xFFFF; данные MG26_15PL. */ +#define MG26_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G27PL >= G26PL) или (G27PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G27PL >= G26PL) || (G27PL == 0) +/* Задаёт MG26_17PL = ~(1 << 6); данные MG26_17PL. */ +#define MG26_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG26_17PL = 0xFFFF; данные MG26_17PL. */ +#define MG26_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G28PL >= G26PL) или (G28PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G28PL >= G26PL) || (G28PL == 0) +/* Задаёт MG26_18PL = ~(1 << 7); данные MG26_18PL. */ +#define MG26_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG26_18PL = 0xFFFF; данные MG26_18PL. */ +#define MG26_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG26_16PL = 0x00DF; данные MG26_16PL. */ +#define MG26_16PL 0x00DF +/* Задаёт MG26 = (MG26_11PL & MG26_12PL & MG26_13PL & MG26_14PL &; маска разрешённых прерываний внутри группы PIE 26. */ +#define MG26 (MG26_11PL & MG26_12PL & MG26_13PL & MG26_14PL & \ + MG26_15PL & MG26_16PL & MG26_17PL & MG26_18PL) /* Продолжает список аргументов, полей или выражение MG26_15PL & MG26_16PL & MG26_17PL & MG26_18PL); порядок элементов сохраняется. */ +// End of MG26: + +// Beginning of MG27: +/* Условие компиляции (G21PL >= G27PL) или (G21PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G21PL >= G27PL) || (G21PL == 0) +/* Задаёт MG27_11PL = ~(1); данные MG27_11PL. */ +#define MG27_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG27_11PL = 0xFFFF; данные MG27_11PL. */ +#define MG27_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G22PL >= G27PL) или (G22PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G22PL >= G27PL) || (G22PL == 0) +/* Задаёт MG27_12PL = ~(1 << 1); данные MG27_12PL. */ +#define MG27_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG27_12PL = 0xFFFF; данные MG27_12PL. */ +#define MG27_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G23PL >= G27PL) или (G23PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G23PL >= G27PL) || (G23PL == 0) +/* Задаёт MG27_13PL = ~(1 << 2); данные MG27_13PL. */ +#define MG27_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG27_13PL = 0xFFFF; данные MG27_13PL. */ +#define MG27_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G24PL >= G27PL) или (G24PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G24PL >= G27PL) || (G24PL == 0) +/* Задаёт MG27_14PL = ~(1 << 3); данные MG27_14PL. */ +#define MG27_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG27_14PL = 0xFFFF; данные MG27_14PL. */ +#define MG27_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G25PL >= G27PL) или (G25PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G25PL >= G27PL) || (G25PL == 0) +/* Задаёт MG27_15PL = ~(1 << 4); данные MG27_15PL. */ +#define MG27_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG27_15PL = 0xFFFF; данные MG27_15PL. */ +#define MG27_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G26PL >= G27PL) или (G26PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G26PL >= G27PL) || (G26PL == 0) +/* Задаёт MG27_16PL = ~(1 << 5); данные MG27_16PL. */ +#define MG27_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG27_16PL = 0xFFFF; данные MG27_16PL. */ +#define MG27_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G28PL >= G27PL) или (G28PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G28PL >= G27PL) || (G28PL == 0) +/* Задаёт MG27_18PL = ~(1 << 7); данные MG27_18PL. */ +#define MG27_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG27_18PL = 0xFFFF; данные MG27_18PL. */ +#define MG27_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG27_17PL = 0x00BF; данные MG27_17PL. */ +#define MG27_17PL 0x00BF +/* Задаёт MG27 = (MG27_11PL & MG27_12PL & MG27_13PL & MG27_14PL &; маска разрешённых прерываний внутри группы PIE 27. */ +#define MG27 (MG27_11PL & MG27_12PL & MG27_13PL & MG27_14PL & \ + MG27_15PL & MG27_16PL & MG27_17PL & MG27_18PL) /* Продолжает список аргументов, полей или выражение MG27_15PL & MG27_16PL & MG27_17PL & MG27_18PL); порядок элементов сохраняется. */ +// End of MG27: + +// Beginning of MG28: +/* Условие компиляции (G21PL >= G28PL) или (G21PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G21PL >= G28PL) || (G21PL == 0) +/* Задаёт MG28_11PL = ~(1); данные MG28_11PL. */ +#define MG28_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG28_11PL = 0xFFFF; данные MG28_11PL. */ +#define MG28_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G22PL >= G28PL) или (G22PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G22PL >= G28PL) || (G22PL == 0) +/* Задаёт MG28_12PL = ~(1 << 1); данные MG28_12PL. */ +#define MG28_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG28_12PL = 0xFFFF; данные MG28_12PL. */ +#define MG28_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G23PL >= G28PL) или (G23PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G23PL >= G28PL) || (G23PL == 0) +/* Задаёт MG28_13PL = ~(1 << 2); данные MG28_13PL. */ +#define MG28_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG28_13PL = 0xFFFF; данные MG28_13PL. */ +#define MG28_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G24PL >= G28PL) или (G24PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G24PL >= G28PL) || (G24PL == 0) +/* Задаёт MG28_14PL = ~(1 << 3); данные MG28_14PL. */ +#define MG28_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG28_14PL = 0xFFFF; данные MG28_14PL. */ +#define MG28_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G25PL >= G28PL) или (G25PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G25PL >= G28PL) || (G25PL == 0) +/* Задаёт MG28_15PL = ~(1 << 4); данные MG28_15PL. */ +#define MG28_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG28_15PL = 0xFFFF; данные MG28_15PL. */ +#define MG28_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G26PL >= G28PL) или (G26PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G26PL >= G28PL) || (G26PL == 0) +/* Задаёт MG28_16PL = ~(1 << 5); данные MG28_16PL. */ +#define MG28_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG28_16PL = 0xFFFF; данные MG28_16PL. */ +#define MG28_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G27PL >= G28PL) или (G27PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G27PL >= G28PL) || (G27PL == 0) +/* Задаёт MG28_17PL = ~(1 << 6); данные MG28_17PL. */ +#define MG28_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG28_17PL = 0xFFFF; данные MG28_17PL. */ +#define MG28_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG28_18PL = 0x007F; данные MG28_18PL. */ +#define MG28_18PL 0x007F +/* Задаёт MG28 = (MG28_11PL & MG28_12PL & MG28_13PL & MG28_14PL &; маска разрешённых прерываний внутри группы PIE 28. */ +#define MG28 (MG28_11PL & MG28_12PL & MG28_13PL & MG28_14PL & \ + MG28_15PL & MG28_16PL & MG28_17PL & MG28_18PL) /* Продолжает список аргументов, полей или выражение MG28_15PL & MG28_16PL & MG28_17PL & MG28_18PL); порядок элементов сохраняется. */ +// End of MG28: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG31 to MG38: +// + +// Beginning of MG31: +/* Условие компиляции (G32PL >= G31PL) или (G32PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G32PL >= G31PL) || (G32PL == 0) +/* Задаёт MG31_12PL = ~(1 << 1); данные MG31_12PL. */ +#define MG31_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG31_12PL = 0xFFFF; данные MG31_12PL. */ +#define MG31_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G33PL >= G31PL) или (G33PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G33PL >= G31PL) || (G33PL == 0) +/* Задаёт MG31_13PL = ~(1 << 2); данные MG31_13PL. */ +#define MG31_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG31_13PL = 0xFFFF; данные MG31_13PL. */ +#define MG31_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G34PL >= G31PL) или (G34PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G34PL >= G31PL) || (G34PL == 0) +/* Задаёт MG31_14PL = ~(1 << 3); данные MG31_14PL. */ +#define MG31_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG31_14PL = 0xFFFF; данные MG31_14PL. */ +#define MG31_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G35PL >= G31PL) или (G35PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G35PL >= G31PL) || (G35PL == 0) +/* Задаёт MG31_15PL = ~(1 << 4); данные MG31_15PL. */ +#define MG31_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG31_15PL = 0xFFFF; данные MG31_15PL. */ +#define MG31_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G36PL >= G31PL) или (G36PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G36PL >= G31PL) || (G36PL == 0) +/* Задаёт MG31_16PL = ~(1 << 5); данные MG31_16PL. */ +#define MG31_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG31_16PL = 0xFFFF; данные MG31_16PL. */ +#define MG31_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G37PL >= G31PL) или (G37PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G37PL >= G31PL) || (G37PL == 0) +/* Задаёт MG31_17PL = ~(1 << 6); данные MG31_17PL. */ +#define MG31_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG31_17PL = 0xFFFF; данные MG31_17PL. */ +#define MG31_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G38PL >= G31PL) или (G38PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G38PL >= G31PL) || (G38PL == 0) +/* Задаёт MG31_18PL = ~(1 << 7); данные MG31_18PL. */ +#define MG31_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG31_18PL = 0xFFFF; данные MG31_18PL. */ +#define MG31_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG31_11PL = 0x00FE; данные MG31_11PL. */ +#define MG31_11PL 0x00FE +/* Задаёт MG31 = (MG31_11PL & MG31_12PL & MG31_13PL & MG31_14PL &; маска разрешённых прерываний внутри группы PIE 31. */ +#define MG31 (MG31_11PL & MG31_12PL & MG31_13PL & MG31_14PL & \ + MG31_15PL & MG31_16PL & MG31_17PL & MG31_18PL) /* Продолжает список аргументов, полей или выражение MG31_15PL & MG31_16PL & MG31_17PL & MG31_18PL); порядок элементов сохраняется. */ +// End of MG31: + +// Beginning of MG32: +/* Условие компиляции (G31PL >= G32PL) или (G31PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G31PL >= G32PL) || (G31PL == 0) +/* Задаёт MG32_11PL = ~(1); данные MG32_11PL. */ +#define MG32_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG32_11PL = 0xFFFF; данные MG32_11PL. */ +#define MG32_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G33PL >= G32PL) или (G33PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G33PL >= G32PL) || (G33PL == 0) +/* Задаёт MG32_13PL = ~(1 << 2); данные MG32_13PL. */ +#define MG32_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG32_13PL = 0xFFFF; данные MG32_13PL. */ +#define MG32_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G34PL >= G32PL) или (G34PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G34PL >= G32PL) || (G34PL == 0) +/* Задаёт MG32_14PL = ~(1 << 3); данные MG32_14PL. */ +#define MG32_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG32_14PL = 0xFFFF; данные MG32_14PL. */ +#define MG32_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G35PL >= G32PL) или (G35PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G35PL >= G32PL) || (G35PL == 0) +/* Задаёт MG32_15PL = ~(1 << 4); данные MG32_15PL. */ +#define MG32_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG32_15PL = 0xFFFF; данные MG32_15PL. */ +#define MG32_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G36PL >= G32PL) или (G36PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G36PL >= G32PL) || (G36PL == 0) +/* Задаёт MG32_16PL = ~(1 << 5); данные MG32_16PL. */ +#define MG32_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG32_16PL = 0xFFFF; данные MG32_16PL. */ +#define MG32_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G37PL >= G32PL) или (G37PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G37PL >= G32PL) || (G37PL == 0) +/* Задаёт MG32_17PL = ~(1 << 6); данные MG32_17PL. */ +#define MG32_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG32_17PL = 0xFFFF; данные MG32_17PL. */ +#define MG32_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G38PL >= G32PL) или (G38PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G38PL >= G32PL) || (G38PL == 0) +/* Задаёт MG32_18PL = ~(1 << 7); данные MG32_18PL. */ +#define MG32_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG32_18PL = 0xFFFF; данные MG32_18PL. */ +#define MG32_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG32_12PL = 0x00FD; данные MG32_12PL. */ +#define MG32_12PL 0x00FD +/* Задаёт MG32 = (MG32_11PL & MG32_12PL & MG32_13PL & MG32_14PL &; маска разрешённых прерываний внутри группы PIE 32. */ +#define MG32 (MG32_11PL & MG32_12PL & MG32_13PL & MG32_14PL & \ + MG32_15PL & MG32_16PL & MG32_17PL & MG32_18PL) /* Продолжает список аргументов, полей или выражение MG32_15PL & MG32_16PL & MG32_17PL & MG32_18PL); порядок элементов сохраняется. */ +// End of MG32: + +// Beginning of MG33: +/* Условие компиляции (G31PL >= G33PL) или (G31PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G31PL >= G33PL) || (G31PL == 0) +/* Задаёт MG33_11PL = ~(1); данные MG33_11PL. */ +#define MG33_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG33_11PL = 0xFFFF; данные MG33_11PL. */ +#define MG33_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G32PL >= G33PL) или (G32PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G32PL >= G33PL) || (G32PL == 0) +/* Задаёт MG33_12PL = ~(1 << 1); данные MG33_12PL. */ +#define MG33_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG33_12PL = 0xFFFF; данные MG33_12PL. */ +#define MG33_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G34PL >= G33PL) или (G34PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G34PL >= G33PL) || (G34PL == 0) +/* Задаёт MG33_14PL = ~(1 << 3); данные MG33_14PL. */ +#define MG33_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG33_14PL = 0xFFFF; данные MG33_14PL. */ +#define MG33_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G35PL >= G33PL) или (G35PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G35PL >= G33PL) || (G35PL == 0) +/* Задаёт MG33_15PL = ~(1 << 4); данные MG33_15PL. */ +#define MG33_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG33_15PL = 0xFFFF; данные MG33_15PL. */ +#define MG33_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G36PL >= G33PL) или (G36PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G36PL >= G33PL) || (G36PL == 0) +/* Задаёт MG33_16PL = ~(1 << 5); данные MG33_16PL. */ +#define MG33_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG33_16PL = 0xFFFF; данные MG33_16PL. */ +#define MG33_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G37PL >= G33PL) или (G37PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G37PL >= G33PL) || (G37PL == 0) +/* Задаёт MG33_17PL = ~(1 << 6); данные MG33_17PL. */ +#define MG33_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG33_17PL = 0xFFFF; данные MG33_17PL. */ +#define MG33_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G38PL >= G33PL) или (G38PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G38PL >= G33PL) || (G38PL == 0) +/* Задаёт MG33_18PL = ~(1 << 7); данные MG33_18PL. */ +#define MG33_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG33_18PL = 0xFFFF; данные MG33_18PL. */ +#define MG33_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG33_13PL = 0x00FB; данные MG33_13PL. */ +#define MG33_13PL 0x00FB +/* Задаёт MG33 = (MG33_11PL & MG33_12PL & MG33_13PL & MG33_14PL &; маска разрешённых прерываний внутри группы PIE 33. */ +#define MG33 (MG33_11PL & MG33_12PL & MG33_13PL & MG33_14PL & \ + MG33_15PL & MG33_16PL & MG33_17PL & MG33_18PL) /* Продолжает список аргументов, полей или выражение MG33_15PL & MG33_16PL & MG33_17PL & MG33_18PL); порядок элементов сохраняется. */ +// End of MG33: + +// Beginning of MG34: +/* Условие компиляции (G31PL >= G34PL) или (G31PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G31PL >= G34PL) || (G31PL == 0) +/* Задаёт MG34_11PL = ~(1); данные MG34_11PL. */ +#define MG34_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG34_11PL = 0xFFFF; данные MG34_11PL. */ +#define MG34_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G32PL >= G34PL) или (G32PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G32PL >= G34PL) || (G32PL == 0) +/* Задаёт MG34_12PL = ~(1 << 1); данные MG34_12PL. */ +#define MG34_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG34_12PL = 0xFFFF; данные MG34_12PL. */ +#define MG34_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G33PL >= G34PL) или (G33PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G33PL >= G34PL) || (G33PL == 0) +/* Задаёт MG34_13PL = ~(1 << 2); данные MG34_13PL. */ +#define MG34_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG34_13PL = 0xFFFF; данные MG34_13PL. */ +#define MG34_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G35PL >= G34PL) или (G35PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G35PL >= G34PL) || (G35PL == 0) +/* Задаёт MG34_15PL = ~(1 << 4); данные MG34_15PL. */ +#define MG34_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG34_15PL = 0xFFFF; данные MG34_15PL. */ +#define MG34_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G36PL >= G34PL) или (G36PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G36PL >= G34PL) || (G36PL == 0) +/* Задаёт MG34_16PL = ~(1 << 5); данные MG34_16PL. */ +#define MG34_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG34_16PL = 0xFFFF; данные MG34_16PL. */ +#define MG34_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G37PL >= G34PL) или (G37PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G37PL >= G34PL) || (G37PL == 0) +/* Задаёт MG34_17PL = ~(1 << 6); данные MG34_17PL. */ +#define MG34_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG34_17PL = 0xFFFF; данные MG34_17PL. */ +#define MG34_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G38PL >= G34PL) или (G38PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G38PL >= G34PL) || (G38PL == 0) +/* Задаёт MG34_18PL = ~(1 << 7); данные MG34_18PL. */ +#define MG34_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG34_18PL = 0xFFFF; данные MG34_18PL. */ +#define MG34_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG34_14PL = 0x00F7; данные MG34_14PL. */ +#define MG34_14PL 0x00F7 +/* Задаёт MG34 = (MG34_11PL & MG34_12PL & MG34_13PL & MG34_14PL &; маска разрешённых прерываний внутри группы PIE 34. */ +#define MG34 (MG34_11PL & MG34_12PL & MG34_13PL & MG34_14PL & \ + MG34_15PL & MG34_16PL & MG34_17PL & MG34_18PL) /* Продолжает список аргументов, полей или выражение MG34_15PL & MG34_16PL & MG34_17PL & MG34_18PL); порядок элементов сохраняется. */ +// End of MG34: + +// Beginning of MG35: +/* Условие компиляции (G31PL >= G35PL) или (G31PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G31PL >= G35PL) || (G31PL == 0) +/* Задаёт MG35_11PL = ~(1); данные MG35_11PL. */ +#define MG35_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG35_11PL = 0xFFFF; данные MG35_11PL. */ +#define MG35_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G32PL >= G35PL) или (G32PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G32PL >= G35PL) || (G32PL == 0) +/* Задаёт MG35_12PL = ~(1 << 1); данные MG35_12PL. */ +#define MG35_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG35_12PL = 0xFFFF; данные MG35_12PL. */ +#define MG35_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G33PL >= G35PL) или (G33PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G33PL >= G35PL) || (G33PL == 0) +/* Задаёт MG35_13PL = ~(1 << 2); данные MG35_13PL. */ +#define MG35_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG35_13PL = 0xFFFF; данные MG35_13PL. */ +#define MG35_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G34PL >= G35PL) или (G34PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G34PL >= G35PL) || (G34PL == 0) +/* Задаёт MG35_14PL = ~(1 << 3); данные MG35_14PL. */ +#define MG35_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG35_14PL = 0xFFFF; данные MG35_14PL. */ +#define MG35_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G36PL >= G35PL) или (G36PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G36PL >= G35PL) || (G36PL == 0) +/* Задаёт MG35_16PL = ~(1 << 5); данные MG35_16PL. */ +#define MG35_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG35_16PL = 0xFFFF; данные MG35_16PL. */ +#define MG35_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G37PL >= G35PL) или (G37PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G37PL >= G35PL) || (G37PL == 0) +/* Задаёт MG35_17PL = ~(1 << 6); данные MG35_17PL. */ +#define MG35_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG35_17PL = 0xFFFF; данные MG35_17PL. */ +#define MG35_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G38PL >= G35PL) или (G38PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G38PL >= G35PL) || (G38PL == 0) +/* Задаёт MG35_18PL = ~(1 << 7); данные MG35_18PL. */ +#define MG35_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG35_18PL = 0xFFFF; данные MG35_18PL. */ +#define MG35_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG35_15PL = 0x00EF; данные MG35_15PL. */ +#define MG35_15PL 0x00EF +/* Задаёт MG35 = (MG35_11PL & MG35_12PL & MG35_13PL & MG35_14PL &; маска разрешённых прерываний внутри группы PIE 35. */ +#define MG35 (MG35_11PL & MG35_12PL & MG35_13PL & MG35_14PL & \ + MG35_15PL & MG35_16PL & MG35_17PL & MG35_18PL) /* Продолжает список аргументов, полей или выражение MG35_15PL & MG35_16PL & MG35_17PL & MG35_18PL); порядок элементов сохраняется. */ +// End of MG35: + +// Beginning of MG36: +/* Условие компиляции (G31PL >= G36PL) или (G31PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G31PL >= G36PL) || (G31PL == 0) +/* Задаёт MG36_11PL = ~(1); данные MG36_11PL. */ +#define MG36_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG36_11PL = 0xFFFF; данные MG36_11PL. */ +#define MG36_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G32PL >= G36PL) или (G32PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G32PL >= G36PL) || (G32PL == 0) +/* Задаёт MG36_12PL = ~(1 << 1); данные MG36_12PL. */ +#define MG36_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG36_12PL = 0xFFFF; данные MG36_12PL. */ +#define MG36_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G33PL >= G36PL) или (G33PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G33PL >= G36PL) || (G33PL == 0) +/* Задаёт MG36_13PL = ~(1 << 2); данные MG36_13PL. */ +#define MG36_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG36_13PL = 0xFFFF; данные MG36_13PL. */ +#define MG36_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G34PL >= G36PL) или (G34PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G34PL >= G36PL) || (G34PL == 0) +/* Задаёт MG36_14PL = ~(1 << 3); данные MG36_14PL. */ +#define MG36_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG36_14PL = 0xFFFF; данные MG36_14PL. */ +#define MG36_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G35PL >= G36PL) или (G35PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G35PL >= G36PL) || (G35PL == 0) +/* Задаёт MG36_15PL = ~(1 << 4); данные MG36_15PL. */ +#define MG36_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG36_15PL = 0xFFFF; данные MG36_15PL. */ +#define MG36_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G37PL >= G36PL) или (G37PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G37PL >= G36PL) || (G37PL == 0) +/* Задаёт MG36_17PL = ~(1 << 6); данные MG36_17PL. */ +#define MG36_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG36_17PL = 0xFFFF; данные MG36_17PL. */ +#define MG36_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G38PL >= G36PL) или (G38PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G38PL >= G36PL) || (G38PL == 0) +/* Задаёт MG36_18PL = ~(1 << 7); данные MG36_18PL. */ +#define MG36_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG36_18PL = 0xFFFF; данные MG36_18PL. */ +#define MG36_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG36_16PL = 0x00DF; данные MG36_16PL. */ +#define MG36_16PL 0x00DF +/* Задаёт MG36 = (MG36_11PL & MG36_12PL & MG36_13PL & MG36_14PL &; маска разрешённых прерываний внутри группы PIE 36. */ +#define MG36 (MG36_11PL & MG36_12PL & MG36_13PL & MG36_14PL & \ + MG36_15PL & MG36_16PL & MG36_17PL & MG36_18PL) /* Продолжает список аргументов, полей или выражение MG36_15PL & MG36_16PL & MG36_17PL & MG36_18PL); порядок элементов сохраняется. */ +// End of MG36: + +// Beginning of MG37: +/* Условие компиляции (G31PL >= G37PL) или (G31PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G31PL >= G37PL) || (G31PL == 0) +/* Задаёт MG37_11PL = ~(1); данные MG37_11PL. */ +#define MG37_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG37_11PL = 0xFFFF; данные MG37_11PL. */ +#define MG37_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G32PL >= G37PL) или (G32PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G32PL >= G37PL) || (G32PL == 0) +/* Задаёт MG37_12PL = ~(1 << 1); данные MG37_12PL. */ +#define MG37_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG37_12PL = 0xFFFF; данные MG37_12PL. */ +#define MG37_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G33PL >= G37PL) или (G33PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G33PL >= G37PL) || (G33PL == 0) +/* Задаёт MG37_13PL = ~(1 << 2); данные MG37_13PL. */ +#define MG37_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG37_13PL = 0xFFFF; данные MG37_13PL. */ +#define MG37_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G34PL >= G37PL) или (G34PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G34PL >= G37PL) || (G34PL == 0) +/* Задаёт MG37_14PL = ~(1 << 3); данные MG37_14PL. */ +#define MG37_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG37_14PL = 0xFFFF; данные MG37_14PL. */ +#define MG37_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G35PL >= G37PL) или (G35PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G35PL >= G37PL) || (G35PL == 0) +/* Задаёт MG37_15PL = ~(1 << 4); данные MG37_15PL. */ +#define MG37_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG37_15PL = 0xFFFF; данные MG37_15PL. */ +#define MG37_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G36PL >= G37PL) или (G36PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G36PL >= G37PL) || (G36PL == 0) +/* Задаёт MG37_16PL = ~(1 << 5); данные MG37_16PL. */ +#define MG37_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG37_16PL = 0xFFFF; данные MG37_16PL. */ +#define MG37_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G38PL >= G37PL) или (G38PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G38PL >= G37PL) || (G38PL == 0) +/* Задаёт MG37_18PL = ~(1 << 7); данные MG37_18PL. */ +#define MG37_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG37_18PL = 0xFFFF; данные MG37_18PL. */ +#define MG37_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG37_17PL = 0x00BF; данные MG37_17PL. */ +#define MG37_17PL 0x00BF +/* Задаёт MG37 = (MG37_11PL & MG37_12PL & MG37_13PL & MG37_14PL &; маска разрешённых прерываний внутри группы PIE 37. */ +#define MG37 (MG37_11PL & MG37_12PL & MG37_13PL & MG37_14PL & \ + MG37_15PL & MG37_16PL & MG37_17PL & MG37_18PL) /* Продолжает список аргументов, полей или выражение MG37_15PL & MG37_16PL & MG37_17PL & MG37_18PL); порядок элементов сохраняется. */ +// End of MG37: + +// Beginning of MG38: +/* Условие компиляции (G31PL >= G38PL) или (G31PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G31PL >= G38PL) || (G31PL == 0) +/* Задаёт MG38_11PL = ~(1); данные MG38_11PL. */ +#define MG38_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG38_11PL = 0xFFFF; данные MG38_11PL. */ +#define MG38_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G32PL >= G38PL) или (G32PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G32PL >= G38PL) || (G32PL == 0) +/* Задаёт MG38_12PL = ~(1 << 1); данные MG38_12PL. */ +#define MG38_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG38_12PL = 0xFFFF; данные MG38_12PL. */ +#define MG38_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G33PL >= G38PL) или (G33PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G33PL >= G38PL) || (G33PL == 0) +/* Задаёт MG38_13PL = ~(1 << 2); данные MG38_13PL. */ +#define MG38_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG38_13PL = 0xFFFF; данные MG38_13PL. */ +#define MG38_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G34PL >= G38PL) или (G34PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G34PL >= G38PL) || (G34PL == 0) +/* Задаёт MG38_14PL = ~(1 << 3); данные MG38_14PL. */ +#define MG38_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG38_14PL = 0xFFFF; данные MG38_14PL. */ +#define MG38_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G35PL >= G38PL) или (G35PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G35PL >= G38PL) || (G35PL == 0) +/* Задаёт MG38_15PL = ~(1 << 4); данные MG38_15PL. */ +#define MG38_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG38_15PL = 0xFFFF; данные MG38_15PL. */ +#define MG38_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G36PL >= G38PL) или (G36PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G36PL >= G38PL) || (G36PL == 0) +/* Задаёт MG38_16PL = ~(1 << 5); данные MG38_16PL. */ +#define MG38_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG38_16PL = 0xFFFF; данные MG38_16PL. */ +#define MG38_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G37PL >= G38PL) или (G37PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G37PL >= G38PL) || (G37PL == 0) +/* Задаёт MG38_17PL = ~(1 << 6); данные MG38_17PL. */ +#define MG38_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG38_17PL = 0xFFFF; данные MG38_17PL. */ +#define MG38_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG38_18PL = 0x007F; данные MG38_18PL. */ +#define MG38_18PL 0x007F +/* Задаёт MG38 = (MG38_11PL & MG38_12PL & MG38_13PL & MG38_14PL &; маска разрешённых прерываний внутри группы PIE 38. */ +#define MG38 (MG38_11PL & MG38_12PL & MG38_13PL & MG38_14PL & \ + MG38_15PL & MG38_16PL & MG38_17PL & MG38_18PL) /* Продолжает список аргументов, полей или выражение MG38_15PL & MG38_16PL & MG38_17PL & MG38_18PL); порядок элементов сохраняется. */ +// End of MG38: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG41 to MG48: +// + +// Beginning of MG41: +/* Условие компиляции (G42PL >= G41PL) или (G42PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G42PL >= G41PL) || (G42PL == 0) +/* Задаёт MG41_12PL = ~(1 << 1); данные MG41_12PL. */ +#define MG41_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG41_12PL = 0xFFFF; данные MG41_12PL. */ +#define MG41_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G43PL >= G41PL) или (G43PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G43PL >= G41PL) || (G43PL == 0) +/* Задаёт MG41_13PL = ~(1 << 2); данные MG41_13PL. */ +#define MG41_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG41_13PL = 0xFFFF; данные MG41_13PL. */ +#define MG41_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G44PL >= G41PL) или (G44PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G44PL >= G41PL) || (G44PL == 0) +/* Задаёт MG41_14PL = ~(1 << 3); данные MG41_14PL. */ +#define MG41_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG41_14PL = 0xFFFF; данные MG41_14PL. */ +#define MG41_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G45PL >= G41PL) или (G45PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G45PL >= G41PL) || (G45PL == 0) +/* Задаёт MG41_15PL = ~(1 << 4); данные MG41_15PL. */ +#define MG41_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG41_15PL = 0xFFFF; данные MG41_15PL. */ +#define MG41_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G46PL >= G41PL) или (G46PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G46PL >= G41PL) || (G46PL == 0) +/* Задаёт MG41_16PL = ~(1 << 5); данные MG41_16PL. */ +#define MG41_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG41_16PL = 0xFFFF; данные MG41_16PL. */ +#define MG41_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G47PL >= G41PL) или (G47PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G47PL >= G41PL) || (G47PL == 0) +/* Задаёт MG41_17PL = ~(1 << 6); данные MG41_17PL. */ +#define MG41_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG41_17PL = 0xFFFF; данные MG41_17PL. */ +#define MG41_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G48PL >= G41PL) или (G48PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G48PL >= G41PL) || (G48PL == 0) +/* Задаёт MG41_18PL = ~(1 << 7); данные MG41_18PL. */ +#define MG41_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG41_18PL = 0xFFFF; данные MG41_18PL. */ +#define MG41_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG41_11PL = 0x00FE; данные MG41_11PL. */ +#define MG41_11PL 0x00FE +/* Задаёт MG41 = (MG41_11PL & MG41_12PL & MG41_13PL & MG41_14PL &; маска разрешённых прерываний внутри группы PIE 41. */ +#define MG41 (MG41_11PL & MG41_12PL & MG41_13PL & MG41_14PL & \ + MG41_15PL & MG41_16PL & MG41_17PL & MG41_18PL) /* Продолжает список аргументов, полей или выражение MG41_15PL & MG41_16PL & MG41_17PL & MG41_18PL); порядок элементов сохраняется. */ +// End of MG41: + +// Beginning of MG42: +/* Условие компиляции (G41PL >= G42PL) или (G41PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G41PL >= G42PL) || (G41PL == 0) +/* Задаёт MG42_11PL = ~(1); данные MG42_11PL. */ +#define MG42_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG42_11PL = 0xFFFF; данные MG42_11PL. */ +#define MG42_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G43PL >= G42PL) или (G43PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G43PL >= G42PL) || (G43PL == 0) +/* Задаёт MG42_13PL = ~(1 << 2); данные MG42_13PL. */ +#define MG42_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG42_13PL = 0xFFFF; данные MG42_13PL. */ +#define MG42_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G44PL >= G42PL) или (G44PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G44PL >= G42PL) || (G44PL == 0) +/* Задаёт MG42_14PL = ~(1 << 3); данные MG42_14PL. */ +#define MG42_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG42_14PL = 0xFFFF; данные MG42_14PL. */ +#define MG42_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G45PL >= G42PL) или (G45PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G45PL >= G42PL) || (G45PL == 0) +/* Задаёт MG42_15PL = ~(1 << 4); данные MG42_15PL. */ +#define MG42_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG42_15PL = 0xFFFF; данные MG42_15PL. */ +#define MG42_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G46PL >= G42PL) или (G46PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G46PL >= G42PL) || (G46PL == 0) +/* Задаёт MG42_16PL = ~(1 << 5); данные MG42_16PL. */ +#define MG42_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG42_16PL = 0xFFFF; данные MG42_16PL. */ +#define MG42_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G47PL >= G42PL) или (G47PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G47PL >= G42PL) || (G47PL == 0) +/* Задаёт MG42_17PL = ~(1 << 6); данные MG42_17PL. */ +#define MG42_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG42_17PL = 0xFFFF; данные MG42_17PL. */ +#define MG42_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G48PL >= G42PL) или (G48PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G48PL >= G42PL) || (G48PL == 0) +/* Задаёт MG42_18PL = ~(1 << 7); данные MG42_18PL. */ +#define MG42_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG42_18PL = 0xFFFF; данные MG42_18PL. */ +#define MG42_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG42_12PL = 0x00FD; данные MG42_12PL. */ +#define MG42_12PL 0x00FD +/* Задаёт MG42 = (MG42_11PL & MG42_12PL & MG42_13PL & MG42_14PL &; маска разрешённых прерываний внутри группы PIE 42. */ +#define MG42 (MG42_11PL & MG42_12PL & MG42_13PL & MG42_14PL & \ + MG42_15PL & MG42_16PL & MG42_17PL & MG42_18PL) /* Продолжает список аргументов, полей или выражение MG42_15PL & MG42_16PL & MG42_17PL & MG42_18PL); порядок элементов сохраняется. */ +// End of MG42: + +// Beginning of MG43: +/* Условие компиляции (G41PL >= G43PL) или (G41PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G41PL >= G43PL) || (G41PL == 0) +/* Задаёт MG43_11PL = ~(1); данные MG43_11PL. */ +#define MG43_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG43_11PL = 0xFFFF; данные MG43_11PL. */ +#define MG43_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G42PL >= G43PL) или (G42PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G42PL >= G43PL) || (G42PL == 0) +/* Задаёт MG43_12PL = ~(1 << 1); данные MG43_12PL. */ +#define MG43_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG43_12PL = 0xFFFF; данные MG43_12PL. */ +#define MG43_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G44PL >= G43PL) или (G44PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G44PL >= G43PL) || (G44PL == 0) +/* Задаёт MG43_14PL = ~(1 << 3); данные MG43_14PL. */ +#define MG43_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG43_14PL = 0xFFFF; данные MG43_14PL. */ +#define MG43_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G45PL >= G43PL) или (G45PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G45PL >= G43PL) || (G45PL == 0) +/* Задаёт MG43_15PL = ~(1 << 4); данные MG43_15PL. */ +#define MG43_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG43_15PL = 0xFFFF; данные MG43_15PL. */ +#define MG43_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G46PL >= G43PL) или (G46PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G46PL >= G43PL) || (G46PL == 0) +/* Задаёт MG43_16PL = ~(1 << 5); данные MG43_16PL. */ +#define MG43_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG43_16PL = 0xFFFF; данные MG43_16PL. */ +#define MG43_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G47PL >= G43PL) или (G47PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G47PL >= G43PL) || (G47PL == 0) +/* Задаёт MG43_17PL = ~(1 << 6); данные MG43_17PL. */ +#define MG43_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG43_17PL = 0xFFFF; данные MG43_17PL. */ +#define MG43_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G48PL >= G43PL) или (G48PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G48PL >= G43PL) || (G48PL == 0) +/* Задаёт MG43_18PL = ~(1 << 7); данные MG43_18PL. */ +#define MG43_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG43_18PL = 0xFFFF; данные MG43_18PL. */ +#define MG43_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG43_13PL = 0x00FB; данные MG43_13PL. */ +#define MG43_13PL 0x00FB +/* Задаёт MG43 = (MG43_11PL & MG43_12PL & MG43_13PL & MG43_14PL &; маска разрешённых прерываний внутри группы PIE 43. */ +#define MG43 (MG43_11PL & MG43_12PL & MG43_13PL & MG43_14PL & \ + MG43_15PL & MG43_16PL & MG43_17PL & MG43_18PL) /* Продолжает список аргументов, полей или выражение MG43_15PL & MG43_16PL & MG43_17PL & MG43_18PL); порядок элементов сохраняется. */ +// End of MG43: + +// Beginning of MG44: +/* Условие компиляции (G41PL >= G44PL) или (G41PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G41PL >= G44PL) || (G41PL == 0) +/* Задаёт MG44_11PL = ~(1); данные MG44_11PL. */ +#define MG44_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG44_11PL = 0xFFFF; данные MG44_11PL. */ +#define MG44_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G42PL >= G44PL) или (G42PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G42PL >= G44PL) || (G42PL == 0) +/* Задаёт MG44_12PL = ~(1 << 1); данные MG44_12PL. */ +#define MG44_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG44_12PL = 0xFFFF; данные MG44_12PL. */ +#define MG44_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G43PL >= G44PL) или (G43PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G43PL >= G44PL) || (G43PL == 0) +/* Задаёт MG44_13PL = ~(1 << 2); данные MG44_13PL. */ +#define MG44_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG44_13PL = 0xFFFF; данные MG44_13PL. */ +#define MG44_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G45PL >= G44PL) или (G45PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G45PL >= G44PL) || (G45PL == 0) +/* Задаёт MG44_15PL = ~(1 << 4); данные MG44_15PL. */ +#define MG44_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG44_15PL = 0xFFFF; данные MG44_15PL. */ +#define MG44_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G46PL >= G44PL) или (G46PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G46PL >= G44PL) || (G46PL == 0) +/* Задаёт MG44_16PL = ~(1 << 5); данные MG44_16PL. */ +#define MG44_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG44_16PL = 0xFFFF; данные MG44_16PL. */ +#define MG44_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G47PL >= G44PL) или (G47PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G47PL >= G44PL) || (G47PL == 0) +/* Задаёт MG44_17PL = ~(1 << 6); данные MG44_17PL. */ +#define MG44_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG44_17PL = 0xFFFF; данные MG44_17PL. */ +#define MG44_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G48PL >= G44PL) или (G48PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G48PL >= G44PL) || (G48PL == 0) +/* Задаёт MG44_18PL = ~(1 << 7); данные MG44_18PL. */ +#define MG44_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG44_18PL = 0xFFFF; данные MG44_18PL. */ +#define MG44_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG44_14PL = 0x00F7; данные MG44_14PL. */ +#define MG44_14PL 0x00F7 +/* Задаёт MG44 = (MG44_11PL & MG44_12PL & MG44_13PL & MG44_14PL &; маска разрешённых прерываний внутри группы PIE 44. */ +#define MG44 (MG44_11PL & MG44_12PL & MG44_13PL & MG44_14PL & \ + MG44_15PL & MG44_16PL & MG44_17PL & MG44_18PL) /* Продолжает список аргументов, полей или выражение MG44_15PL & MG44_16PL & MG44_17PL & MG44_18PL); порядок элементов сохраняется. */ +// End of MG44: + +// Beginning of MG45: +/* Условие компиляции (G41PL >= G45PL) или (G41PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G41PL >= G45PL) || (G41PL == 0) +/* Задаёт MG45_11PL = ~(1); данные MG45_11PL. */ +#define MG45_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG45_11PL = 0xFFFF; данные MG45_11PL. */ +#define MG45_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G42PL >= G45PL) или (G42PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G42PL >= G45PL) || (G42PL == 0) +/* Задаёт MG45_12PL = ~(1 << 1); данные MG45_12PL. */ +#define MG45_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG45_12PL = 0xFFFF; данные MG45_12PL. */ +#define MG45_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G43PL >= G45PL) или (G43PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G43PL >= G45PL) || (G43PL == 0) +/* Задаёт MG45_13PL = ~(1 << 2); данные MG45_13PL. */ +#define MG45_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG45_13PL = 0xFFFF; данные MG45_13PL. */ +#define MG45_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G44PL >= G45PL) или (G44PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G44PL >= G45PL) || (G44PL == 0) +/* Задаёт MG45_14PL = ~(1 << 3); данные MG45_14PL. */ +#define MG45_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG45_14PL = 0xFFFF; данные MG45_14PL. */ +#define MG45_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G46PL >= G45PL) или (G46PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G46PL >= G45PL) || (G46PL == 0) +/* Задаёт MG45_16PL = ~(1 << 5); данные MG45_16PL. */ +#define MG45_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG45_16PL = 0xFFFF; данные MG45_16PL. */ +#define MG45_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G47PL >= G45PL) или (G47PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G47PL >= G45PL) || (G47PL == 0) +/* Задаёт MG45_17PL = ~(1 << 6); данные MG45_17PL. */ +#define MG45_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG45_17PL = 0xFFFF; данные MG45_17PL. */ +#define MG45_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G48PL >= G45PL) или (G48PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G48PL >= G45PL) || (G48PL == 0) +/* Задаёт MG45_18PL = ~(1 << 7); данные MG45_18PL. */ +#define MG45_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG45_18PL = 0xFFFF; данные MG45_18PL. */ +#define MG45_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG45_15PL = 0x00EF; данные MG45_15PL. */ +#define MG45_15PL 0x00EF +/* Задаёт MG45 = (MG45_11PL & MG45_12PL & MG45_13PL & MG45_14PL &; маска разрешённых прерываний внутри группы PIE 45. */ +#define MG45 (MG45_11PL & MG45_12PL & MG45_13PL & MG45_14PL & \ + MG45_15PL & MG45_16PL & MG45_17PL & MG45_18PL) /* Продолжает список аргументов, полей или выражение MG45_15PL & MG45_16PL & MG45_17PL & MG45_18PL); порядок элементов сохраняется. */ +// End of MG45: + +// Beginning of MG46: +/* Условие компиляции (G41PL >= G46PL) или (G41PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G41PL >= G46PL) || (G41PL == 0) +/* Задаёт MG46_11PL = ~(1); данные MG46_11PL. */ +#define MG46_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG46_11PL = 0xFFFF; данные MG46_11PL. */ +#define MG46_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G42PL >= G46PL) или (G42PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G42PL >= G46PL) || (G42PL == 0) +/* Задаёт MG46_12PL = ~(1 << 1); данные MG46_12PL. */ +#define MG46_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG46_12PL = 0xFFFF; данные MG46_12PL. */ +#define MG46_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G43PL >= G46PL) или (G43PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G43PL >= G46PL) || (G43PL == 0) +/* Задаёт MG46_13PL = ~(1 << 2); данные MG46_13PL. */ +#define MG46_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG46_13PL = 0xFFFF; данные MG46_13PL. */ +#define MG46_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G44PL >= G46PL) или (G44PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G44PL >= G46PL) || (G44PL == 0) +/* Задаёт MG46_14PL = ~(1 << 3); данные MG46_14PL. */ +#define MG46_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG46_14PL = 0xFFFF; данные MG46_14PL. */ +#define MG46_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G45PL >= G46PL) или (G45PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G45PL >= G46PL) || (G45PL == 0) +/* Задаёт MG46_15PL = ~(1 << 4); данные MG46_15PL. */ +#define MG46_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG46_15PL = 0xFFFF; данные MG46_15PL. */ +#define MG46_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G47PL >= G46PL) или (G47PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G47PL >= G46PL) || (G47PL == 0) +/* Задаёт MG46_17PL = ~(1 << 6); данные MG46_17PL. */ +#define MG46_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG46_17PL = 0xFFFF; данные MG46_17PL. */ +#define MG46_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G48PL >= G46PL) или (G48PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G48PL >= G46PL) || (G48PL == 0) +/* Задаёт MG46_18PL = ~(1 << 7); данные MG46_18PL. */ +#define MG46_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG46_18PL = 0xFFFF; данные MG46_18PL. */ +#define MG46_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG46_16PL = 0x00DF; данные MG46_16PL. */ +#define MG46_16PL 0x00DF +/* Задаёт MG46 = (MG46_11PL & MG46_12PL & MG46_13PL & MG46_14PL &; маска разрешённых прерываний внутри группы PIE 46. */ +#define MG46 (MG46_11PL & MG46_12PL & MG46_13PL & MG46_14PL & \ + MG46_15PL & MG46_16PL & MG46_17PL & MG46_18PL) /* Продолжает список аргументов, полей или выражение MG46_15PL & MG46_16PL & MG46_17PL & MG46_18PL); порядок элементов сохраняется. */ +// End of MG46: + +// Beginning of MG47: +/* Условие компиляции (G41PL >= G47PL) или (G41PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G41PL >= G47PL) || (G41PL == 0) +/* Задаёт MG47_11PL = ~(1); данные MG47_11PL. */ +#define MG47_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG47_11PL = 0xFFFF; данные MG47_11PL. */ +#define MG47_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G42PL >= G47PL) или (G42PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G42PL >= G47PL) || (G42PL == 0) +/* Задаёт MG47_12PL = ~(1 << 1); данные MG47_12PL. */ +#define MG47_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG47_12PL = 0xFFFF; данные MG47_12PL. */ +#define MG47_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G43PL >= G47PL) или (G43PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G43PL >= G47PL) || (G43PL == 0) +/* Задаёт MG47_13PL = ~(1 << 2); данные MG47_13PL. */ +#define MG47_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG47_13PL = 0xFFFF; данные MG47_13PL. */ +#define MG47_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G44PL >= G47PL) или (G44PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G44PL >= G47PL) || (G44PL == 0) +/* Задаёт MG47_14PL = ~(1 << 3); данные MG47_14PL. */ +#define MG47_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG47_14PL = 0xFFFF; данные MG47_14PL. */ +#define MG47_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G45PL >= G47PL) или (G45PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G45PL >= G47PL) || (G45PL == 0) +/* Задаёт MG47_15PL = ~(1 << 4); данные MG47_15PL. */ +#define MG47_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG47_15PL = 0xFFFF; данные MG47_15PL. */ +#define MG47_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G46PL >= G47PL) или (G46PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G46PL >= G47PL) || (G46PL == 0) +/* Задаёт MG47_16PL = ~(1 << 5); данные MG47_16PL. */ +#define MG47_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG47_16PL = 0xFFFF; данные MG47_16PL. */ +#define MG47_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G48PL >= G47PL) или (G48PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G48PL >= G47PL) || (G48PL == 0) +/* Задаёт MG47_18PL = ~(1 << 7); данные MG47_18PL. */ +#define MG47_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG47_18PL = 0xFFFF; данные MG47_18PL. */ +#define MG47_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG47_17PL = 0x00BF; данные MG47_17PL. */ +#define MG47_17PL 0x00BF +/* Задаёт MG47 = (MG47_11PL & MG47_12PL & MG47_13PL & MG47_14PL &; маска разрешённых прерываний внутри группы PIE 47. */ +#define MG47 (MG47_11PL & MG47_12PL & MG47_13PL & MG47_14PL & \ + MG47_15PL & MG47_16PL & MG47_17PL & MG47_18PL) /* Продолжает список аргументов, полей или выражение MG47_15PL & MG47_16PL & MG47_17PL & MG47_18PL); порядок элементов сохраняется. */ +// End of MG47: + +// Beginning of MG48: +/* Условие компиляции (G41PL >= G48PL) или (G41PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G41PL >= G48PL) || (G41PL == 0) +/* Задаёт MG48_11PL = ~(1); данные MG48_11PL. */ +#define MG48_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG48_11PL = 0xFFFF; данные MG48_11PL. */ +#define MG48_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G42PL >= G48PL) или (G42PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G42PL >= G48PL) || (G42PL == 0) +/* Задаёт MG48_12PL = ~(1 << 1); данные MG48_12PL. */ +#define MG48_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG48_12PL = 0xFFFF; данные MG48_12PL. */ +#define MG48_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G43PL >= G48PL) или (G43PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G43PL >= G48PL) || (G43PL == 0) +/* Задаёт MG48_13PL = ~(1 << 2); данные MG48_13PL. */ +#define MG48_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG48_13PL = 0xFFFF; данные MG48_13PL. */ +#define MG48_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G44PL >= G48PL) или (G44PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G44PL >= G48PL) || (G44PL == 0) +/* Задаёт MG48_14PL = ~(1 << 3); данные MG48_14PL. */ +#define MG48_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG48_14PL = 0xFFFF; данные MG48_14PL. */ +#define MG48_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G45PL >= G48PL) или (G45PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G45PL >= G48PL) || (G45PL == 0) +/* Задаёт MG48_15PL = ~(1 << 4); данные MG48_15PL. */ +#define MG48_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG48_15PL = 0xFFFF; данные MG48_15PL. */ +#define MG48_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G46PL >= G48PL) или (G46PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G46PL >= G48PL) || (G46PL == 0) +/* Задаёт MG48_16PL = ~(1 << 5); данные MG48_16PL. */ +#define MG48_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG48_16PL = 0xFFFF; данные MG48_16PL. */ +#define MG48_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G47PL >= G48PL) или (G47PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G47PL >= G48PL) || (G47PL == 0) +/* Задаёт MG48_17PL = ~(1 << 6); данные MG48_17PL. */ +#define MG48_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG48_17PL = 0xFFFF; данные MG48_17PL. */ +#define MG48_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG48_18PL = 0x007F; данные MG48_18PL. */ +#define MG48_18PL 0x007F +/* Задаёт MG48 = (MG48_11PL & MG48_12PL & MG48_13PL & MG48_14PL &; маска разрешённых прерываний внутри группы PIE 48. */ +#define MG48 (MG48_11PL & MG48_12PL & MG48_13PL & MG48_14PL & \ + MG48_15PL & MG48_16PL & MG48_17PL & MG48_18PL) /* Продолжает список аргументов, полей или выражение MG48_15PL & MG48_16PL & MG48_17PL & MG48_18PL); порядок элементов сохраняется. */ +// End of MG48: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG51 to MG58: +// + +// Beginning of MG51: +/* Условие компиляции (G52PL >= G51PL) или (G52PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G52PL >= G51PL) || (G52PL == 0) +/* Задаёт MG51_12PL = ~(1 << 1); данные MG51_12PL. */ +#define MG51_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG51_12PL = 0xFFFF; данные MG51_12PL. */ +#define MG51_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G53PL >= G51PL) или (G53PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G53PL >= G51PL) || (G53PL == 0) +/* Задаёт MG51_13PL = ~(1 << 2); данные MG51_13PL. */ +#define MG51_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG51_13PL = 0xFFFF; данные MG51_13PL. */ +#define MG51_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G54PL >= G51PL) или (G54PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G54PL >= G51PL) || (G54PL == 0) +/* Задаёт MG51_14PL = ~(1 << 3); данные MG51_14PL. */ +#define MG51_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG51_14PL = 0xFFFF; данные MG51_14PL. */ +#define MG51_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G55PL >= G51PL) или (G55PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G55PL >= G51PL) || (G55PL == 0) +/* Задаёт MG51_15PL = ~(1 << 4); данные MG51_15PL. */ +#define MG51_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG51_15PL = 0xFFFF; данные MG51_15PL. */ +#define MG51_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G56PL >= G51PL) или (G56PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G56PL >= G51PL) || (G56PL == 0) +/* Задаёт MG51_16PL = ~(1 << 5); данные MG51_16PL. */ +#define MG51_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG51_16PL = 0xFFFF; данные MG51_16PL. */ +#define MG51_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G57PL >= G51PL) или (G57PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G57PL >= G51PL) || (G57PL == 0) +/* Задаёт MG51_17PL = ~(1 << 6); данные MG51_17PL. */ +#define MG51_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG51_17PL = 0xFFFF; данные MG51_17PL. */ +#define MG51_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G58PL >= G51PL) или (G58PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G58PL >= G51PL) || (G58PL == 0) +/* Задаёт MG51_18PL = ~(1 << 7); данные MG51_18PL. */ +#define MG51_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG51_18PL = 0xFFFF; данные MG51_18PL. */ +#define MG51_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG51_11PL = 0x00FE; данные MG51_11PL. */ +#define MG51_11PL 0x00FE +/* Задаёт MG51 = (MG51_11PL & MG51_12PL & MG51_13PL & MG51_14PL &; маска разрешённых прерываний внутри группы PIE 51. */ +#define MG51 (MG51_11PL & MG51_12PL & MG51_13PL & MG51_14PL & \ + MG51_15PL & MG51_16PL & MG51_17PL & MG51_18PL) /* Продолжает список аргументов, полей или выражение MG51_15PL & MG51_16PL & MG51_17PL & MG51_18PL); порядок элементов сохраняется. */ +// End of MG51: + +// Beginning of MG52: +/* Условие компиляции (G51PL >= G52PL) или (G51PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G51PL >= G52PL) || (G51PL == 0) +/* Задаёт MG52_11PL = ~(1); данные MG52_11PL. */ +#define MG52_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG52_11PL = 0xFFFF; данные MG52_11PL. */ +#define MG52_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G53PL >= G52PL) или (G53PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G53PL >= G52PL) || (G53PL == 0) +/* Задаёт MG52_13PL = ~(1 << 2); данные MG52_13PL. */ +#define MG52_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG52_13PL = 0xFFFF; данные MG52_13PL. */ +#define MG52_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G54PL >= G52PL) или (G54PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G54PL >= G52PL) || (G54PL == 0) +/* Задаёт MG52_14PL = ~(1 << 3); данные MG52_14PL. */ +#define MG52_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG52_14PL = 0xFFFF; данные MG52_14PL. */ +#define MG52_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G55PL >= G52PL) или (G55PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G55PL >= G52PL) || (G55PL == 0) +/* Задаёт MG52_15PL = ~(1 << 4); данные MG52_15PL. */ +#define MG52_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG52_15PL = 0xFFFF; данные MG52_15PL. */ +#define MG52_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G56PL >= G52PL) или (G56PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G56PL >= G52PL) || (G56PL == 0) +/* Задаёт MG52_16PL = ~(1 << 5); данные MG52_16PL. */ +#define MG52_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG52_16PL = 0xFFFF; данные MG52_16PL. */ +#define MG52_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G57PL >= G52PL) или (G57PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G57PL >= G52PL) || (G57PL == 0) +/* Задаёт MG52_17PL = ~(1 << 6); данные MG52_17PL. */ +#define MG52_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG52_17PL = 0xFFFF; данные MG52_17PL. */ +#define MG52_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G58PL >= G52PL) или (G58PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G58PL >= G52PL) || (G58PL == 0) +/* Задаёт MG52_18PL = ~(1 << 7); данные MG52_18PL. */ +#define MG52_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG52_18PL = 0xFFFF; данные MG52_18PL. */ +#define MG52_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG52_12PL = 0x00FD; данные MG52_12PL. */ +#define MG52_12PL 0x00FD +/* Задаёт MG52 = (MG52_11PL & MG52_12PL & MG52_13PL & MG52_14PL &; маска разрешённых прерываний внутри группы PIE 52. */ +#define MG52 (MG52_11PL & MG52_12PL & MG52_13PL & MG52_14PL & \ + MG52_15PL & MG52_16PL & MG52_17PL & MG52_18PL) /* Продолжает список аргументов, полей или выражение MG52_15PL & MG52_16PL & MG52_17PL & MG52_18PL); порядок элементов сохраняется. */ +// End of MG52: + +// Beginning of MG53: +/* Условие компиляции (G51PL >= G53PL) или (G51PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G51PL >= G53PL) || (G51PL == 0) +/* Задаёт MG53_11PL = ~(1); данные MG53_11PL. */ +#define MG53_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG53_11PL = 0xFFFF; данные MG53_11PL. */ +#define MG53_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G52PL >= G53PL) или (G52PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G52PL >= G53PL) || (G52PL == 0) +/* Задаёт MG53_12PL = ~(1 << 1); данные MG53_12PL. */ +#define MG53_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG53_12PL = 0xFFFF; данные MG53_12PL. */ +#define MG53_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G54PL >= G53PL) или (G54PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G54PL >= G53PL) || (G54PL == 0) +/* Задаёт MG53_14PL = ~(1 << 3); данные MG53_14PL. */ +#define MG53_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG53_14PL = 0xFFFF; данные MG53_14PL. */ +#define MG53_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G55PL >= G53PL) или (G55PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G55PL >= G53PL) || (G55PL == 0) +/* Задаёт MG53_15PL = ~(1 << 4); данные MG53_15PL. */ +#define MG53_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG53_15PL = 0xFFFF; данные MG53_15PL. */ +#define MG53_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G56PL >= G53PL) или (G56PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G56PL >= G53PL) || (G56PL == 0) +/* Задаёт MG53_16PL = ~(1 << 5); данные MG53_16PL. */ +#define MG53_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG53_16PL = 0xFFFF; данные MG53_16PL. */ +#define MG53_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G57PL >= G53PL) или (G57PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G57PL >= G53PL) || (G57PL == 0) +/* Задаёт MG53_17PL = ~(1 << 6); данные MG53_17PL. */ +#define MG53_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG53_17PL = 0xFFFF; данные MG53_17PL. */ +#define MG53_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G58PL >= G53PL) или (G58PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G58PL >= G53PL) || (G58PL == 0) +/* Задаёт MG53_18PL = ~(1 << 7); данные MG53_18PL. */ +#define MG53_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG53_18PL = 0xFFFF; данные MG53_18PL. */ +#define MG53_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG53_13PL = 0x00FB; данные MG53_13PL. */ +#define MG53_13PL 0x00FB +/* Задаёт MG53 = (MG53_11PL & MG53_12PL & MG53_13PL & MG53_14PL &; маска разрешённых прерываний внутри группы PIE 53. */ +#define MG53 (MG53_11PL & MG53_12PL & MG53_13PL & MG53_14PL & \ + MG53_15PL & MG53_16PL & MG53_17PL & MG53_18PL) /* Продолжает список аргументов, полей или выражение MG53_15PL & MG53_16PL & MG53_17PL & MG53_18PL); порядок элементов сохраняется. */ +// End of MG53: + +// Beginning of MG54: +/* Условие компиляции (G51PL >= G54PL) или (G51PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G51PL >= G54PL) || (G51PL == 0) +/* Задаёт MG54_11PL = ~(1); данные MG54_11PL. */ +#define MG54_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG54_11PL = 0xFFFF; данные MG54_11PL. */ +#define MG54_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G52PL >= G54PL) или (G52PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G52PL >= G54PL) || (G52PL == 0) +/* Задаёт MG54_12PL = ~(1 << 1); данные MG54_12PL. */ +#define MG54_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG54_12PL = 0xFFFF; данные MG54_12PL. */ +#define MG54_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G53PL >= G54PL) или (G53PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G53PL >= G54PL) || (G53PL == 0) +/* Задаёт MG54_13PL = ~(1 << 2); данные MG54_13PL. */ +#define MG54_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG54_13PL = 0xFFFF; данные MG54_13PL. */ +#define MG54_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G55PL >= G54PL) или (G55PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G55PL >= G54PL) || (G55PL == 0) +/* Задаёт MG54_15PL = ~(1 << 4); данные MG54_15PL. */ +#define MG54_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG54_15PL = 0xFFFF; данные MG54_15PL. */ +#define MG54_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G56PL >= G54PL) или (G56PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G56PL >= G54PL) || (G56PL == 0) +/* Задаёт MG54_16PL = ~(1 << 5); данные MG54_16PL. */ +#define MG54_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG54_16PL = 0xFFFF; данные MG54_16PL. */ +#define MG54_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G57PL >= G54PL) или (G57PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G57PL >= G54PL) || (G57PL == 0) +/* Задаёт MG54_17PL = ~(1 << 6); данные MG54_17PL. */ +#define MG54_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG54_17PL = 0xFFFF; данные MG54_17PL. */ +#define MG54_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G58PL >= G54PL) или (G58PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G58PL >= G54PL) || (G58PL == 0) +/* Задаёт MG54_18PL = ~(1 << 7); данные MG54_18PL. */ +#define MG54_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG54_18PL = 0xFFFF; данные MG54_18PL. */ +#define MG54_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG54_14PL = 0x00F7; данные MG54_14PL. */ +#define MG54_14PL 0x00F7 +/* Задаёт MG54 = (MG54_11PL & MG54_12PL & MG54_13PL & MG54_14PL &; маска разрешённых прерываний внутри группы PIE 54. */ +#define MG54 (MG54_11PL & MG54_12PL & MG54_13PL & MG54_14PL & \ + MG54_15PL & MG54_16PL & MG54_17PL & MG54_18PL) /* Продолжает список аргументов, полей или выражение MG54_15PL & MG54_16PL & MG54_17PL & MG54_18PL); порядок элементов сохраняется. */ +// End of MG54: + +// Beginning of MG55: +/* Условие компиляции (G51PL >= G55PL) или (G51PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G51PL >= G55PL) || (G51PL == 0) +/* Задаёт MG55_11PL = ~(1); данные MG55_11PL. */ +#define MG55_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG55_11PL = 0xFFFF; данные MG55_11PL. */ +#define MG55_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G52PL >= G55PL) или (G52PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G52PL >= G55PL) || (G52PL == 0) +/* Задаёт MG55_12PL = ~(1 << 1); данные MG55_12PL. */ +#define MG55_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG55_12PL = 0xFFFF; данные MG55_12PL. */ +#define MG55_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G53PL >= G55PL) или (G53PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G53PL >= G55PL) || (G53PL == 0) +/* Задаёт MG55_13PL = ~(1 << 2); данные MG55_13PL. */ +#define MG55_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG55_13PL = 0xFFFF; данные MG55_13PL. */ +#define MG55_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G54PL >= G55PL) или (G54PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G54PL >= G55PL) || (G54PL == 0) +/* Задаёт MG55_14PL = ~(1 << 3); данные MG55_14PL. */ +#define MG55_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG55_14PL = 0xFFFF; данные MG55_14PL. */ +#define MG55_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G56PL >= G55PL) или (G56PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G56PL >= G55PL) || (G56PL == 0) +/* Задаёт MG55_16PL = ~(1 << 5); данные MG55_16PL. */ +#define MG55_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG55_16PL = 0xFFFF; данные MG55_16PL. */ +#define MG55_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G57PL >= G55PL) или (G57PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G57PL >= G55PL) || (G57PL == 0) +/* Задаёт MG55_17PL = ~(1 << 6); данные MG55_17PL. */ +#define MG55_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG55_17PL = 0xFFFF; данные MG55_17PL. */ +#define MG55_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G58PL >= G55PL) или (G58PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G58PL >= G55PL) || (G58PL == 0) +/* Задаёт MG55_18PL = ~(1 << 7); данные MG55_18PL. */ +#define MG55_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG55_18PL = 0xFFFF; данные MG55_18PL. */ +#define MG55_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG55_15PL = 0x00EF; данные MG55_15PL. */ +#define MG55_15PL 0x00EF +/* Задаёт MG55 = (MG55_11PL & MG55_12PL & MG55_13PL & MG55_14PL &; маска разрешённых прерываний внутри группы PIE 55. */ +#define MG55 (MG55_11PL & MG55_12PL & MG55_13PL & MG55_14PL & \ + MG55_15PL & MG55_16PL & MG55_17PL & MG55_18PL) /* Продолжает список аргументов, полей или выражение MG55_15PL & MG55_16PL & MG55_17PL & MG55_18PL); порядок элементов сохраняется. */ +// End of MG55: + +// Beginning of MG56: +/* Условие компиляции (G51PL >= G56PL) или (G51PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G51PL >= G56PL) || (G51PL == 0) +/* Задаёт MG56_11PL = ~(1); данные MG56_11PL. */ +#define MG56_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG56_11PL = 0xFFFF; данные MG56_11PL. */ +#define MG56_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G52PL >= G56PL) или (G52PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G52PL >= G56PL) || (G52PL == 0) +/* Задаёт MG56_12PL = ~(1 << 1); данные MG56_12PL. */ +#define MG56_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG56_12PL = 0xFFFF; данные MG56_12PL. */ +#define MG56_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G53PL >= G56PL) или (G53PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G53PL >= G56PL) || (G53PL == 0) +/* Задаёт MG56_13PL = ~(1 << 2); данные MG56_13PL. */ +#define MG56_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG56_13PL = 0xFFFF; данные MG56_13PL. */ +#define MG56_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G54PL >= G56PL) или (G54PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G54PL >= G56PL) || (G54PL == 0) +/* Задаёт MG56_14PL = ~(1 << 3); данные MG56_14PL. */ +#define MG56_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG56_14PL = 0xFFFF; данные MG56_14PL. */ +#define MG56_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G55PL >= G56PL) или (G55PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G55PL >= G56PL) || (G55PL == 0) +/* Задаёт MG56_15PL = ~(1 << 4); данные MG56_15PL. */ +#define MG56_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG56_15PL = 0xFFFF; данные MG56_15PL. */ +#define MG56_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G57PL >= G56PL) или (G57PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G57PL >= G56PL) || (G57PL == 0) +/* Задаёт MG56_17PL = ~(1 << 6); данные MG56_17PL. */ +#define MG56_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG56_17PL = 0xFFFF; данные MG56_17PL. */ +#define MG56_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G58PL >= G56PL) или (G58PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G58PL >= G56PL) || (G58PL == 0) +/* Задаёт MG56_18PL = ~(1 << 7); данные MG56_18PL. */ +#define MG56_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG56_18PL = 0xFFFF; данные MG56_18PL. */ +#define MG56_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG56_16PL = 0x00DF; данные MG56_16PL. */ +#define MG56_16PL 0x00DF +/* Задаёт MG56 = (MG56_11PL & MG56_12PL & MG56_13PL & MG56_14PL &; маска разрешённых прерываний внутри группы PIE 56. */ +#define MG56 (MG56_11PL & MG56_12PL & MG56_13PL & MG56_14PL & \ + MG56_15PL & MG56_16PL & MG56_17PL & MG56_18PL) /* Продолжает список аргументов, полей или выражение MG56_15PL & MG56_16PL & MG56_17PL & MG56_18PL); порядок элементов сохраняется. */ +// End of MG56: + +// Beginning of MG57: +/* Условие компиляции (G51PL >= G57PL) или (G51PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G51PL >= G57PL) || (G51PL == 0) +/* Задаёт MG57_11PL = ~(1); данные MG57_11PL. */ +#define MG57_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG57_11PL = 0xFFFF; данные MG57_11PL. */ +#define MG57_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G52PL >= G57PL) или (G52PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G52PL >= G57PL) || (G52PL == 0) +/* Задаёт MG57_12PL = ~(1 << 1); данные MG57_12PL. */ +#define MG57_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG57_12PL = 0xFFFF; данные MG57_12PL. */ +#define MG57_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G53PL >= G57PL) или (G53PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G53PL >= G57PL) || (G53PL == 0) +/* Задаёт MG57_13PL = ~(1 << 2); данные MG57_13PL. */ +#define MG57_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG57_13PL = 0xFFFF; данные MG57_13PL. */ +#define MG57_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G54PL >= G57PL) или (G54PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G54PL >= G57PL) || (G54PL == 0) +/* Задаёт MG57_14PL = ~(1 << 3); данные MG57_14PL. */ +#define MG57_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG57_14PL = 0xFFFF; данные MG57_14PL. */ +#define MG57_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G55PL >= G57PL) или (G55PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G55PL >= G57PL) || (G55PL == 0) +/* Задаёт MG57_15PL = ~(1 << 4); данные MG57_15PL. */ +#define MG57_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG57_15PL = 0xFFFF; данные MG57_15PL. */ +#define MG57_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G56PL >= G57PL) или (G56PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G56PL >= G57PL) || (G56PL == 0) +/* Задаёт MG57_16PL = ~(1 << 5); данные MG57_16PL. */ +#define MG57_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG57_16PL = 0xFFFF; данные MG57_16PL. */ +#define MG57_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G58PL >= G57PL) или (G58PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G58PL >= G57PL) || (G58PL == 0) +/* Задаёт MG57_18PL = ~(1 << 7); данные MG57_18PL. */ +#define MG57_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG57_18PL = 0xFFFF; данные MG57_18PL. */ +#define MG57_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG57_17PL = 0x00BF; данные MG57_17PL. */ +#define MG57_17PL 0x00BF +/* Задаёт MG57 = (MG57_11PL & MG57_12PL & MG57_13PL & MG57_14PL &; маска разрешённых прерываний внутри группы PIE 57. */ +#define MG57 (MG57_11PL & MG57_12PL & MG57_13PL & MG57_14PL & \ + MG57_15PL & MG57_16PL & MG57_17PL & MG57_18PL) /* Продолжает список аргументов, полей или выражение MG57_15PL & MG57_16PL & MG57_17PL & MG57_18PL); порядок элементов сохраняется. */ +// End of MG57: + +// Beginning of MG58: +/* Условие компиляции (G51PL >= G58PL) или (G51PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G51PL >= G58PL) || (G51PL == 0) +/* Задаёт MG58_11PL = ~(1); данные MG58_11PL. */ +#define MG58_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG58_11PL = 0xFFFF; данные MG58_11PL. */ +#define MG58_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G52PL >= G58PL) или (G52PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G52PL >= G58PL) || (G52PL == 0) +/* Задаёт MG58_12PL = ~(1 << 1); данные MG58_12PL. */ +#define MG58_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG58_12PL = 0xFFFF; данные MG58_12PL. */ +#define MG58_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G53PL >= G58PL) или (G53PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G53PL >= G58PL) || (G53PL == 0) +/* Задаёт MG58_13PL = ~(1 << 2); данные MG58_13PL. */ +#define MG58_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG58_13PL = 0xFFFF; данные MG58_13PL. */ +#define MG58_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G54PL >= G58PL) или (G54PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G54PL >= G58PL) || (G54PL == 0) +/* Задаёт MG58_14PL = ~(1 << 3); данные MG58_14PL. */ +#define MG58_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG58_14PL = 0xFFFF; данные MG58_14PL. */ +#define MG58_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G55PL >= G58PL) или (G55PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G55PL >= G58PL) || (G55PL == 0) +/* Задаёт MG58_15PL = ~(1 << 4); данные MG58_15PL. */ +#define MG58_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG58_15PL = 0xFFFF; данные MG58_15PL. */ +#define MG58_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G56PL >= G58PL) или (G56PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G56PL >= G58PL) || (G56PL == 0) +/* Задаёт MG58_16PL = ~(1 << 5); данные MG58_16PL. */ +#define MG58_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG58_16PL = 0xFFFF; данные MG58_16PL. */ +#define MG58_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G57PL >= G58PL) или (G57PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G57PL >= G58PL) || (G57PL == 0) +/* Задаёт MG58_17PL = ~(1 << 6); данные MG58_17PL. */ +#define MG58_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG58_17PL = 0xFFFF; данные MG58_17PL. */ +#define MG58_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG58_18PL = 0x007F; данные MG58_18PL. */ +#define MG58_18PL 0x007F +/* Задаёт MG58 = (MG58_11PL & MG58_12PL & MG58_13PL & MG58_14PL &; маска разрешённых прерываний внутри группы PIE 58. */ +#define MG58 (MG58_11PL & MG58_12PL & MG58_13PL & MG58_14PL & \ + MG58_15PL & MG58_16PL & MG58_17PL & MG58_18PL) /* Продолжает список аргументов, полей или выражение MG58_15PL & MG58_16PL & MG58_17PL & MG58_18PL); порядок элементов сохраняется. */ +// End of MG58: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG61 to MG68: +// + +// Beginning of MG61: +/* Условие компиляции (G62PL >= G61PL) или (G62PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G62PL >= G61PL) || (G62PL == 0) +/* Задаёт MG61_12PL = ~(1 << 1); данные MG61_12PL. */ +#define MG61_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG61_12PL = 0xFFFF; данные MG61_12PL. */ +#define MG61_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G63PL >= G61PL) или (G63PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G63PL >= G61PL) || (G63PL == 0) +/* Задаёт MG61_13PL = ~(1 << 2); данные MG61_13PL. */ +#define MG61_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG61_13PL = 0xFFFF; данные MG61_13PL. */ +#define MG61_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G64PL >= G61PL) или (G64PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G64PL >= G61PL) || (G64PL == 0) +/* Задаёт MG61_14PL = ~(1 << 3); данные MG61_14PL. */ +#define MG61_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG61_14PL = 0xFFFF; данные MG61_14PL. */ +#define MG61_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G65PL >= G61PL) или (G65PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G65PL >= G61PL) || (G65PL == 0) +/* Задаёт MG61_15PL = ~(1 << 4); данные MG61_15PL. */ +#define MG61_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG61_15PL = 0xFFFF; данные MG61_15PL. */ +#define MG61_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G66PL >= G61PL) или (G66PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G66PL >= G61PL) || (G66PL == 0) +/* Задаёт MG61_16PL = ~(1 << 5); данные MG61_16PL. */ +#define MG61_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG61_16PL = 0xFFFF; данные MG61_16PL. */ +#define MG61_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G67PL >= G61PL) или (G67PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G67PL >= G61PL) || (G67PL == 0) +/* Задаёт MG61_17PL = ~(1 << 6); данные MG61_17PL. */ +#define MG61_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG61_17PL = 0xFFFF; данные MG61_17PL. */ +#define MG61_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G68PL >= G61PL) или (G68PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G68PL >= G61PL) || (G68PL == 0) +/* Задаёт MG61_18PL = ~(1 << 7); данные MG61_18PL. */ +#define MG61_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG61_18PL = 0xFFFF; данные MG61_18PL. */ +#define MG61_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG61_11PL = 0x00FE; данные MG61_11PL. */ +#define MG61_11PL 0x00FE +/* Задаёт MG61 = (MG61_11PL & MG61_12PL & MG61_13PL & MG61_14PL &; маска разрешённых прерываний внутри группы PIE 61. */ +#define MG61 (MG61_11PL & MG61_12PL & MG61_13PL & MG61_14PL & \ + MG61_15PL & MG61_16PL & MG61_17PL & MG61_18PL) /* Продолжает список аргументов, полей или выражение MG61_15PL & MG61_16PL & MG61_17PL & MG61_18PL); порядок элементов сохраняется. */ +// End of MG61: + +// Beginning of MG62: +/* Условие компиляции (G61PL >= G62PL) или (G61PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G61PL >= G62PL) || (G61PL == 0) +/* Задаёт MG62_11PL = ~(1); данные MG62_11PL. */ +#define MG62_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG62_11PL = 0xFFFF; данные MG62_11PL. */ +#define MG62_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G63PL >= G62PL) или (G63PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G63PL >= G62PL) || (G63PL == 0) +/* Задаёт MG62_13PL = ~(1 << 2); данные MG62_13PL. */ +#define MG62_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG62_13PL = 0xFFFF; данные MG62_13PL. */ +#define MG62_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G64PL >= G62PL) или (G64PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G64PL >= G62PL) || (G64PL == 0) +/* Задаёт MG62_14PL = ~(1 << 3); данные MG62_14PL. */ +#define MG62_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG62_14PL = 0xFFFF; данные MG62_14PL. */ +#define MG62_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G65PL >= G62PL) или (G65PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G65PL >= G62PL) || (G65PL == 0) +/* Задаёт MG62_15PL = ~(1 << 4); данные MG62_15PL. */ +#define MG62_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG62_15PL = 0xFFFF; данные MG62_15PL. */ +#define MG62_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G66PL >= G62PL) или (G66PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G66PL >= G62PL) || (G66PL == 0) +/* Задаёт MG62_16PL = ~(1 << 5); данные MG62_16PL. */ +#define MG62_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG62_16PL = 0xFFFF; данные MG62_16PL. */ +#define MG62_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G67PL >= G62PL) или (G67PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G67PL >= G62PL) || (G67PL == 0) +/* Задаёт MG62_17PL = ~(1 << 6); данные MG62_17PL. */ +#define MG62_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG62_17PL = 0xFFFF; данные MG62_17PL. */ +#define MG62_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G68PL >= G62PL) или (G68PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G68PL >= G62PL) || (G68PL == 0) +/* Задаёт MG62_18PL = ~(1 << 7); данные MG62_18PL. */ +#define MG62_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG62_18PL = 0xFFFF; данные MG62_18PL. */ +#define MG62_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG62_12PL = 0x00FD; данные MG62_12PL. */ +#define MG62_12PL 0x00FD +/* Задаёт MG62 = (MG62_11PL & MG62_12PL & MG62_13PL & MG62_14PL &; маска разрешённых прерываний внутри группы PIE 62. */ +#define MG62 (MG62_11PL & MG62_12PL & MG62_13PL & MG62_14PL & \ + MG62_15PL & MG62_16PL & MG62_17PL & MG62_18PL) /* Продолжает список аргументов, полей или выражение MG62_15PL & MG62_16PL & MG62_17PL & MG62_18PL); порядок элементов сохраняется. */ +// End of MG62: + +// Beginning of MG63: +/* Условие компиляции (G61PL >= G63PL) или (G61PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G61PL >= G63PL) || (G61PL == 0) +/* Задаёт MG63_11PL = ~(1); данные MG63_11PL. */ +#define MG63_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG63_11PL = 0xFFFF; данные MG63_11PL. */ +#define MG63_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G62PL >= G63PL) или (G62PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G62PL >= G63PL) || (G62PL == 0) +/* Задаёт MG63_12PL = ~(1 << 1); данные MG63_12PL. */ +#define MG63_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG63_12PL = 0xFFFF; данные MG63_12PL. */ +#define MG63_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G64PL >= G63PL) или (G64PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G64PL >= G63PL) || (G64PL == 0) +/* Задаёт MG63_14PL = ~(1 << 3); данные MG63_14PL. */ +#define MG63_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG63_14PL = 0xFFFF; данные MG63_14PL. */ +#define MG63_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G65PL >= G63PL) или (G65PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G65PL >= G63PL) || (G65PL == 0) +/* Задаёт MG63_15PL = ~(1 << 4); данные MG63_15PL. */ +#define MG63_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG63_15PL = 0xFFFF; данные MG63_15PL. */ +#define MG63_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G66PL >= G63PL) или (G66PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G66PL >= G63PL) || (G66PL == 0) +/* Задаёт MG63_16PL = ~(1 << 5); данные MG63_16PL. */ +#define MG63_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG63_16PL = 0xFFFF; данные MG63_16PL. */ +#define MG63_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G67PL >= G63PL) или (G67PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G67PL >= G63PL) || (G67PL == 0) +/* Задаёт MG63_17PL = ~(1 << 6); данные MG63_17PL. */ +#define MG63_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG63_17PL = 0xFFFF; данные MG63_17PL. */ +#define MG63_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G68PL >= G63PL) или (G68PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G68PL >= G63PL) || (G68PL == 0) +/* Задаёт MG63_18PL = ~(1 << 7); данные MG63_18PL. */ +#define MG63_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG63_18PL = 0xFFFF; данные MG63_18PL. */ +#define MG63_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG63_13PL = 0x00FB; данные MG63_13PL. */ +#define MG63_13PL 0x00FB +/* Задаёт MG63 = (MG63_11PL & MG63_12PL & MG63_13PL & MG63_14PL &; маска разрешённых прерываний внутри группы PIE 63. */ +#define MG63 (MG63_11PL & MG63_12PL & MG63_13PL & MG63_14PL & \ + MG63_15PL & MG63_16PL & MG63_17PL & MG63_18PL) /* Продолжает список аргументов, полей или выражение MG63_15PL & MG63_16PL & MG63_17PL & MG63_18PL); порядок элементов сохраняется. */ +// End of MG63: + +// Beginning of MG64: +/* Условие компиляции (G61PL >= G64PL) или (G61PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G61PL >= G64PL) || (G61PL == 0) +/* Задаёт MG64_11PL = ~(1); данные MG64_11PL. */ +#define MG64_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG64_11PL = 0xFFFF; данные MG64_11PL. */ +#define MG64_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G62PL >= G64PL) или (G62PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G62PL >= G64PL) || (G62PL == 0) +/* Задаёт MG64_12PL = ~(1 << 1); данные MG64_12PL. */ +#define MG64_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG64_12PL = 0xFFFF; данные MG64_12PL. */ +#define MG64_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G63PL >= G64PL) или (G63PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G63PL >= G64PL) || (G63PL == 0) +/* Задаёт MG64_13PL = ~(1 << 2); данные MG64_13PL. */ +#define MG64_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG64_13PL = 0xFFFF; данные MG64_13PL. */ +#define MG64_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G65PL >= G64PL) или (G65PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G65PL >= G64PL) || (G65PL == 0) +/* Задаёт MG64_15PL = ~(1 << 4); данные MG64_15PL. */ +#define MG64_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG64_15PL = 0xFFFF; данные MG64_15PL. */ +#define MG64_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G66PL >= G64PL) или (G66PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G66PL >= G64PL) || (G66PL == 0) +/* Задаёт MG64_16PL = ~(1 << 5); данные MG64_16PL. */ +#define MG64_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG64_16PL = 0xFFFF; данные MG64_16PL. */ +#define MG64_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G67PL >= G64PL) или (G67PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G67PL >= G64PL) || (G67PL == 0) +/* Задаёт MG64_17PL = ~(1 << 6); данные MG64_17PL. */ +#define MG64_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG64_17PL = 0xFFFF; данные MG64_17PL. */ +#define MG64_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G68PL >= G64PL) или (G68PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G68PL >= G64PL) || (G68PL == 0) +/* Задаёт MG64_18PL = ~(1 << 7); данные MG64_18PL. */ +#define MG64_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG64_18PL = 0xFFFF; данные MG64_18PL. */ +#define MG64_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG64_14PL = 0x00F7; данные MG64_14PL. */ +#define MG64_14PL 0x00F7 +/* Задаёт MG64 = (MG64_11PL & MG64_12PL & MG64_13PL & MG64_14PL &; маска разрешённых прерываний внутри группы PIE 64. */ +#define MG64 (MG64_11PL & MG64_12PL & MG64_13PL & MG64_14PL & \ + MG64_15PL & MG64_16PL & MG64_17PL & MG64_18PL) /* Продолжает список аргументов, полей или выражение MG64_15PL & MG64_16PL & MG64_17PL & MG64_18PL); порядок элементов сохраняется. */ +// End of MG64: + +// Beginning of MG65: +/* Условие компиляции (G61PL >= G65PL) или (G61PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G61PL >= G65PL) || (G61PL == 0) +/* Задаёт MG65_11PL = ~(1); данные MG65_11PL. */ +#define MG65_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG65_11PL = 0xFFFF; данные MG65_11PL. */ +#define MG65_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G62PL >= G65PL) или (G62PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G62PL >= G65PL) || (G62PL == 0) +/* Задаёт MG65_12PL = ~(1 << 1); данные MG65_12PL. */ +#define MG65_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG65_12PL = 0xFFFF; данные MG65_12PL. */ +#define MG65_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G63PL >= G65PL) или (G63PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G63PL >= G65PL) || (G63PL == 0) +/* Задаёт MG65_13PL = ~(1 << 2); данные MG65_13PL. */ +#define MG65_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG65_13PL = 0xFFFF; данные MG65_13PL. */ +#define MG65_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G64PL >= G65PL) или (G64PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G64PL >= G65PL) || (G64PL == 0) +/* Задаёт MG65_14PL = ~(1 << 3); данные MG65_14PL. */ +#define MG65_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG65_14PL = 0xFFFF; данные MG65_14PL. */ +#define MG65_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G66PL >= G65PL) или (G66PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G66PL >= G65PL) || (G66PL == 0) +/* Задаёт MG65_16PL = ~(1 << 5); данные MG65_16PL. */ +#define MG65_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG65_16PL = 0xFFFF; данные MG65_16PL. */ +#define MG65_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G67PL >= G65PL) или (G67PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G67PL >= G65PL) || (G67PL == 0) +/* Задаёт MG65_17PL = ~(1 << 6); данные MG65_17PL. */ +#define MG65_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG65_17PL = 0xFFFF; данные MG65_17PL. */ +#define MG65_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G68PL >= G65PL) или (G68PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G68PL >= G65PL) || (G68PL == 0) +/* Задаёт MG65_18PL = ~(1 << 7); данные MG65_18PL. */ +#define MG65_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG65_18PL = 0xFFFF; данные MG65_18PL. */ +#define MG65_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG65_15PL = 0x00EF; данные MG65_15PL. */ +#define MG65_15PL 0x00EF +/* Задаёт MG65 = (MG65_11PL & MG65_12PL & MG65_13PL & MG65_14PL &; маска разрешённых прерываний внутри группы PIE 65. */ +#define MG65 (MG65_11PL & MG65_12PL & MG65_13PL & MG65_14PL & \ + MG65_15PL & MG65_16PL & MG65_17PL & MG65_18PL) /* Продолжает список аргументов, полей или выражение MG65_15PL & MG65_16PL & MG65_17PL & MG65_18PL); порядок элементов сохраняется. */ +// End of MG65: + +// Beginning of MG66: +/* Условие компиляции (G61PL >= G66PL) или (G61PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G61PL >= G66PL) || (G61PL == 0) +/* Задаёт MG66_11PL = ~(1); данные MG66_11PL. */ +#define MG66_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG66_11PL = 0xFFFF; данные MG66_11PL. */ +#define MG66_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G62PL >= G66PL) или (G62PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G62PL >= G66PL) || (G62PL == 0) +/* Задаёт MG66_12PL = ~(1 << 1); данные MG66_12PL. */ +#define MG66_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG66_12PL = 0xFFFF; данные MG66_12PL. */ +#define MG66_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G63PL >= G66PL) или (G63PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G63PL >= G66PL) || (G63PL == 0) +/* Задаёт MG66_13PL = ~(1 << 2); данные MG66_13PL. */ +#define MG66_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG66_13PL = 0xFFFF; данные MG66_13PL. */ +#define MG66_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G64PL >= G66PL) или (G64PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G64PL >= G66PL) || (G64PL == 0) +/* Задаёт MG66_14PL = ~(1 << 3); данные MG66_14PL. */ +#define MG66_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG66_14PL = 0xFFFF; данные MG66_14PL. */ +#define MG66_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G65PL >= G66PL) или (G65PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G65PL >= G66PL) || (G65PL == 0) +/* Задаёт MG66_15PL = ~(1 << 4); данные MG66_15PL. */ +#define MG66_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG66_15PL = 0xFFFF; данные MG66_15PL. */ +#define MG66_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G67PL >= G66PL) или (G67PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G67PL >= G66PL) || (G67PL == 0) +/* Задаёт MG66_17PL = ~(1 << 6); данные MG66_17PL. */ +#define MG66_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG66_17PL = 0xFFFF; данные MG66_17PL. */ +#define MG66_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G68PL >= G66PL) или (G68PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G68PL >= G66PL) || (G68PL == 0) +/* Задаёт MG66_18PL = ~(1 << 7); данные MG66_18PL. */ +#define MG66_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG66_18PL = 0xFFFF; данные MG66_18PL. */ +#define MG66_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG66_16PL = 0x00DF; данные MG66_16PL. */ +#define MG66_16PL 0x00DF +/* Задаёт MG66 = (MG66_11PL & MG66_12PL & MG66_13PL & MG66_14PL &; маска разрешённых прерываний внутри группы PIE 66. */ +#define MG66 (MG66_11PL & MG66_12PL & MG66_13PL & MG66_14PL & \ + MG66_15PL & MG66_16PL & MG66_17PL & MG66_18PL) /* Продолжает список аргументов, полей или выражение MG66_15PL & MG66_16PL & MG66_17PL & MG66_18PL); порядок элементов сохраняется. */ +// End of MG66: + +// Beginning of MG67: +/* Условие компиляции (G61PL >= G67PL) или (G61PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G61PL >= G67PL) || (G61PL == 0) +/* Задаёт MG67_11PL = ~(1); данные MG67_11PL. */ +#define MG67_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG67_11PL = 0xFFFF; данные MG67_11PL. */ +#define MG67_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G62PL >= G67PL) или (G62PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G62PL >= G67PL) || (G62PL == 0) +/* Задаёт MG67_12PL = ~(1 << 1); данные MG67_12PL. */ +#define MG67_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG67_12PL = 0xFFFF; данные MG67_12PL. */ +#define MG67_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G63PL >= G67PL) или (G63PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G63PL >= G67PL) || (G63PL == 0) +/* Задаёт MG67_13PL = ~(1 << 2); данные MG67_13PL. */ +#define MG67_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG67_13PL = 0xFFFF; данные MG67_13PL. */ +#define MG67_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G64PL >= G67PL) или (G64PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G64PL >= G67PL) || (G64PL == 0) +/* Задаёт MG67_14PL = ~(1 << 3); данные MG67_14PL. */ +#define MG67_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG67_14PL = 0xFFFF; данные MG67_14PL. */ +#define MG67_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G65PL >= G67PL) или (G65PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G65PL >= G67PL) || (G65PL == 0) +/* Задаёт MG67_15PL = ~(1 << 4); данные MG67_15PL. */ +#define MG67_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG67_15PL = 0xFFFF; данные MG67_15PL. */ +#define MG67_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G66PL >= G67PL) или (G66PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G66PL >= G67PL) || (G66PL == 0) +/* Задаёт MG67_16PL = ~(1 << 5); данные MG67_16PL. */ +#define MG67_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG67_16PL = 0xFFFF; данные MG67_16PL. */ +#define MG67_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G68PL >= G67PL) или (G68PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G68PL >= G67PL) || (G68PL == 0) +/* Задаёт MG67_18PL = ~(1 << 7); данные MG67_18PL. */ +#define MG67_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG67_18PL = 0xFFFF; данные MG67_18PL. */ +#define MG67_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG67_17PL = 0x00BF; данные MG67_17PL. */ +#define MG67_17PL 0x00BF +/* Задаёт MG67 = (MG67_11PL & MG67_12PL & MG67_13PL & MG67_14PL &; маска разрешённых прерываний внутри группы PIE 67. */ +#define MG67 (MG67_11PL & MG67_12PL & MG67_13PL & MG67_14PL & \ + MG67_15PL & MG67_16PL & MG67_17PL & MG67_18PL) /* Продолжает список аргументов, полей или выражение MG67_15PL & MG67_16PL & MG67_17PL & MG67_18PL); порядок элементов сохраняется. */ +// End of MG67: + +// Beginning of MG68: +/* Условие компиляции (G61PL >= G68PL) или (G61PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G61PL >= G68PL) || (G61PL == 0) +/* Задаёт MG68_11PL = ~(1); данные MG68_11PL. */ +#define MG68_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG68_11PL = 0xFFFF; данные MG68_11PL. */ +#define MG68_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G62PL >= G68PL) или (G62PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G62PL >= G68PL) || (G62PL == 0) +/* Задаёт MG68_12PL = ~(1 << 1); данные MG68_12PL. */ +#define MG68_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG68_12PL = 0xFFFF; данные MG68_12PL. */ +#define MG68_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G63PL >= G68PL) или (G63PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G63PL >= G68PL) || (G63PL == 0) +/* Задаёт MG68_13PL = ~(1 << 2); данные MG68_13PL. */ +#define MG68_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG68_13PL = 0xFFFF; данные MG68_13PL. */ +#define MG68_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G64PL >= G68PL) или (G64PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G64PL >= G68PL) || (G64PL == 0) +/* Задаёт MG68_14PL = ~(1 << 3); данные MG68_14PL. */ +#define MG68_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG68_14PL = 0xFFFF; данные MG68_14PL. */ +#define MG68_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G65PL >= G68PL) или (G65PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G65PL >= G68PL) || (G65PL == 0) +/* Задаёт MG68_15PL = ~(1 << 4); данные MG68_15PL. */ +#define MG68_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG68_15PL = 0xFFFF; данные MG68_15PL. */ +#define MG68_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G66PL >= G68PL) или (G66PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G66PL >= G68PL) || (G66PL == 0) +/* Задаёт MG68_16PL = ~(1 << 5); данные MG68_16PL. */ +#define MG68_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG68_16PL = 0xFFFF; данные MG68_16PL. */ +#define MG68_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G67PL >= G68PL) или (G67PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G67PL >= G68PL) || (G67PL == 0) +/* Задаёт MG68_17PL = ~(1 << 6); данные MG68_17PL. */ +#define MG68_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG68_17PL = 0xFFFF; данные MG68_17PL. */ +#define MG68_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG68_18PL = 0x007F; данные MG68_18PL. */ +#define MG68_18PL 0x007F +/* Задаёт MG68 = (MG68_11PL & MG68_12PL & MG68_13PL & MG68_14PL &; маска разрешённых прерываний внутри группы PIE 68. */ +#define MG68 (MG68_11PL & MG68_12PL & MG68_13PL & MG68_14PL & \ + MG68_15PL & MG68_16PL & MG68_17PL & MG68_18PL) /* Продолжает список аргументов, полей или выражение MG68_15PL & MG68_16PL & MG68_17PL & MG68_18PL); порядок элементов сохраняется. */ +// End of MG68: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG71 to MG78: +// + +// Beginning of MG71: +/* Условие компиляции (G72PL >= G71PL) или (G72PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G72PL >= G71PL) || (G72PL == 0) +/* Задаёт MG71_12PL = ~(1 << 1); данные MG71_12PL. */ +#define MG71_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG71_12PL = 0xFFFF; данные MG71_12PL. */ +#define MG71_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G73PL >= G71PL) или (G73PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G73PL >= G71PL) || (G73PL == 0) +/* Задаёт MG71_13PL = ~(1 << 2); данные MG71_13PL. */ +#define MG71_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG71_13PL = 0xFFFF; данные MG71_13PL. */ +#define MG71_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G74PL >= G71PL) или (G74PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G74PL >= G71PL) || (G74PL == 0) +/* Задаёт MG71_14PL = ~(1 << 3); данные MG71_14PL. */ +#define MG71_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG71_14PL = 0xFFFF; данные MG71_14PL. */ +#define MG71_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G75PL >= G71PL) или (G75PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G75PL >= G71PL) || (G75PL == 0) +/* Задаёт MG71_15PL = ~(1 << 4); данные MG71_15PL. */ +#define MG71_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG71_15PL = 0xFFFF; данные MG71_15PL. */ +#define MG71_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G76PL >= G71PL) или (G76PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G76PL >= G71PL) || (G76PL == 0) +/* Задаёт MG71_16PL = ~(1 << 5); данные MG71_16PL. */ +#define MG71_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG71_16PL = 0xFFFF; данные MG71_16PL. */ +#define MG71_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G77PL >= G71PL) или (G77PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G77PL >= G71PL) || (G77PL == 0) +/* Задаёт MG71_17PL = ~(1 << 6); данные MG71_17PL. */ +#define MG71_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG71_17PL = 0xFFFF; данные MG71_17PL. */ +#define MG71_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G78PL >= G71PL) или (G78PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G78PL >= G71PL) || (G78PL == 0) +/* Задаёт MG71_18PL = ~(1 << 7); данные MG71_18PL. */ +#define MG71_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG71_18PL = 0xFFFF; данные MG71_18PL. */ +#define MG71_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG71_11PL = 0x00FE; данные MG71_11PL. */ +#define MG71_11PL 0x00FE +/* Задаёт MG71 = (MG71_11PL & MG71_12PL & MG71_13PL & MG71_14PL &; маска разрешённых прерываний внутри группы PIE 71. */ +#define MG71 (MG71_11PL & MG71_12PL & MG71_13PL & MG71_14PL & \ + MG71_15PL & MG71_16PL & MG71_17PL & MG71_18PL) /* Продолжает список аргументов, полей или выражение MG71_15PL & MG71_16PL & MG71_17PL & MG71_18PL); порядок элементов сохраняется. */ +// End of MG71: + +// Beginning of MG72: +/* Условие компиляции (G71PL >= G72PL) или (G71PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G71PL >= G72PL) || (G71PL == 0) +/* Задаёт MG72_11PL = ~(1); данные MG72_11PL. */ +#define MG72_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG72_11PL = 0xFFFF; данные MG72_11PL. */ +#define MG72_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G73PL >= G72PL) или (G73PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G73PL >= G72PL) || (G73PL == 0) +/* Задаёт MG72_13PL = ~(1 << 2); данные MG72_13PL. */ +#define MG72_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG72_13PL = 0xFFFF; данные MG72_13PL. */ +#define MG72_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G74PL >= G72PL) или (G74PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G74PL >= G72PL) || (G74PL == 0) +/* Задаёт MG72_14PL = ~(1 << 3); данные MG72_14PL. */ +#define MG72_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG72_14PL = 0xFFFF; данные MG72_14PL. */ +#define MG72_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G75PL >= G72PL) или (G75PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G75PL >= G72PL) || (G75PL == 0) +/* Задаёт MG72_15PL = ~(1 << 4); данные MG72_15PL. */ +#define MG72_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG72_15PL = 0xFFFF; данные MG72_15PL. */ +#define MG72_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G76PL >= G72PL) или (G76PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G76PL >= G72PL) || (G76PL == 0) +/* Задаёт MG72_16PL = ~(1 << 5); данные MG72_16PL. */ +#define MG72_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG72_16PL = 0xFFFF; данные MG72_16PL. */ +#define MG72_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G77PL >= G72PL) или (G77PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G77PL >= G72PL) || (G77PL == 0) +/* Задаёт MG72_17PL = ~(1 << 6); данные MG72_17PL. */ +#define MG72_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG72_17PL = 0xFFFF; данные MG72_17PL. */ +#define MG72_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G78PL >= G72PL) или (G78PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G78PL >= G72PL) || (G78PL == 0) +/* Задаёт MG72_18PL = ~(1 << 7); данные MG72_18PL. */ +#define MG72_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG72_18PL = 0xFFFF; данные MG72_18PL. */ +#define MG72_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG72_12PL = 0x00FD; данные MG72_12PL. */ +#define MG72_12PL 0x00FD +/* Задаёт MG72 = (MG72_11PL & MG72_12PL & MG72_13PL & MG72_14PL &; маска разрешённых прерываний внутри группы PIE 72. */ +#define MG72 (MG72_11PL & MG72_12PL & MG72_13PL & MG72_14PL & \ + MG72_15PL & MG72_16PL & MG72_17PL & MG72_18PL) /* Продолжает список аргументов, полей или выражение MG72_15PL & MG72_16PL & MG72_17PL & MG72_18PL); порядок элементов сохраняется. */ +// End of MG72: + +// Beginning of MG73: +/* Условие компиляции (G71PL >= G73PL) или (G71PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G71PL >= G73PL) || (G71PL == 0) +/* Задаёт MG73_11PL = ~(1); данные MG73_11PL. */ +#define MG73_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG73_11PL = 0xFFFF; данные MG73_11PL. */ +#define MG73_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G72PL >= G73PL) или (G72PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G72PL >= G73PL) || (G72PL == 0) +/* Задаёт MG73_12PL = ~(1 << 1); данные MG73_12PL. */ +#define MG73_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG73_12PL = 0xFFFF; данные MG73_12PL. */ +#define MG73_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G74PL >= G73PL) или (G74PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G74PL >= G73PL) || (G74PL == 0) +/* Задаёт MG73_14PL = ~(1 << 3); данные MG73_14PL. */ +#define MG73_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG73_14PL = 0xFFFF; данные MG73_14PL. */ +#define MG73_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G75PL >= G73PL) или (G75PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G75PL >= G73PL) || (G75PL == 0) +/* Задаёт MG73_15PL = ~(1 << 4); данные MG73_15PL. */ +#define MG73_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG73_15PL = 0xFFFF; данные MG73_15PL. */ +#define MG73_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G76PL >= G73PL) или (G76PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G76PL >= G73PL) || (G76PL == 0) +/* Задаёт MG73_16PL = ~(1 << 5); данные MG73_16PL. */ +#define MG73_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG73_16PL = 0xFFFF; данные MG73_16PL. */ +#define MG73_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G77PL >= G73PL) или (G77PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G77PL >= G73PL) || (G77PL == 0) +/* Задаёт MG73_17PL = ~(1 << 6); данные MG73_17PL. */ +#define MG73_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG73_17PL = 0xFFFF; данные MG73_17PL. */ +#define MG73_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G78PL >= G73PL) или (G78PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G78PL >= G73PL) || (G78PL == 0) +/* Задаёт MG73_18PL = ~(1 << 7); данные MG73_18PL. */ +#define MG73_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG73_18PL = 0xFFFF; данные MG73_18PL. */ +#define MG73_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG73_13PL = 0x00FB; данные MG73_13PL. */ +#define MG73_13PL 0x00FB +/* Задаёт MG73 = (MG73_11PL & MG73_12PL & MG73_13PL & MG73_14PL &; маска разрешённых прерываний внутри группы PIE 73. */ +#define MG73 (MG73_11PL & MG73_12PL & MG73_13PL & MG73_14PL & \ + MG73_15PL & MG73_16PL & MG73_17PL & MG73_18PL) /* Продолжает список аргументов, полей или выражение MG73_15PL & MG73_16PL & MG73_17PL & MG73_18PL); порядок элементов сохраняется. */ +// End of MG73: + +// Beginning of MG74: +/* Условие компиляции (G71PL >= G74PL) или (G71PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G71PL >= G74PL) || (G71PL == 0) +/* Задаёт MG74_11PL = ~(1); данные MG74_11PL. */ +#define MG74_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG74_11PL = 0xFFFF; данные MG74_11PL. */ +#define MG74_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G72PL >= G74PL) или (G72PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G72PL >= G74PL) || (G72PL == 0) +/* Задаёт MG74_12PL = ~(1 << 1); данные MG74_12PL. */ +#define MG74_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG74_12PL = 0xFFFF; данные MG74_12PL. */ +#define MG74_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G73PL >= G74PL) или (G73PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G73PL >= G74PL) || (G73PL == 0) +/* Задаёт MG74_13PL = ~(1 << 2); данные MG74_13PL. */ +#define MG74_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG74_13PL = 0xFFFF; данные MG74_13PL. */ +#define MG74_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G75PL >= G74PL) или (G75PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G75PL >= G74PL) || (G75PL == 0) +/* Задаёт MG74_15PL = ~(1 << 4); данные MG74_15PL. */ +#define MG74_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG74_15PL = 0xFFFF; данные MG74_15PL. */ +#define MG74_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G76PL >= G74PL) или (G76PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G76PL >= G74PL) || (G76PL == 0) +/* Задаёт MG74_16PL = ~(1 << 5); данные MG74_16PL. */ +#define MG74_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG74_16PL = 0xFFFF; данные MG74_16PL. */ +#define MG74_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G77PL >= G74PL) или (G77PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G77PL >= G74PL) || (G77PL == 0) +/* Задаёт MG74_17PL = ~(1 << 6); данные MG74_17PL. */ +#define MG74_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG74_17PL = 0xFFFF; данные MG74_17PL. */ +#define MG74_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G78PL >= G74PL) или (G78PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G78PL >= G74PL) || (G78PL == 0) +/* Задаёт MG74_18PL = ~(1 << 7); данные MG74_18PL. */ +#define MG74_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG74_18PL = 0xFFFF; данные MG74_18PL. */ +#define MG74_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG74_14PL = 0x00F7; данные MG74_14PL. */ +#define MG74_14PL 0x00F7 +/* Задаёт MG74 = (MG74_11PL & MG74_12PL & MG74_13PL & MG74_14PL &; маска разрешённых прерываний внутри группы PIE 74. */ +#define MG74 (MG74_11PL & MG74_12PL & MG74_13PL & MG74_14PL & \ + MG74_15PL & MG74_16PL & MG74_17PL & MG74_18PL) /* Продолжает список аргументов, полей или выражение MG74_15PL & MG74_16PL & MG74_17PL & MG74_18PL); порядок элементов сохраняется. */ +// End of MG74: + +// Beginning of MG75: +/* Условие компиляции (G71PL >= G75PL) или (G71PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G71PL >= G75PL) || (G71PL == 0) +/* Задаёт MG75_11PL = ~(1); данные MG75_11PL. */ +#define MG75_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG75_11PL = 0xFFFF; данные MG75_11PL. */ +#define MG75_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G72PL >= G75PL) или (G72PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G72PL >= G75PL) || (G72PL == 0) +/* Задаёт MG75_12PL = ~(1 << 1); данные MG75_12PL. */ +#define MG75_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG75_12PL = 0xFFFF; данные MG75_12PL. */ +#define MG75_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G73PL >= G75PL) или (G73PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G73PL >= G75PL) || (G73PL == 0) +/* Задаёт MG75_13PL = ~(1 << 2); данные MG75_13PL. */ +#define MG75_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG75_13PL = 0xFFFF; данные MG75_13PL. */ +#define MG75_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G74PL >= G75PL) или (G74PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G74PL >= G75PL) || (G74PL == 0) +/* Задаёт MG75_14PL = ~(1 << 3); данные MG75_14PL. */ +#define MG75_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG75_14PL = 0xFFFF; данные MG75_14PL. */ +#define MG75_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G76PL >= G75PL) или (G76PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G76PL >= G75PL) || (G76PL == 0) +/* Задаёт MG75_16PL = ~(1 << 5); данные MG75_16PL. */ +#define MG75_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG75_16PL = 0xFFFF; данные MG75_16PL. */ +#define MG75_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G77PL >= G75PL) или (G77PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G77PL >= G75PL) || (G77PL == 0) +/* Задаёт MG75_17PL = ~(1 << 6); данные MG75_17PL. */ +#define MG75_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG75_17PL = 0xFFFF; данные MG75_17PL. */ +#define MG75_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G78PL >= G75PL) или (G78PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G78PL >= G75PL) || (G78PL == 0) +/* Задаёт MG75_18PL = ~(1 << 7); данные MG75_18PL. */ +#define MG75_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG75_18PL = 0xFFFF; данные MG75_18PL. */ +#define MG75_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG75_15PL = 0x00EF; данные MG75_15PL. */ +#define MG75_15PL 0x00EF +/* Задаёт MG75 = (MG75_11PL & MG75_12PL & MG75_13PL & MG75_14PL &; маска разрешённых прерываний внутри группы PIE 75. */ +#define MG75 (MG75_11PL & MG75_12PL & MG75_13PL & MG75_14PL & \ + MG75_15PL & MG75_16PL & MG75_17PL & MG75_18PL) /* Продолжает список аргументов, полей или выражение MG75_15PL & MG75_16PL & MG75_17PL & MG75_18PL); порядок элементов сохраняется. */ +// End of MG75: + +// Beginning of MG76: +/* Условие компиляции (G71PL >= G76PL) или (G71PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G71PL >= G76PL) || (G71PL == 0) +/* Задаёт MG76_11PL = ~(1); данные MG76_11PL. */ +#define MG76_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG76_11PL = 0xFFFF; данные MG76_11PL. */ +#define MG76_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G72PL >= G76PL) или (G72PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G72PL >= G76PL) || (G72PL == 0) +/* Задаёт MG76_12PL = ~(1 << 1); данные MG76_12PL. */ +#define MG76_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG76_12PL = 0xFFFF; данные MG76_12PL. */ +#define MG76_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G73PL >= G76PL) или (G73PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G73PL >= G76PL) || (G73PL == 0) +/* Задаёт MG76_13PL = ~(1 << 2); данные MG76_13PL. */ +#define MG76_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG76_13PL = 0xFFFF; данные MG76_13PL. */ +#define MG76_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G74PL >= G76PL) или (G74PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G74PL >= G76PL) || (G74PL == 0) +/* Задаёт MG76_14PL = ~(1 << 3); данные MG76_14PL. */ +#define MG76_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG76_14PL = 0xFFFF; данные MG76_14PL. */ +#define MG76_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G75PL >= G76PL) или (G75PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G75PL >= G76PL) || (G75PL == 0) +/* Задаёт MG76_15PL = ~(1 << 4); данные MG76_15PL. */ +#define MG76_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG76_15PL = 0xFFFF; данные MG76_15PL. */ +#define MG76_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G77PL >= G76PL) или (G77PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G77PL >= G76PL) || (G77PL == 0) +/* Задаёт MG76_17PL = ~(1 << 6); данные MG76_17PL. */ +#define MG76_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG76_17PL = 0xFFFF; данные MG76_17PL. */ +#define MG76_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G78PL >= G76PL) или (G78PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G78PL >= G76PL) || (G78PL == 0) +/* Задаёт MG76_18PL = ~(1 << 7); данные MG76_18PL. */ +#define MG76_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG76_18PL = 0xFFFF; данные MG76_18PL. */ +#define MG76_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG76_16PL = 0x00DF; данные MG76_16PL. */ +#define MG76_16PL 0x00DF +/* Задаёт MG76 = (MG76_11PL & MG76_12PL & MG76_13PL & MG76_14PL &; маска разрешённых прерываний внутри группы PIE 76. */ +#define MG76 (MG76_11PL & MG76_12PL & MG76_13PL & MG76_14PL & \ + MG76_15PL & MG76_16PL & MG76_17PL & MG76_18PL) /* Продолжает список аргументов, полей или выражение MG76_15PL & MG76_16PL & MG76_17PL & MG76_18PL); порядок элементов сохраняется. */ +// End of MG76: + +// Beginning of MG77: +/* Условие компиляции (G71PL >= G77PL) или (G71PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G71PL >= G77PL) || (G71PL == 0) +/* Задаёт MG77_11PL = ~(1); данные MG77_11PL. */ +#define MG77_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG77_11PL = 0xFFFF; данные MG77_11PL. */ +#define MG77_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G72PL >= G77PL) или (G72PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G72PL >= G77PL) || (G72PL == 0) +/* Задаёт MG77_12PL = ~(1 << 1); данные MG77_12PL. */ +#define MG77_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG77_12PL = 0xFFFF; данные MG77_12PL. */ +#define MG77_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G73PL >= G77PL) или (G73PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G73PL >= G77PL) || (G73PL == 0) +/* Задаёт MG77_13PL = ~(1 << 2); данные MG77_13PL. */ +#define MG77_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG77_13PL = 0xFFFF; данные MG77_13PL. */ +#define MG77_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G74PL >= G77PL) или (G74PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G74PL >= G77PL) || (G74PL == 0) +/* Задаёт MG77_14PL = ~(1 << 3); данные MG77_14PL. */ +#define MG77_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG77_14PL = 0xFFFF; данные MG77_14PL. */ +#define MG77_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G75PL >= G77PL) или (G75PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G75PL >= G77PL) || (G75PL == 0) +/* Задаёт MG77_15PL = ~(1 << 4); данные MG77_15PL. */ +#define MG77_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG77_15PL = 0xFFFF; данные MG77_15PL. */ +#define MG77_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G76PL >= G77PL) или (G76PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G76PL >= G77PL) || (G76PL == 0) +/* Задаёт MG77_16PL = ~(1 << 5); данные MG77_16PL. */ +#define MG77_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG77_16PL = 0xFFFF; данные MG77_16PL. */ +#define MG77_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G78PL >= G77PL) или (G78PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G78PL >= G77PL) || (G78PL == 0) +/* Задаёт MG77_18PL = ~(1 << 7); данные MG77_18PL. */ +#define MG77_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG77_18PL = 0xFFFF; данные MG77_18PL. */ +#define MG77_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG77_17PL = 0x00BF; данные MG77_17PL. */ +#define MG77_17PL 0x00BF +/* Задаёт MG77 = (MG77_11PL & MG77_12PL & MG77_13PL & MG77_14PL &; маска разрешённых прерываний внутри группы PIE 77. */ +#define MG77 (MG77_11PL & MG77_12PL & MG77_13PL & MG77_14PL & \ + MG77_15PL & MG77_16PL & MG77_17PL & MG77_18PL) /* Продолжает список аргументов, полей или выражение MG77_15PL & MG77_16PL & MG77_17PL & MG77_18PL); порядок элементов сохраняется. */ +// End of MG77: + +// Beginning of MG78: +/* Условие компиляции (G71PL >= G78PL) или (G71PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G71PL >= G78PL) || (G71PL == 0) +/* Задаёт MG78_11PL = ~(1); данные MG78_11PL. */ +#define MG78_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG78_11PL = 0xFFFF; данные MG78_11PL. */ +#define MG78_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G72PL >= G78PL) или (G72PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G72PL >= G78PL) || (G72PL == 0) +/* Задаёт MG78_12PL = ~(1 << 1); данные MG78_12PL. */ +#define MG78_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG78_12PL = 0xFFFF; данные MG78_12PL. */ +#define MG78_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G73PL >= G78PL) или (G73PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G73PL >= G78PL) || (G73PL == 0) +/* Задаёт MG78_13PL = ~(1 << 2); данные MG78_13PL. */ +#define MG78_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG78_13PL = 0xFFFF; данные MG78_13PL. */ +#define MG78_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G74PL >= G78PL) или (G74PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G74PL >= G78PL) || (G74PL == 0) +/* Задаёт MG78_14PL = ~(1 << 3); данные MG78_14PL. */ +#define MG78_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG78_14PL = 0xFFFF; данные MG78_14PL. */ +#define MG78_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G75PL >= G78PL) или (G75PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G75PL >= G78PL) || (G75PL == 0) +/* Задаёт MG78_15PL = ~(1 << 4); данные MG78_15PL. */ +#define MG78_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG78_15PL = 0xFFFF; данные MG78_15PL. */ +#define MG78_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G76PL >= G78PL) или (G76PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G76PL >= G78PL) || (G76PL == 0) +/* Задаёт MG78_16PL = ~(1 << 5); данные MG78_16PL. */ +#define MG78_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG78_16PL = 0xFFFF; данные MG78_16PL. */ +#define MG78_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G77PL >= G78PL) или (G77PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G77PL >= G78PL) || (G77PL == 0) +/* Задаёт MG78_17PL = ~(1 << 6); данные MG78_17PL. */ +#define MG78_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG78_17PL = 0xFFFF; данные MG78_17PL. */ +#define MG78_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG78_18PL = 0x007F; данные MG78_18PL. */ +#define MG78_18PL 0x007F +/* Задаёт MG78 = (MG78_11PL & MG78_12PL & MG78_13PL & MG78_14PL &; маска разрешённых прерываний внутри группы PIE 78. */ +#define MG78 (MG78_11PL & MG78_12PL & MG78_13PL & MG78_14PL & \ + MG78_15PL & MG78_16PL & MG78_17PL & MG78_18PL) /* Продолжает список аргументов, полей или выражение MG78_15PL & MG78_16PL & MG78_17PL & MG78_18PL); порядок элементов сохраняется. */ +// End of MG78: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG81 to MG88: +// + +// Beginning of MG81: +/* Условие компиляции (G82PL >= G81PL) или (G82PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G82PL >= G81PL) || (G82PL == 0) +/* Задаёт MG81_12PL = ~(1 << 1); данные MG81_12PL. */ +#define MG81_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG81_12PL = 0xFFFF; данные MG81_12PL. */ +#define MG81_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G83PL >= G81PL) или (G83PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G83PL >= G81PL) || (G83PL == 0) +/* Задаёт MG81_13PL = ~(1 << 2); данные MG81_13PL. */ +#define MG81_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG81_13PL = 0xFFFF; данные MG81_13PL. */ +#define MG81_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G84PL >= G81PL) или (G84PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G84PL >= G81PL) || (G84PL == 0) +/* Задаёт MG81_14PL = ~(1 << 3); данные MG81_14PL. */ +#define MG81_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG81_14PL = 0xFFFF; данные MG81_14PL. */ +#define MG81_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G85PL >= G81PL) или (G85PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G85PL >= G81PL) || (G85PL == 0) +/* Задаёт MG81_15PL = ~(1 << 4); данные MG81_15PL. */ +#define MG81_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG81_15PL = 0xFFFF; данные MG81_15PL. */ +#define MG81_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G86PL >= G81PL) или (G86PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G86PL >= G81PL) || (G86PL == 0) +/* Задаёт MG81_16PL = ~(1 << 5); данные MG81_16PL. */ +#define MG81_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG81_16PL = 0xFFFF; данные MG81_16PL. */ +#define MG81_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G87PL >= G81PL) или (G87PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G87PL >= G81PL) || (G87PL == 0) +/* Задаёт MG81_17PL = ~(1 << 6); данные MG81_17PL. */ +#define MG81_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG81_17PL = 0xFFFF; данные MG81_17PL. */ +#define MG81_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G88PL >= G81PL) или (G88PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G88PL >= G81PL) || (G88PL == 0) +/* Задаёт MG81_18PL = ~(1 << 7); данные MG81_18PL. */ +#define MG81_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG81_18PL = 0xFFFF; данные MG81_18PL. */ +#define MG81_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG81_11PL = 0x00FE; данные MG81_11PL. */ +#define MG81_11PL 0x00FE +/* Задаёт MG81 = (MG81_11PL & MG81_12PL & MG81_13PL & MG81_14PL &; маска разрешённых прерываний внутри группы PIE 81. */ +#define MG81 (MG81_11PL & MG81_12PL & MG81_13PL & MG81_14PL & \ + MG81_15PL & MG81_16PL & MG81_17PL & MG81_18PL) /* Продолжает список аргументов, полей или выражение MG81_15PL & MG81_16PL & MG81_17PL & MG81_18PL); порядок элементов сохраняется. */ +// End of MG81: + +// Beginning of MG82: +/* Условие компиляции (G81PL >= G82PL) или (G81PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G81PL >= G82PL) || (G81PL == 0) +/* Задаёт MG82_11PL = ~(1); данные MG82_11PL. */ +#define MG82_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG82_11PL = 0xFFFF; данные MG82_11PL. */ +#define MG82_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G83PL >= G82PL) или (G83PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G83PL >= G82PL) || (G83PL == 0) +/* Задаёт MG82_13PL = ~(1 << 2); данные MG82_13PL. */ +#define MG82_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG82_13PL = 0xFFFF; данные MG82_13PL. */ +#define MG82_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G84PL >= G82PL) или (G84PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G84PL >= G82PL) || (G84PL == 0) +/* Задаёт MG82_14PL = ~(1 << 3); данные MG82_14PL. */ +#define MG82_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG82_14PL = 0xFFFF; данные MG82_14PL. */ +#define MG82_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G85PL >= G82PL) или (G85PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G85PL >= G82PL) || (G85PL == 0) +/* Задаёт MG82_15PL = ~(1 << 4); данные MG82_15PL. */ +#define MG82_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG82_15PL = 0xFFFF; данные MG82_15PL. */ +#define MG82_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G86PL >= G82PL) или (G86PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G86PL >= G82PL) || (G86PL == 0) +/* Задаёт MG82_16PL = ~(1 << 5); данные MG82_16PL. */ +#define MG82_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG82_16PL = 0xFFFF; данные MG82_16PL. */ +#define MG82_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G87PL >= G82PL) или (G87PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G87PL >= G82PL) || (G87PL == 0) +/* Задаёт MG82_17PL = ~(1 << 6); данные MG82_17PL. */ +#define MG82_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG82_17PL = 0xFFFF; данные MG82_17PL. */ +#define MG82_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G88PL >= G82PL) или (G88PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G88PL >= G82PL) || (G88PL == 0) +/* Задаёт MG82_18PL = ~(1 << 7); данные MG82_18PL. */ +#define MG82_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG82_18PL = 0xFFFF; данные MG82_18PL. */ +#define MG82_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG82_12PL = 0x00FD; данные MG82_12PL. */ +#define MG82_12PL 0x00FD +/* Задаёт MG82 = (MG82_11PL & MG82_12PL & MG82_13PL & MG82_14PL &; маска разрешённых прерываний внутри группы PIE 82. */ +#define MG82 (MG82_11PL & MG82_12PL & MG82_13PL & MG82_14PL & \ + MG82_15PL & MG82_16PL & MG82_17PL & MG82_18PL) /* Продолжает список аргументов, полей или выражение MG82_15PL & MG82_16PL & MG82_17PL & MG82_18PL); порядок элементов сохраняется. */ +// End of MG82: + +// Beginning of MG83: +/* Условие компиляции (G81PL >= G83PL) или (G81PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G81PL >= G83PL) || (G81PL == 0) +/* Задаёт MG83_11PL = ~(1); данные MG83_11PL. */ +#define MG83_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG83_11PL = 0xFFFF; данные MG83_11PL. */ +#define MG83_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G82PL >= G83PL) или (G82PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G82PL >= G83PL) || (G82PL == 0) +/* Задаёт MG83_12PL = ~(1 << 1); данные MG83_12PL. */ +#define MG83_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG83_12PL = 0xFFFF; данные MG83_12PL. */ +#define MG83_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G84PL >= G83PL) или (G84PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G84PL >= G83PL) || (G84PL == 0) +/* Задаёт MG83_14PL = ~(1 << 3); данные MG83_14PL. */ +#define MG83_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG83_14PL = 0xFFFF; данные MG83_14PL. */ +#define MG83_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G85PL >= G83PL) или (G85PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G85PL >= G83PL) || (G85PL == 0) +/* Задаёт MG83_15PL = ~(1 << 4); данные MG83_15PL. */ +#define MG83_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG83_15PL = 0xFFFF; данные MG83_15PL. */ +#define MG83_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G86PL >= G83PL) или (G86PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G86PL >= G83PL) || (G86PL == 0) +/* Задаёт MG83_16PL = ~(1 << 5); данные MG83_16PL. */ +#define MG83_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG83_16PL = 0xFFFF; данные MG83_16PL. */ +#define MG83_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G87PL >= G83PL) или (G87PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G87PL >= G83PL) || (G87PL == 0) +/* Задаёт MG83_17PL = ~(1 << 6); данные MG83_17PL. */ +#define MG83_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG83_17PL = 0xFFFF; данные MG83_17PL. */ +#define MG83_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G88PL >= G83PL) или (G88PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G88PL >= G83PL) || (G88PL == 0) +/* Задаёт MG83_18PL = ~(1 << 7); данные MG83_18PL. */ +#define MG83_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG83_18PL = 0xFFFF; данные MG83_18PL. */ +#define MG83_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG83_13PL = 0x00FB; данные MG83_13PL. */ +#define MG83_13PL 0x00FB +/* Задаёт MG83 = (MG83_11PL & MG83_12PL & MG83_13PL & MG83_14PL &; маска разрешённых прерываний внутри группы PIE 83. */ +#define MG83 (MG83_11PL & MG83_12PL & MG83_13PL & MG83_14PL & \ + MG83_15PL & MG83_16PL & MG83_17PL & MG83_18PL) /* Продолжает список аргументов, полей или выражение MG83_15PL & MG83_16PL & MG83_17PL & MG83_18PL); порядок элементов сохраняется. */ +// End of MG83: + +// Beginning of MG84: +/* Условие компиляции (G81PL >= G84PL) или (G81PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G81PL >= G84PL) || (G81PL == 0) +/* Задаёт MG84_11PL = ~(1); данные MG84_11PL. */ +#define MG84_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG84_11PL = 0xFFFF; данные MG84_11PL. */ +#define MG84_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G82PL >= G84PL) или (G82PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G82PL >= G84PL) || (G82PL == 0) +/* Задаёт MG84_12PL = ~(1 << 1); данные MG84_12PL. */ +#define MG84_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG84_12PL = 0xFFFF; данные MG84_12PL. */ +#define MG84_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G83PL >= G84PL) или (G83PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G83PL >= G84PL) || (G83PL == 0) +/* Задаёт MG84_13PL = ~(1 << 2); данные MG84_13PL. */ +#define MG84_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG84_13PL = 0xFFFF; данные MG84_13PL. */ +#define MG84_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G85PL >= G84PL) или (G85PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G85PL >= G84PL) || (G85PL == 0) +/* Задаёт MG84_15PL = ~(1 << 4); данные MG84_15PL. */ +#define MG84_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG84_15PL = 0xFFFF; данные MG84_15PL. */ +#define MG84_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G86PL >= G84PL) или (G86PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G86PL >= G84PL) || (G86PL == 0) +/* Задаёт MG84_16PL = ~(1 << 5); данные MG84_16PL. */ +#define MG84_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG84_16PL = 0xFFFF; данные MG84_16PL. */ +#define MG84_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G87PL >= G84PL) или (G87PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G87PL >= G84PL) || (G87PL == 0) +/* Задаёт MG84_17PL = ~(1 << 6); данные MG84_17PL. */ +#define MG84_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG84_17PL = 0xFFFF; данные MG84_17PL. */ +#define MG84_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G88PL >= G84PL) или (G88PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G88PL >= G84PL) || (G88PL == 0) +/* Задаёт MG84_18PL = ~(1 << 7); данные MG84_18PL. */ +#define MG84_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG84_18PL = 0xFFFF; данные MG84_18PL. */ +#define MG84_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG84_14PL = 0x00F7; данные MG84_14PL. */ +#define MG84_14PL 0x00F7 +/* Задаёт MG84 = (MG84_11PL & MG84_12PL & MG84_13PL & MG84_14PL &; маска разрешённых прерываний внутри группы PIE 84. */ +#define MG84 (MG84_11PL & MG84_12PL & MG84_13PL & MG84_14PL & \ + MG84_15PL & MG84_16PL & MG84_17PL & MG84_18PL) /* Продолжает список аргументов, полей или выражение MG84_15PL & MG84_16PL & MG84_17PL & MG84_18PL); порядок элементов сохраняется. */ +// End of MG84: + +// Beginning of MG85: +/* Условие компиляции (G81PL >= G85PL) или (G81PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G81PL >= G85PL) || (G81PL == 0) +/* Задаёт MG85_11PL = ~(1); данные MG85_11PL. */ +#define MG85_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG85_11PL = 0xFFFF; данные MG85_11PL. */ +#define MG85_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G82PL >= G85PL) или (G82PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G82PL >= G85PL) || (G82PL == 0) +/* Задаёт MG85_12PL = ~(1 << 1); данные MG85_12PL. */ +#define MG85_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG85_12PL = 0xFFFF; данные MG85_12PL. */ +#define MG85_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G83PL >= G85PL) или (G83PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G83PL >= G85PL) || (G83PL == 0) +/* Задаёт MG85_13PL = ~(1 << 2); данные MG85_13PL. */ +#define MG85_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG85_13PL = 0xFFFF; данные MG85_13PL. */ +#define MG85_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G84PL >= G85PL) или (G84PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G84PL >= G85PL) || (G84PL == 0) +/* Задаёт MG85_14PL = ~(1 << 3); данные MG85_14PL. */ +#define MG85_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG85_14PL = 0xFFFF; данные MG85_14PL. */ +#define MG85_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G86PL >= G85PL) или (G86PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G86PL >= G85PL) || (G86PL == 0) +/* Задаёт MG85_16PL = ~(1 << 5); данные MG85_16PL. */ +#define MG85_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG85_16PL = 0xFFFF; данные MG85_16PL. */ +#define MG85_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G87PL >= G85PL) или (G87PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G87PL >= G85PL) || (G87PL == 0) +/* Задаёт MG85_17PL = ~(1 << 6); данные MG85_17PL. */ +#define MG85_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG85_17PL = 0xFFFF; данные MG85_17PL. */ +#define MG85_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G88PL >= G85PL) или (G88PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G88PL >= G85PL) || (G88PL == 0) +/* Задаёт MG85_18PL = ~(1 << 7); данные MG85_18PL. */ +#define MG85_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG85_18PL = 0xFFFF; данные MG85_18PL. */ +#define MG85_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG85_15PL = 0x00EF; данные MG85_15PL. */ +#define MG85_15PL 0x00EF +/* Задаёт MG85 = (MG85_11PL & MG85_12PL & MG85_13PL & MG85_14PL &; маска разрешённых прерываний внутри группы PIE 85. */ +#define MG85 (MG85_11PL & MG85_12PL & MG85_13PL & MG85_14PL & \ + MG85_15PL & MG85_16PL & MG85_17PL & MG85_18PL) /* Продолжает список аргументов, полей или выражение MG85_15PL & MG85_16PL & MG85_17PL & MG85_18PL); порядок элементов сохраняется. */ +// End of MG85: + +// Beginning of MG86: +/* Условие компиляции (G81PL >= G86PL) или (G81PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G81PL >= G86PL) || (G81PL == 0) +/* Задаёт MG86_11PL = ~(1); данные MG86_11PL. */ +#define MG86_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG86_11PL = 0xFFFF; данные MG86_11PL. */ +#define MG86_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G82PL >= G86PL) или (G82PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G82PL >= G86PL) || (G82PL == 0) +/* Задаёт MG86_12PL = ~(1 << 1); данные MG86_12PL. */ +#define MG86_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG86_12PL = 0xFFFF; данные MG86_12PL. */ +#define MG86_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G83PL >= G86PL) или (G83PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G83PL >= G86PL) || (G83PL == 0) +/* Задаёт MG86_13PL = ~(1 << 2); данные MG86_13PL. */ +#define MG86_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG86_13PL = 0xFFFF; данные MG86_13PL. */ +#define MG86_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G84PL >= G86PL) или (G84PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G84PL >= G86PL) || (G84PL == 0) +/* Задаёт MG86_14PL = ~(1 << 3); данные MG86_14PL. */ +#define MG86_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG86_14PL = 0xFFFF; данные MG86_14PL. */ +#define MG86_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G85PL >= G86PL) или (G85PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G85PL >= G86PL) || (G85PL == 0) +/* Задаёт MG86_15PL = ~(1 << 4); данные MG86_15PL. */ +#define MG86_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG86_15PL = 0xFFFF; данные MG86_15PL. */ +#define MG86_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G87PL >= G86PL) или (G87PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G87PL >= G86PL) || (G87PL == 0) +/* Задаёт MG86_17PL = ~(1 << 6); данные MG86_17PL. */ +#define MG86_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG86_17PL = 0xFFFF; данные MG86_17PL. */ +#define MG86_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G88PL >= G86PL) или (G88PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G88PL >= G86PL) || (G88PL == 0) +/* Задаёт MG86_18PL = ~(1 << 7); данные MG86_18PL. */ +#define MG86_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG86_18PL = 0xFFFF; данные MG86_18PL. */ +#define MG86_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG86_16PL = 0x00DF; данные MG86_16PL. */ +#define MG86_16PL 0x00DF +/* Задаёт MG86 = (MG86_11PL & MG86_12PL & MG86_13PL & MG86_14PL &; маска разрешённых прерываний внутри группы PIE 86. */ +#define MG86 (MG86_11PL & MG86_12PL & MG86_13PL & MG86_14PL & \ + MG86_15PL & MG86_16PL & MG86_17PL & MG86_18PL) /* Продолжает список аргументов, полей или выражение MG86_15PL & MG86_16PL & MG86_17PL & MG86_18PL); порядок элементов сохраняется. */ +// End of MG86: + +// Beginning of MG87: +/* Условие компиляции (G81PL >= G87PL) или (G81PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G81PL >= G87PL) || (G81PL == 0) +/* Задаёт MG87_11PL = ~(1); данные MG87_11PL. */ +#define MG87_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG87_11PL = 0xFFFF; данные MG87_11PL. */ +#define MG87_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G82PL >= G87PL) или (G82PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G82PL >= G87PL) || (G82PL == 0) +/* Задаёт MG87_12PL = ~(1 << 1); данные MG87_12PL. */ +#define MG87_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG87_12PL = 0xFFFF; данные MG87_12PL. */ +#define MG87_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G83PL >= G87PL) или (G83PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G83PL >= G87PL) || (G83PL == 0) +/* Задаёт MG87_13PL = ~(1 << 2); данные MG87_13PL. */ +#define MG87_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG87_13PL = 0xFFFF; данные MG87_13PL. */ +#define MG87_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G84PL >= G87PL) или (G84PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G84PL >= G87PL) || (G84PL == 0) +/* Задаёт MG87_14PL = ~(1 << 3); данные MG87_14PL. */ +#define MG87_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG87_14PL = 0xFFFF; данные MG87_14PL. */ +#define MG87_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G85PL >= G87PL) или (G85PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G85PL >= G87PL) || (G85PL == 0) +/* Задаёт MG87_15PL = ~(1 << 4); данные MG87_15PL. */ +#define MG87_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG87_15PL = 0xFFFF; данные MG87_15PL. */ +#define MG87_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G86PL >= G87PL) или (G86PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G86PL >= G87PL) || (G86PL == 0) +/* Задаёт MG87_16PL = ~(1 << 5); данные MG87_16PL. */ +#define MG87_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG87_16PL = 0xFFFF; данные MG87_16PL. */ +#define MG87_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G88PL >= G87PL) или (G88PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G88PL >= G87PL) || (G88PL == 0) +/* Задаёт MG87_18PL = ~(1 << 7); данные MG87_18PL. */ +#define MG87_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG87_18PL = 0xFFFF; данные MG87_18PL. */ +#define MG87_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG87_17PL = 0x00BF; данные MG87_17PL. */ +#define MG87_17PL 0x00BF +/* Задаёт MG87 = (MG87_11PL & MG87_12PL & MG87_13PL & MG87_14PL &; маска разрешённых прерываний внутри группы PIE 87. */ +#define MG87 (MG87_11PL & MG87_12PL & MG87_13PL & MG87_14PL & \ + MG87_15PL & MG87_16PL & MG87_17PL & MG87_18PL) /* Продолжает список аргументов, полей или выражение MG87_15PL & MG87_16PL & MG87_17PL & MG87_18PL); порядок элементов сохраняется. */ +// End of MG87: + +// Beginning of MG88: +/* Условие компиляции (G81PL >= G88PL) или (G81PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G81PL >= G88PL) || (G81PL == 0) +/* Задаёт MG88_11PL = ~(1); данные MG88_11PL. */ +#define MG88_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG88_11PL = 0xFFFF; данные MG88_11PL. */ +#define MG88_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G82PL >= G88PL) или (G82PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G82PL >= G88PL) || (G82PL == 0) +/* Задаёт MG88_12PL = ~(1 << 1); данные MG88_12PL. */ +#define MG88_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG88_12PL = 0xFFFF; данные MG88_12PL. */ +#define MG88_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G83PL >= G88PL) или (G83PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G83PL >= G88PL) || (G83PL == 0) +/* Задаёт MG88_13PL = ~(1 << 2); данные MG88_13PL. */ +#define MG88_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG88_13PL = 0xFFFF; данные MG88_13PL. */ +#define MG88_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G84PL >= G88PL) или (G84PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G84PL >= G88PL) || (G84PL == 0) +/* Задаёт MG88_14PL = ~(1 << 3); данные MG88_14PL. */ +#define MG88_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG88_14PL = 0xFFFF; данные MG88_14PL. */ +#define MG88_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G85PL >= G88PL) или (G85PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G85PL >= G88PL) || (G85PL == 0) +/* Задаёт MG88_15PL = ~(1 << 4); данные MG88_15PL. */ +#define MG88_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG88_15PL = 0xFFFF; данные MG88_15PL. */ +#define MG88_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G86PL >= G88PL) или (G86PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G86PL >= G88PL) || (G86PL == 0) +/* Задаёт MG88_16PL = ~(1 << 5); данные MG88_16PL. */ +#define MG88_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG88_16PL = 0xFFFF; данные MG88_16PL. */ +#define MG88_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G87PL >= G88PL) или (G87PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G87PL >= G88PL) || (G87PL == 0) +/* Задаёт MG88_17PL = ~(1 << 6); данные MG88_17PL. */ +#define MG88_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG88_17PL = 0xFFFF; данные MG88_17PL. */ +#define MG88_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG88_18PL = 0x007F; данные MG88_18PL. */ +#define MG88_18PL 0x007F +/* Задаёт MG88 = (MG88_11PL & MG88_12PL & MG88_13PL & MG88_14PL &; маска разрешённых прерываний внутри группы PIE 88. */ +#define MG88 (MG88_11PL & MG88_12PL & MG88_13PL & MG88_14PL & \ + MG88_15PL & MG88_16PL & MG88_17PL & MG88_18PL) /* Продолжает список аргументов, полей или выражение MG88_15PL & MG88_16PL & MG88_17PL & MG88_18PL); порядок элементов сохраняется. */ +// End of MG88: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG91 to MG98: +// + +// Beginning of MG91: +/* Условие компиляции (G92PL >= G91PL) или (G92PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G92PL >= G91PL) || (G92PL == 0) +/* Задаёт MG91_12PL = ~(1 << 1); данные MG91_12PL. */ +#define MG91_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG91_12PL = 0xFFFF; данные MG91_12PL. */ +#define MG91_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G93PL >= G91PL) или (G93PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G93PL >= G91PL) || (G93PL == 0) +/* Задаёт MG91_13PL = ~(1 << 2); данные MG91_13PL. */ +#define MG91_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG91_13PL = 0xFFFF; данные MG91_13PL. */ +#define MG91_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G94PL >= G91PL) или (G94PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G94PL >= G91PL) || (G94PL == 0) +/* Задаёт MG91_14PL = ~(1 << 3); данные MG91_14PL. */ +#define MG91_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG91_14PL = 0xFFFF; данные MG91_14PL. */ +#define MG91_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G95PL >= G91PL) или (G95PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G95PL >= G91PL) || (G95PL == 0) +/* Задаёт MG91_15PL = ~(1 << 4); данные MG91_15PL. */ +#define MG91_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG91_15PL = 0xFFFF; данные MG91_15PL. */ +#define MG91_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G96PL >= G91PL) или (G96PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G96PL >= G91PL) || (G96PL == 0) +/* Задаёт MG91_16PL = ~(1 << 5); данные MG91_16PL. */ +#define MG91_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG91_16PL = 0xFFFF; данные MG91_16PL. */ +#define MG91_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G97PL >= G91PL) или (G97PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G97PL >= G91PL) || (G97PL == 0) +/* Задаёт MG91_17PL = ~(1 << 6); данные MG91_17PL. */ +#define MG91_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG91_17PL = 0xFFFF; данные MG91_17PL. */ +#define MG91_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G98PL >= G91PL) или (G98PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G98PL >= G91PL) || (G98PL == 0) +/* Задаёт MG91_18PL = ~(1 << 7); данные MG91_18PL. */ +#define MG91_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG91_18PL = 0xFFFF; данные MG91_18PL. */ +#define MG91_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG91_11PL = 0x00FE; данные MG91_11PL. */ +#define MG91_11PL 0x00FE +/* Задаёт MG91 = (MG91_11PL & MG91_12PL & MG91_13PL & MG91_14PL &; маска разрешённых прерываний внутри группы PIE 91. */ +#define MG91 (MG91_11PL & MG91_12PL & MG91_13PL & MG91_14PL & \ + MG91_15PL & MG91_16PL & MG91_17PL & MG91_18PL) /* Продолжает список аргументов, полей или выражение MG91_15PL & MG91_16PL & MG91_17PL & MG91_18PL); порядок элементов сохраняется. */ +// End of MG91: + +// Beginning of MG92: +/* Условие компиляции (G91PL >= G92PL) или (G91PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G91PL >= G92PL) || (G91PL == 0) +/* Задаёт MG92_11PL = ~(1); данные MG92_11PL. */ +#define MG92_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG92_11PL = 0xFFFF; данные MG92_11PL. */ +#define MG92_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G93PL >= G92PL) или (G93PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G93PL >= G92PL) || (G93PL == 0) +/* Задаёт MG92_13PL = ~(1 << 2); данные MG92_13PL. */ +#define MG92_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG92_13PL = 0xFFFF; данные MG92_13PL. */ +#define MG92_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G94PL >= G92PL) или (G94PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G94PL >= G92PL) || (G94PL == 0) +/* Задаёт MG92_14PL = ~(1 << 3); данные MG92_14PL. */ +#define MG92_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG92_14PL = 0xFFFF; данные MG92_14PL. */ +#define MG92_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G95PL >= G92PL) или (G95PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G95PL >= G92PL) || (G95PL == 0) +/* Задаёт MG92_15PL = ~(1 << 4); данные MG92_15PL. */ +#define MG92_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG92_15PL = 0xFFFF; данные MG92_15PL. */ +#define MG92_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G96PL >= G92PL) или (G96PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G96PL >= G92PL) || (G96PL == 0) +/* Задаёт MG92_16PL = ~(1 << 5); данные MG92_16PL. */ +#define MG92_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG92_16PL = 0xFFFF; данные MG92_16PL. */ +#define MG92_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G97PL >= G92PL) или (G97PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G97PL >= G92PL) || (G97PL == 0) +/* Задаёт MG92_17PL = ~(1 << 6); данные MG92_17PL. */ +#define MG92_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG92_17PL = 0xFFFF; данные MG92_17PL. */ +#define MG92_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G98PL >= G92PL) или (G98PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G98PL >= G92PL) || (G98PL == 0) +/* Задаёт MG92_18PL = ~(1 << 7); данные MG92_18PL. */ +#define MG92_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG92_18PL = 0xFFFF; данные MG92_18PL. */ +#define MG92_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG92_12PL = 0x00FD; данные MG92_12PL. */ +#define MG92_12PL 0x00FD +/* Задаёт MG92 = (MG92_11PL & MG92_12PL & MG92_13PL & MG92_14PL &; маска разрешённых прерываний внутри группы PIE 92. */ +#define MG92 (MG92_11PL & MG92_12PL & MG92_13PL & MG92_14PL & \ + MG92_15PL & MG92_16PL & MG92_17PL & MG92_18PL) /* Продолжает список аргументов, полей или выражение MG92_15PL & MG92_16PL & MG92_17PL & MG92_18PL); порядок элементов сохраняется. */ +// End of MG92: + +// Beginning of MG93: +/* Условие компиляции (G91PL >= G93PL) или (G91PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G91PL >= G93PL) || (G91PL == 0) +/* Задаёт MG93_11PL = ~(1); данные MG93_11PL. */ +#define MG93_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG93_11PL = 0xFFFF; данные MG93_11PL. */ +#define MG93_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G92PL >= G93PL) или (G92PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G92PL >= G93PL) || (G92PL == 0) +/* Задаёт MG93_12PL = ~(1 << 1); данные MG93_12PL. */ +#define MG93_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG93_12PL = 0xFFFF; данные MG93_12PL. */ +#define MG93_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G94PL >= G93PL) или (G94PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G94PL >= G93PL) || (G94PL == 0) +/* Задаёт MG93_14PL = ~(1 << 3); данные MG93_14PL. */ +#define MG93_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG93_14PL = 0xFFFF; данные MG93_14PL. */ +#define MG93_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G95PL >= G93PL) или (G95PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G95PL >= G93PL) || (G95PL == 0) +/* Задаёт MG93_15PL = ~(1 << 4); данные MG93_15PL. */ +#define MG93_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG93_15PL = 0xFFFF; данные MG93_15PL. */ +#define MG93_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G96PL >= G93PL) или (G96PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G96PL >= G93PL) || (G96PL == 0) +/* Задаёт MG93_16PL = ~(1 << 5); данные MG93_16PL. */ +#define MG93_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG93_16PL = 0xFFFF; данные MG93_16PL. */ +#define MG93_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G97PL >= G93PL) или (G97PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G97PL >= G93PL) || (G97PL == 0) +/* Задаёт MG93_17PL = ~(1 << 6); данные MG93_17PL. */ +#define MG93_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG93_17PL = 0xFFFF; данные MG93_17PL. */ +#define MG93_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G98PL >= G93PL) или (G98PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G98PL >= G93PL) || (G98PL == 0) +/* Задаёт MG93_18PL = ~(1 << 7); данные MG93_18PL. */ +#define MG93_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG93_18PL = 0xFFFF; данные MG93_18PL. */ +#define MG93_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG93_13PL = 0x00FB; данные MG93_13PL. */ +#define MG93_13PL 0x00FB +/* Задаёт MG93 = (MG93_11PL & MG93_12PL & MG93_13PL & MG93_14PL &; маска разрешённых прерываний внутри группы PIE 93. */ +#define MG93 (MG93_11PL & MG93_12PL & MG93_13PL & MG93_14PL & \ + MG93_15PL & MG93_16PL & MG93_17PL & MG93_18PL) /* Продолжает список аргументов, полей или выражение MG93_15PL & MG93_16PL & MG93_17PL & MG93_18PL); порядок элементов сохраняется. */ +// End of MG93: + +// Beginning of MG94: +/* Условие компиляции (G91PL >= G94PL) или (G91PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G91PL >= G94PL) || (G91PL == 0) +/* Задаёт MG94_11PL = ~(1); данные MG94_11PL. */ +#define MG94_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG94_11PL = 0xFFFF; данные MG94_11PL. */ +#define MG94_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G92PL >= G94PL) или (G92PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G92PL >= G94PL) || (G92PL == 0) +/* Задаёт MG94_12PL = ~(1 << 1); данные MG94_12PL. */ +#define MG94_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG94_12PL = 0xFFFF; данные MG94_12PL. */ +#define MG94_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G93PL >= G94PL) или (G93PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G93PL >= G94PL) || (G93PL == 0) +/* Задаёт MG94_13PL = ~(1 << 2); данные MG94_13PL. */ +#define MG94_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG94_13PL = 0xFFFF; данные MG94_13PL. */ +#define MG94_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G95PL >= G94PL) или (G95PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G95PL >= G94PL) || (G95PL == 0) +/* Задаёт MG94_15PL = ~(1 << 4); данные MG94_15PL. */ +#define MG94_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG94_15PL = 0xFFFF; данные MG94_15PL. */ +#define MG94_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G96PL >= G94PL) или (G96PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G96PL >= G94PL) || (G96PL == 0) +/* Задаёт MG94_16PL = ~(1 << 5); данные MG94_16PL. */ +#define MG94_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG94_16PL = 0xFFFF; данные MG94_16PL. */ +#define MG94_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G97PL >= G94PL) или (G97PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G97PL >= G94PL) || (G97PL == 0) +/* Задаёт MG94_17PL = ~(1 << 6); данные MG94_17PL. */ +#define MG94_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG94_17PL = 0xFFFF; данные MG94_17PL. */ +#define MG94_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G98PL >= G94PL) или (G98PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G98PL >= G94PL) || (G98PL == 0) +/* Задаёт MG94_18PL = ~(1 << 7); данные MG94_18PL. */ +#define MG94_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG94_18PL = 0xFFFF; данные MG94_18PL. */ +#define MG94_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG94_14PL = 0x00F7; данные MG94_14PL. */ +#define MG94_14PL 0x00F7 +/* Задаёт MG94 = (MG94_11PL & MG94_12PL & MG94_13PL & MG94_14PL &; маска разрешённых прерываний внутри группы PIE 94. */ +#define MG94 (MG94_11PL & MG94_12PL & MG94_13PL & MG94_14PL & \ + MG94_15PL & MG94_16PL & MG94_17PL & MG94_18PL) /* Продолжает список аргументов, полей или выражение MG94_15PL & MG94_16PL & MG94_17PL & MG94_18PL); порядок элементов сохраняется. */ +// End of MG94: + +// Beginning of MG95: +/* Условие компиляции (G91PL >= G95PL) или (G91PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G91PL >= G95PL) || (G91PL == 0) +/* Задаёт MG95_11PL = ~(1); данные MG95_11PL. */ +#define MG95_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG95_11PL = 0xFFFF; данные MG95_11PL. */ +#define MG95_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G92PL >= G95PL) или (G92PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G92PL >= G95PL) || (G92PL == 0) +/* Задаёт MG95_12PL = ~(1 << 1); данные MG95_12PL. */ +#define MG95_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG95_12PL = 0xFFFF; данные MG95_12PL. */ +#define MG95_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G93PL >= G95PL) или (G93PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G93PL >= G95PL) || (G93PL == 0) +/* Задаёт MG95_13PL = ~(1 << 2); данные MG95_13PL. */ +#define MG95_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG95_13PL = 0xFFFF; данные MG95_13PL. */ +#define MG95_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G94PL >= G95PL) или (G94PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G94PL >= G95PL) || (G94PL == 0) +/* Задаёт MG95_14PL = ~(1 << 3); данные MG95_14PL. */ +#define MG95_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG95_14PL = 0xFFFF; данные MG95_14PL. */ +#define MG95_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G96PL >= G95PL) или (G96PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G96PL >= G95PL) || (G96PL == 0) +/* Задаёт MG95_16PL = ~(1 << 5); данные MG95_16PL. */ +#define MG95_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG95_16PL = 0xFFFF; данные MG95_16PL. */ +#define MG95_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G97PL >= G95PL) или (G97PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G97PL >= G95PL) || (G97PL == 0) +/* Задаёт MG95_17PL = ~(1 << 6); данные MG95_17PL. */ +#define MG95_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG95_17PL = 0xFFFF; данные MG95_17PL. */ +#define MG95_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G98PL >= G95PL) или (G98PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G98PL >= G95PL) || (G98PL == 0) +/* Задаёт MG95_18PL = ~(1 << 7); данные MG95_18PL. */ +#define MG95_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG95_18PL = 0xFFFF; данные MG95_18PL. */ +#define MG95_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG95_15PL = 0x00EF; данные MG95_15PL. */ +#define MG95_15PL 0x00EF +/* Задаёт MG95 = (MG95_11PL & MG95_12PL & MG95_13PL & MG95_14PL &; маска разрешённых прерываний внутри группы PIE 95. */ +#define MG95 (MG95_11PL & MG95_12PL & MG95_13PL & MG95_14PL & \ + MG95_15PL & MG95_16PL & MG95_17PL & MG95_18PL) /* Продолжает список аргументов, полей или выражение MG95_15PL & MG95_16PL & MG95_17PL & MG95_18PL); порядок элементов сохраняется. */ +// End of MG95: + +// Beginning of MG96: +/* Условие компиляции (G91PL >= G96PL) или (G91PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G91PL >= G96PL) || (G91PL == 0) +/* Задаёт MG96_11PL = ~(1); данные MG96_11PL. */ +#define MG96_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG96_11PL = 0xFFFF; данные MG96_11PL. */ +#define MG96_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G92PL >= G96PL) или (G92PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G92PL >= G96PL) || (G92PL == 0) +/* Задаёт MG96_12PL = ~(1 << 1); данные MG96_12PL. */ +#define MG96_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG96_12PL = 0xFFFF; данные MG96_12PL. */ +#define MG96_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G93PL >= G96PL) или (G93PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G93PL >= G96PL) || (G93PL == 0) +/* Задаёт MG96_13PL = ~(1 << 2); данные MG96_13PL. */ +#define MG96_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG96_13PL = 0xFFFF; данные MG96_13PL. */ +#define MG96_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G94PL >= G96PL) или (G94PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G94PL >= G96PL) || (G94PL == 0) +/* Задаёт MG96_14PL = ~(1 << 3); данные MG96_14PL. */ +#define MG96_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG96_14PL = 0xFFFF; данные MG96_14PL. */ +#define MG96_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G95PL >= G96PL) или (G95PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G95PL >= G96PL) || (G95PL == 0) +/* Задаёт MG96_15PL = ~(1 << 4); данные MG96_15PL. */ +#define MG96_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG96_15PL = 0xFFFF; данные MG96_15PL. */ +#define MG96_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G97PL >= G96PL) или (G97PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G97PL >= G96PL) || (G97PL == 0) +/* Задаёт MG96_17PL = ~(1 << 6); данные MG96_17PL. */ +#define MG96_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG96_17PL = 0xFFFF; данные MG96_17PL. */ +#define MG96_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G98PL >= G96PL) или (G98PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G98PL >= G96PL) || (G98PL == 0) +/* Задаёт MG96_18PL = ~(1 << 7); данные MG96_18PL. */ +#define MG96_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG96_18PL = 0xFFFF; данные MG96_18PL. */ +#define MG96_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG96_16PL = 0x00DF; данные MG96_16PL. */ +#define MG96_16PL 0x00DF +/* Задаёт MG96 = (MG96_11PL & MG96_12PL & MG96_13PL & MG96_14PL &; маска разрешённых прерываний внутри группы PIE 96. */ +#define MG96 (MG96_11PL & MG96_12PL & MG96_13PL & MG96_14PL & \ + MG96_15PL & MG96_16PL & MG96_17PL & MG96_18PL) /* Продолжает список аргументов, полей или выражение MG96_15PL & MG96_16PL & MG96_17PL & MG96_18PL); порядок элементов сохраняется. */ +// End of MG96: + +// Beginning of MG97: +/* Условие компиляции (G91PL >= G97PL) или (G91PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G91PL >= G97PL) || (G91PL == 0) +/* Задаёт MG97_11PL = ~(1); данные MG97_11PL. */ +#define MG97_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG97_11PL = 0xFFFF; данные MG97_11PL. */ +#define MG97_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G92PL >= G97PL) или (G92PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G92PL >= G97PL) || (G92PL == 0) +/* Задаёт MG97_12PL = ~(1 << 1); данные MG97_12PL. */ +#define MG97_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG97_12PL = 0xFFFF; данные MG97_12PL. */ +#define MG97_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G93PL >= G97PL) или (G93PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G93PL >= G97PL) || (G93PL == 0) +/* Задаёт MG97_13PL = ~(1 << 2); данные MG97_13PL. */ +#define MG97_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG97_13PL = 0xFFFF; данные MG97_13PL. */ +#define MG97_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G94PL >= G97PL) или (G94PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G94PL >= G97PL) || (G94PL == 0) +/* Задаёт MG97_14PL = ~(1 << 3); данные MG97_14PL. */ +#define MG97_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG97_14PL = 0xFFFF; данные MG97_14PL. */ +#define MG97_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G95PL >= G97PL) или (G95PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G95PL >= G97PL) || (G95PL == 0) +/* Задаёт MG97_15PL = ~(1 << 4); данные MG97_15PL. */ +#define MG97_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG97_15PL = 0xFFFF; данные MG97_15PL. */ +#define MG97_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G96PL >= G97PL) или (G96PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G96PL >= G97PL) || (G96PL == 0) +/* Задаёт MG97_16PL = ~(1 << 5); данные MG97_16PL. */ +#define MG97_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG97_16PL = 0xFFFF; данные MG97_16PL. */ +#define MG97_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G98PL >= G97PL) или (G98PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G98PL >= G97PL) || (G98PL == 0) +/* Задаёт MG97_18PL = ~(1 << 7); данные MG97_18PL. */ +#define MG97_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG97_18PL = 0xFFFF; данные MG97_18PL. */ +#define MG97_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG97_17PL = 0x00BF; данные MG97_17PL. */ +#define MG97_17PL 0x00BF +/* Задаёт MG97 = (MG97_11PL & MG97_12PL & MG97_13PL & MG97_14PL &; маска разрешённых прерываний внутри группы PIE 97. */ +#define MG97 (MG97_11PL & MG97_12PL & MG97_13PL & MG97_14PL & \ + MG97_15PL & MG97_16PL & MG97_17PL & MG97_18PL) /* Продолжает список аргументов, полей или выражение MG97_15PL & MG97_16PL & MG97_17PL & MG97_18PL); порядок элементов сохраняется. */ +// End of MG97: + +// Beginning of MG98: +/* Условие компиляции (G91PL >= G98PL) или (G91PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G91PL >= G98PL) || (G91PL == 0) +/* Задаёт MG98_11PL = ~(1); данные MG98_11PL. */ +#define MG98_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG98_11PL = 0xFFFF; данные MG98_11PL. */ +#define MG98_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G92PL >= G98PL) или (G92PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G92PL >= G98PL) || (G92PL == 0) +/* Задаёт MG98_12PL = ~(1 << 1); данные MG98_12PL. */ +#define MG98_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG98_12PL = 0xFFFF; данные MG98_12PL. */ +#define MG98_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G93PL >= G98PL) или (G93PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G93PL >= G98PL) || (G93PL == 0) +/* Задаёт MG98_13PL = ~(1 << 2); данные MG98_13PL. */ +#define MG98_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG98_13PL = 0xFFFF; данные MG98_13PL. */ +#define MG98_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G94PL >= G98PL) или (G94PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G94PL >= G98PL) || (G94PL == 0) +/* Задаёт MG98_14PL = ~(1 << 3); данные MG98_14PL. */ +#define MG98_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG98_14PL = 0xFFFF; данные MG98_14PL. */ +#define MG98_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G95PL >= G98PL) или (G95PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G95PL >= G98PL) || (G95PL == 0) +/* Задаёт MG98_15PL = ~(1 << 4); данные MG98_15PL. */ +#define MG98_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG98_15PL = 0xFFFF; данные MG98_15PL. */ +#define MG98_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G96PL >= G98PL) или (G96PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G96PL >= G98PL) || (G96PL == 0) +/* Задаёт MG98_16PL = ~(1 << 5); данные MG98_16PL. */ +#define MG98_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG98_16PL = 0xFFFF; данные MG98_16PL. */ +#define MG98_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G97PL >= G98PL) или (G97PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G97PL >= G98PL) || (G97PL == 0) +/* Задаёт MG98_17PL = ~(1 << 6); данные MG98_17PL. */ +#define MG98_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG98_17PL = 0xFFFF; данные MG98_17PL. */ +#define MG98_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG98_18PL = 0x007F; данные MG98_18PL. */ +#define MG98_18PL 0x007F +/* Задаёт MG98 = (MG98_11PL & MG98_12PL & MG98_13PL & MG98_14PL &; маска разрешённых прерываний внутри группы PIE 98. */ +#define MG98 (MG98_11PL & MG98_12PL & MG98_13PL & MG98_14PL & \ + MG98_15PL & MG98_16PL & MG98_17PL & MG98_18PL) /* Продолжает список аргументов, полей или выражение MG98_15PL & MG98_16PL & MG98_17PL & MG98_18PL); порядок элементов сохраняется. */ +// End of MG98: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG101 to MG108: +// + +// Beginning of MG101: +/* Условие компиляции (G102PL >= G101PL) или (G102PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G102PL >= G101PL) || (G102PL == 0) +/* Задаёт MG101_12PL = ~(1 << 1); данные MG101_12PL. */ +#define MG101_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG101_12PL = 0xFFFF; данные MG101_12PL. */ +#define MG101_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G103PL >= G101PL) или (G103PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G103PL >= G101PL) || (G103PL == 0) +/* Задаёт MG101_13PL = ~(1 << 2); данные MG101_13PL. */ +#define MG101_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG101_13PL = 0xFFFF; данные MG101_13PL. */ +#define MG101_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G104PL >= G101PL) или (G104PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G104PL >= G101PL) || (G104PL == 0) +/* Задаёт MG101_14PL = ~(1 << 3); данные MG101_14PL. */ +#define MG101_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG101_14PL = 0xFFFF; данные MG101_14PL. */ +#define MG101_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G105PL >= G101PL) или (G105PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G105PL >= G101PL) || (G105PL == 0) +/* Задаёт MG101_15PL = ~(1 << 4); данные MG101_15PL. */ +#define MG101_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG101_15PL = 0xFFFF; данные MG101_15PL. */ +#define MG101_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G106PL >= G101PL) или (G106PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G106PL >= G101PL) || (G106PL == 0) +/* Задаёт MG101_16PL = ~(1 << 5); данные MG101_16PL. */ +#define MG101_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG101_16PL = 0xFFFF; данные MG101_16PL. */ +#define MG101_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G107PL >= G101PL) или (G107PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G107PL >= G101PL) || (G107PL == 0) +/* Задаёт MG101_17PL = ~(1 << 6); данные MG101_17PL. */ +#define MG101_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG101_17PL = 0xFFFF; данные MG101_17PL. */ +#define MG101_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G108PL >= G101PL) или (G108PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G108PL >= G101PL) || (G108PL == 0) +/* Задаёт MG101_18PL = ~(1 << 7); данные MG101_18PL. */ +#define MG101_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG101_18PL = 0xFFFF; данные MG101_18PL. */ +#define MG101_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG101_11PL = 0x00FE; данные MG101_11PL. */ +#define MG101_11PL 0x00FE +/* Задаёт MG101 = (MG101_11PL & MG101_12PL & MG101_13PL & MG101_14PL &; маска разрешённых прерываний внутри группы PIE 101. */ +#define MG101 (MG101_11PL & MG101_12PL & MG101_13PL & MG101_14PL & \ + MG101_15PL & MG101_16PL & MG101_17PL & MG101_18PL) /* Продолжает список аргументов, полей или выражение MG101_15PL & MG101_16PL & MG101_17PL & MG101_18PL); порядок элементов сохраняется. */ +// End of MG101: + +// Beginning of MG102: +/* Условие компиляции (G101PL >= G102PL) или (G101PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G101PL >= G102PL) || (G101PL == 0) +/* Задаёт MG102_11PL = ~(1); данные MG102_11PL. */ +#define MG102_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG102_11PL = 0xFFFF; данные MG102_11PL. */ +#define MG102_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G103PL >= G102PL) или (G103PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G103PL >= G102PL) || (G103PL == 0) +/* Задаёт MG102_13PL = ~(1 << 2); данные MG102_13PL. */ +#define MG102_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG102_13PL = 0xFFFF; данные MG102_13PL. */ +#define MG102_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G104PL >= G102PL) или (G104PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G104PL >= G102PL) || (G104PL == 0) +/* Задаёт MG102_14PL = ~(1 << 3); данные MG102_14PL. */ +#define MG102_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG102_14PL = 0xFFFF; данные MG102_14PL. */ +#define MG102_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G105PL >= G102PL) или (G105PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G105PL >= G102PL) || (G105PL == 0) +/* Задаёт MG102_15PL = ~(1 << 4); данные MG102_15PL. */ +#define MG102_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG102_15PL = 0xFFFF; данные MG102_15PL. */ +#define MG102_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G106PL >= G102PL) или (G106PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G106PL >= G102PL) || (G106PL == 0) +/* Задаёт MG102_16PL = ~(1 << 5); данные MG102_16PL. */ +#define MG102_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG102_16PL = 0xFFFF; данные MG102_16PL. */ +#define MG102_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G107PL >= G102PL) или (G107PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G107PL >= G102PL) || (G107PL == 0) +/* Задаёт MG102_17PL = ~(1 << 6); данные MG102_17PL. */ +#define MG102_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG102_17PL = 0xFFFF; данные MG102_17PL. */ +#define MG102_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G108PL >= G102PL) или (G108PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G108PL >= G102PL) || (G108PL == 0) +/* Задаёт MG102_18PL = ~(1 << 7); данные MG102_18PL. */ +#define MG102_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG102_18PL = 0xFFFF; данные MG102_18PL. */ +#define MG102_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG102_12PL = 0x00FD; данные MG102_12PL. */ +#define MG102_12PL 0x00FD +/* Задаёт MG102 = (MG102_11PL & MG102_12PL & MG102_13PL & MG102_14PL &; маска разрешённых прерываний внутри группы PIE 102. */ +#define MG102 (MG102_11PL & MG102_12PL & MG102_13PL & MG102_14PL & \ + MG102_15PL & MG102_16PL & MG102_17PL & MG102_18PL) /* Продолжает список аргументов, полей или выражение MG102_15PL & MG102_16PL & MG102_17PL & MG102_18PL); порядок элементов сохраняется. */ +// End of MG102: + +// Beginning of MG103: +/* Условие компиляции (G101PL >= G103PL) или (G101PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G101PL >= G103PL) || (G101PL == 0) +/* Задаёт MG103_11PL = ~(1); данные MG103_11PL. */ +#define MG103_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG103_11PL = 0xFFFF; данные MG103_11PL. */ +#define MG103_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G102PL >= G103PL) или (G102PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G102PL >= G103PL) || (G102PL == 0) +/* Задаёт MG103_12PL = ~(1 << 1); данные MG103_12PL. */ +#define MG103_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG103_12PL = 0xFFFF; данные MG103_12PL. */ +#define MG103_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G104PL >= G103PL) или (G104PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G104PL >= G103PL) || (G104PL == 0) +/* Задаёт MG103_14PL = ~(1 << 3); данные MG103_14PL. */ +#define MG103_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG103_14PL = 0xFFFF; данные MG103_14PL. */ +#define MG103_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G105PL >= G103PL) или (G105PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G105PL >= G103PL) || (G105PL == 0) +/* Задаёт MG103_15PL = ~(1 << 4); данные MG103_15PL. */ +#define MG103_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG103_15PL = 0xFFFF; данные MG103_15PL. */ +#define MG103_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G106PL >= G103PL) или (G106PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G106PL >= G103PL) || (G106PL == 0) +/* Задаёт MG103_16PL = ~(1 << 5); данные MG103_16PL. */ +#define MG103_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG103_16PL = 0xFFFF; данные MG103_16PL. */ +#define MG103_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G107PL >= G103PL) или (G107PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G107PL >= G103PL) || (G107PL == 0) +/* Задаёт MG103_17PL = ~(1 << 6); данные MG103_17PL. */ +#define MG103_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG103_17PL = 0xFFFF; данные MG103_17PL. */ +#define MG103_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G108PL >= G103PL) или (G108PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G108PL >= G103PL) || (G108PL == 0) +/* Задаёт MG103_18PL = ~(1 << 7); данные MG103_18PL. */ +#define MG103_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG103_18PL = 0xFFFF; данные MG103_18PL. */ +#define MG103_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG103_13PL = 0x00FB; данные MG103_13PL. */ +#define MG103_13PL 0x00FB +/* Задаёт MG103 = (MG103_11PL & MG103_12PL & MG103_13PL & MG103_14PL &; маска разрешённых прерываний внутри группы PIE 103. */ +#define MG103 (MG103_11PL & MG103_12PL & MG103_13PL & MG103_14PL & \ + MG103_15PL & MG103_16PL & MG103_17PL & MG103_18PL) /* Продолжает список аргументов, полей или выражение MG103_15PL & MG103_16PL & MG103_17PL & MG103_18PL); порядок элементов сохраняется. */ +// End of MG103: + +// Beginning of MG104: +/* Условие компиляции (G101PL >= G104PL) или (G101PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G101PL >= G104PL) || (G101PL == 0) +/* Задаёт MG104_11PL = ~(1); данные MG104_11PL. */ +#define MG104_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG104_11PL = 0xFFFF; данные MG104_11PL. */ +#define MG104_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G102PL >= G104PL) или (G102PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G102PL >= G104PL) || (G102PL == 0) +/* Задаёт MG104_12PL = ~(1 << 1); данные MG104_12PL. */ +#define MG104_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG104_12PL = 0xFFFF; данные MG104_12PL. */ +#define MG104_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G103PL >= G104PL) или (G103PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G103PL >= G104PL) || (G103PL == 0) +/* Задаёт MG104_13PL = ~(1 << 2); данные MG104_13PL. */ +#define MG104_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG104_13PL = 0xFFFF; данные MG104_13PL. */ +#define MG104_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G105PL >= G104PL) или (G105PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G105PL >= G104PL) || (G105PL == 0) +/* Задаёт MG104_15PL = ~(1 << 4); данные MG104_15PL. */ +#define MG104_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG104_15PL = 0xFFFF; данные MG104_15PL. */ +#define MG104_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G106PL >= G104PL) или (G106PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G106PL >= G104PL) || (G106PL == 0) +/* Задаёт MG104_16PL = ~(1 << 5); данные MG104_16PL. */ +#define MG104_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG104_16PL = 0xFFFF; данные MG104_16PL. */ +#define MG104_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G107PL >= G104PL) или (G107PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G107PL >= G104PL) || (G107PL == 0) +/* Задаёт MG104_17PL = ~(1 << 6); данные MG104_17PL. */ +#define MG104_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG104_17PL = 0xFFFF; данные MG104_17PL. */ +#define MG104_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G108PL >= G104PL) или (G108PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G108PL >= G104PL) || (G108PL == 0) +/* Задаёт MG104_18PL = ~(1 << 7); данные MG104_18PL. */ +#define MG104_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG104_18PL = 0xFFFF; данные MG104_18PL. */ +#define MG104_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG104_14PL = 0x00F7; данные MG104_14PL. */ +#define MG104_14PL 0x00F7 +/* Задаёт MG104 = (MG104_11PL & MG104_12PL & MG104_13PL & MG104_14PL &; маска разрешённых прерываний внутри группы PIE 104. */ +#define MG104 (MG104_11PL & MG104_12PL & MG104_13PL & MG104_14PL & \ + MG104_15PL & MG104_16PL & MG104_17PL & MG104_18PL) /* Продолжает список аргументов, полей или выражение MG104_15PL & MG104_16PL & MG104_17PL & MG104_18PL); порядок элементов сохраняется. */ +// End of MG104: + +// Beginning of MG105: +/* Условие компиляции (G101PL >= G105PL) или (G101PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G101PL >= G105PL) || (G101PL == 0) +/* Задаёт MG105_11PL = ~(1); данные MG105_11PL. */ +#define MG105_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG105_11PL = 0xFFFF; данные MG105_11PL. */ +#define MG105_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G102PL >= G105PL) или (G102PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G102PL >= G105PL) || (G102PL == 0) +/* Задаёт MG105_12PL = ~(1 << 1); данные MG105_12PL. */ +#define MG105_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG105_12PL = 0xFFFF; данные MG105_12PL. */ +#define MG105_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G103PL >= G105PL) или (G103PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G103PL >= G105PL) || (G103PL == 0) +/* Задаёт MG105_13PL = ~(1 << 2); данные MG105_13PL. */ +#define MG105_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG105_13PL = 0xFFFF; данные MG105_13PL. */ +#define MG105_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G104PL >= G105PL) или (G104PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G104PL >= G105PL) || (G104PL == 0) +/* Задаёт MG105_14PL = ~(1 << 3); данные MG105_14PL. */ +#define MG105_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG105_14PL = 0xFFFF; данные MG105_14PL. */ +#define MG105_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G106PL >= G105PL) или (G106PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G106PL >= G105PL) || (G106PL == 0) +/* Задаёт MG105_16PL = ~(1 << 5); данные MG105_16PL. */ +#define MG105_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG105_16PL = 0xFFFF; данные MG105_16PL. */ +#define MG105_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G107PL >= G105PL) или (G107PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G107PL >= G105PL) || (G107PL == 0) +/* Задаёт MG105_17PL = ~(1 << 6); данные MG105_17PL. */ +#define MG105_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG105_17PL = 0xFFFF; данные MG105_17PL. */ +#define MG105_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G108PL >= G105PL) или (G108PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G108PL >= G105PL) || (G108PL == 0) +/* Задаёт MG105_18PL = ~(1 << 7); данные MG105_18PL. */ +#define MG105_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG105_18PL = 0xFFFF; данные MG105_18PL. */ +#define MG105_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG105_15PL = 0x00EF; данные MG105_15PL. */ +#define MG105_15PL 0x00EF +/* Задаёт MG105 = (MG105_11PL & MG105_12PL & MG105_13PL & MG105_14PL &; маска разрешённых прерываний внутри группы PIE 105. */ +#define MG105 (MG105_11PL & MG105_12PL & MG105_13PL & MG105_14PL & \ + MG105_15PL & MG105_16PL & MG105_17PL & MG105_18PL) /* Продолжает список аргументов, полей или выражение MG105_15PL & MG105_16PL & MG105_17PL & MG105_18PL); порядок элементов сохраняется. */ +// End of MG105: + +// Beginning of MG106: +/* Условие компиляции (G101PL >= G106PL) или (G101PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G101PL >= G106PL) || (G101PL == 0) +/* Задаёт MG106_11PL = ~(1); данные MG106_11PL. */ +#define MG106_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG106_11PL = 0xFFFF; данные MG106_11PL. */ +#define MG106_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G102PL >= G106PL) или (G102PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G102PL >= G106PL) || (G102PL == 0) +/* Задаёт MG106_12PL = ~(1 << 1); данные MG106_12PL. */ +#define MG106_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG106_12PL = 0xFFFF; данные MG106_12PL. */ +#define MG106_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G103PL >= G106PL) или (G103PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G103PL >= G106PL) || (G103PL == 0) +/* Задаёт MG106_13PL = ~(1 << 2); данные MG106_13PL. */ +#define MG106_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG106_13PL = 0xFFFF; данные MG106_13PL. */ +#define MG106_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G104PL >= G106PL) или (G104PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G104PL >= G106PL) || (G104PL == 0) +/* Задаёт MG106_14PL = ~(1 << 3); данные MG106_14PL. */ +#define MG106_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG106_14PL = 0xFFFF; данные MG106_14PL. */ +#define MG106_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G105PL >= G106PL) или (G105PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G105PL >= G106PL) || (G105PL == 0) +/* Задаёт MG106_15PL = ~(1 << 4); данные MG106_15PL. */ +#define MG106_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG106_15PL = 0xFFFF; данные MG106_15PL. */ +#define MG106_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G107PL >= G106PL) или (G107PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G107PL >= G106PL) || (G107PL == 0) +/* Задаёт MG106_17PL = ~(1 << 6); данные MG106_17PL. */ +#define MG106_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG106_17PL = 0xFFFF; данные MG106_17PL. */ +#define MG106_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G108PL >= G106PL) или (G108PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G108PL >= G106PL) || (G108PL == 0) +/* Задаёт MG106_18PL = ~(1 << 7); данные MG106_18PL. */ +#define MG106_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG106_18PL = 0xFFFF; данные MG106_18PL. */ +#define MG106_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG106_16PL = 0x00DF; данные MG106_16PL. */ +#define MG106_16PL 0x00DF +/* Задаёт MG106 = (MG106_11PL & MG106_12PL & MG106_13PL & MG106_14PL &; маска разрешённых прерываний внутри группы PIE 106. */ +#define MG106 (MG106_11PL & MG106_12PL & MG106_13PL & MG106_14PL & \ + MG106_15PL & MG106_16PL & MG106_17PL & MG106_18PL) /* Продолжает список аргументов, полей или выражение MG106_15PL & MG106_16PL & MG106_17PL & MG106_18PL); порядок элементов сохраняется. */ +// End of MG106: + +// Beginning of MG107: +/* Условие компиляции (G101PL >= G107PL) или (G101PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G101PL >= G107PL) || (G101PL == 0) +/* Задаёт MG107_11PL = ~(1); данные MG107_11PL. */ +#define MG107_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG107_11PL = 0xFFFF; данные MG107_11PL. */ +#define MG107_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G102PL >= G107PL) или (G102PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G102PL >= G107PL) || (G102PL == 0) +/* Задаёт MG107_12PL = ~(1 << 1); данные MG107_12PL. */ +#define MG107_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG107_12PL = 0xFFFF; данные MG107_12PL. */ +#define MG107_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G103PL >= G107PL) или (G103PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G103PL >= G107PL) || (G103PL == 0) +/* Задаёт MG107_13PL = ~(1 << 2); данные MG107_13PL. */ +#define MG107_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG107_13PL = 0xFFFF; данные MG107_13PL. */ +#define MG107_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G104PL >= G107PL) или (G104PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G104PL >= G107PL) || (G104PL == 0) +/* Задаёт MG107_14PL = ~(1 << 3); данные MG107_14PL. */ +#define MG107_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG107_14PL = 0xFFFF; данные MG107_14PL. */ +#define MG107_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G105PL >= G107PL) или (G105PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G105PL >= G107PL) || (G105PL == 0) +/* Задаёт MG107_15PL = ~(1 << 4); данные MG107_15PL. */ +#define MG107_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG107_15PL = 0xFFFF; данные MG107_15PL. */ +#define MG107_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G106PL >= G107PL) или (G106PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G106PL >= G107PL) || (G106PL == 0) +/* Задаёт MG107_16PL = ~(1 << 5); данные MG107_16PL. */ +#define MG107_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG107_16PL = 0xFFFF; данные MG107_16PL. */ +#define MG107_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G108PL >= G107PL) или (G108PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G108PL >= G107PL) || (G108PL == 0) +/* Задаёт MG107_18PL = ~(1 << 7); данные MG107_18PL. */ +#define MG107_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG107_18PL = 0xFFFF; данные MG107_18PL. */ +#define MG107_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG107_17PL = 0x00BF; данные MG107_17PL. */ +#define MG107_17PL 0x00BF +/* Задаёт MG107 = (MG107_11PL & MG107_12PL & MG107_13PL & MG107_14PL &; маска разрешённых прерываний внутри группы PIE 107. */ +#define MG107 (MG107_11PL & MG107_12PL & MG107_13PL & MG107_14PL & \ + MG107_15PL & MG107_16PL & MG107_17PL & MG107_18PL) /* Продолжает список аргументов, полей или выражение MG107_15PL & MG107_16PL & MG107_17PL & MG107_18PL); порядок элементов сохраняется. */ +// End of MG107: + +// Beginning of MG108: +/* Условие компиляции (G101PL >= G108PL) или (G101PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G101PL >= G108PL) || (G101PL == 0) +/* Задаёт MG108_11PL = ~(1); данные MG108_11PL. */ +#define MG108_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG108_11PL = 0xFFFF; данные MG108_11PL. */ +#define MG108_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G102PL >= G108PL) или (G102PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G102PL >= G108PL) || (G102PL == 0) +/* Задаёт MG108_12PL = ~(1 << 1); данные MG108_12PL. */ +#define MG108_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG108_12PL = 0xFFFF; данные MG108_12PL. */ +#define MG108_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G103PL >= G108PL) или (G103PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G103PL >= G108PL) || (G103PL == 0) +/* Задаёт MG108_13PL = ~(1 << 2); данные MG108_13PL. */ +#define MG108_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG108_13PL = 0xFFFF; данные MG108_13PL. */ +#define MG108_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G104PL >= G108PL) или (G104PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G104PL >= G108PL) || (G104PL == 0) +/* Задаёт MG108_14PL = ~(1 << 3); данные MG108_14PL. */ +#define MG108_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG108_14PL = 0xFFFF; данные MG108_14PL. */ +#define MG108_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G105PL >= G108PL) или (G105PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G105PL >= G108PL) || (G105PL == 0) +/* Задаёт MG108_15PL = ~(1 << 4); данные MG108_15PL. */ +#define MG108_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG108_15PL = 0xFFFF; данные MG108_15PL. */ +#define MG108_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G106PL >= G108PL) или (G106PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G106PL >= G108PL) || (G106PL == 0) +/* Задаёт MG108_16PL = ~(1 << 5); данные MG108_16PL. */ +#define MG108_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG108_16PL = 0xFFFF; данные MG108_16PL. */ +#define MG108_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G107PL >= G108PL) или (G107PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G107PL >= G108PL) || (G107PL == 0) +/* Задаёт MG108_17PL = ~(1 << 6); данные MG108_17PL. */ +#define MG108_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG108_17PL = 0xFFFF; данные MG108_17PL. */ +#define MG108_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG108_18PL = 0x007F; данные MG108_18PL. */ +#define MG108_18PL 0x007F +/* Задаёт MG108 = (MG108_11PL & MG108_12PL & MG108_13PL & MG108_14PL &; маска разрешённых прерываний внутри группы PIE 108. */ +#define MG108 (MG108_11PL & MG108_12PL & MG108_13PL & MG108_14PL & \ + MG108_15PL & MG108_16PL & MG108_17PL & MG108_18PL) /* Продолжает список аргументов, полей или выражение MG108_15PL & MG108_16PL & MG108_17PL & MG108_18PL); порядок элементов сохраняется. */ +// End of MG108: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG111 to MG118: +// + +// Beginning of MG111: +/* Условие компиляции (G112PL >= G111PL) или (G112PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G112PL >= G111PL) || (G112PL == 0) +/* Задаёт MG111_12PL = ~(1 << 1); данные MG111_12PL. */ +#define MG111_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG111_12PL = 0xFFFF; данные MG111_12PL. */ +#define MG111_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G113PL >= G111PL) или (G113PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G113PL >= G111PL) || (G113PL == 0) +/* Задаёт MG111_13PL = ~(1 << 2); данные MG111_13PL. */ +#define MG111_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG111_13PL = 0xFFFF; данные MG111_13PL. */ +#define MG111_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G114PL >= G111PL) или (G114PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G114PL >= G111PL) || (G114PL == 0) +/* Задаёт MG111_14PL = ~(1 << 3); данные MG111_14PL. */ +#define MG111_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG111_14PL = 0xFFFF; данные MG111_14PL. */ +#define MG111_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G115PL >= G111PL) или (G115PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G115PL >= G111PL) || (G115PL == 0) +/* Задаёт MG111_15PL = ~(1 << 4); данные MG111_15PL. */ +#define MG111_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG111_15PL = 0xFFFF; данные MG111_15PL. */ +#define MG111_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G116PL >= G111PL) или (G116PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G116PL >= G111PL) || (G116PL == 0) +/* Задаёт MG111_16PL = ~(1 << 5); данные MG111_16PL. */ +#define MG111_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG111_16PL = 0xFFFF; данные MG111_16PL. */ +#define MG111_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G117PL >= G111PL) или (G117PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G117PL >= G111PL) || (G117PL == 0) +/* Задаёт MG111_17PL = ~(1 << 6); данные MG111_17PL. */ +#define MG111_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG111_17PL = 0xFFFF; данные MG111_17PL. */ +#define MG111_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G118PL >= G111PL) или (G118PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G118PL >= G111PL) || (G118PL == 0) +/* Задаёт MG111_18PL = ~(1 << 7); данные MG111_18PL. */ +#define MG111_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG111_18PL = 0xFFFF; данные MG111_18PL. */ +#define MG111_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG111_11PL = 0x00FE; данные MG111_11PL. */ +#define MG111_11PL 0x00FE +/* Задаёт MG111 = (MG111_11PL & MG111_12PL & MG111_13PL & MG111_14PL &; маска разрешённых прерываний внутри группы PIE 111. */ +#define MG111 (MG111_11PL & MG111_12PL & MG111_13PL & MG111_14PL & \ + MG111_15PL & MG111_16PL & MG111_17PL & MG111_18PL) /* Продолжает список аргументов, полей или выражение MG111_15PL & MG111_16PL & MG111_17PL & MG111_18PL); порядок элементов сохраняется. */ +// End of MG111: + +// Beginning of MG112: +/* Условие компиляции (G111PL >= G112PL) или (G111PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G111PL >= G112PL) || (G111PL == 0) +/* Задаёт MG112_11PL = ~(1); данные MG112_11PL. */ +#define MG112_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG112_11PL = 0xFFFF; данные MG112_11PL. */ +#define MG112_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G113PL >= G112PL) или (G113PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G113PL >= G112PL) || (G113PL == 0) +/* Задаёт MG112_13PL = ~(1 << 2); данные MG112_13PL. */ +#define MG112_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG112_13PL = 0xFFFF; данные MG112_13PL. */ +#define MG112_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G114PL >= G112PL) или (G114PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G114PL >= G112PL) || (G114PL == 0) +/* Задаёт MG112_14PL = ~(1 << 3); данные MG112_14PL. */ +#define MG112_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG112_14PL = 0xFFFF; данные MG112_14PL. */ +#define MG112_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G115PL >= G112PL) или (G115PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G115PL >= G112PL) || (G115PL == 0) +/* Задаёт MG112_15PL = ~(1 << 4); данные MG112_15PL. */ +#define MG112_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG112_15PL = 0xFFFF; данные MG112_15PL. */ +#define MG112_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G116PL >= G112PL) или (G116PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G116PL >= G112PL) || (G116PL == 0) +/* Задаёт MG112_16PL = ~(1 << 5); данные MG112_16PL. */ +#define MG112_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG112_16PL = 0xFFFF; данные MG112_16PL. */ +#define MG112_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G117PL >= G112PL) или (G117PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G117PL >= G112PL) || (G117PL == 0) +/* Задаёт MG112_17PL = ~(1 << 6); данные MG112_17PL. */ +#define MG112_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG112_17PL = 0xFFFF; данные MG112_17PL. */ +#define MG112_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G118PL >= G112PL) или (G118PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G118PL >= G112PL) || (G118PL == 0) +/* Задаёт MG112_18PL = ~(1 << 7); данные MG112_18PL. */ +#define MG112_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG112_18PL = 0xFFFF; данные MG112_18PL. */ +#define MG112_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG112_12PL = 0x00FD; данные MG112_12PL. */ +#define MG112_12PL 0x00FD +/* Задаёт MG112 = (MG112_11PL & MG112_12PL & MG112_13PL & MG112_14PL &; маска разрешённых прерываний внутри группы PIE 112. */ +#define MG112 (MG112_11PL & MG112_12PL & MG112_13PL & MG112_14PL & \ + MG112_15PL & MG112_16PL & MG112_17PL & MG112_18PL) /* Продолжает список аргументов, полей или выражение MG112_15PL & MG112_16PL & MG112_17PL & MG112_18PL); порядок элементов сохраняется. */ +// End of MG112: + +// Beginning of MG113: +/* Условие компиляции (G111PL >= G113PL) или (G111PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G111PL >= G113PL) || (G111PL == 0) +/* Задаёт MG113_11PL = ~(1); данные MG113_11PL. */ +#define MG113_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG113_11PL = 0xFFFF; данные MG113_11PL. */ +#define MG113_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G112PL >= G113PL) или (G112PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G112PL >= G113PL) || (G112PL == 0) +/* Задаёт MG113_12PL = ~(1 << 1); данные MG113_12PL. */ +#define MG113_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG113_12PL = 0xFFFF; данные MG113_12PL. */ +#define MG113_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G114PL >= G113PL) или (G114PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G114PL >= G113PL) || (G114PL == 0) +/* Задаёт MG113_14PL = ~(1 << 3); данные MG113_14PL. */ +#define MG113_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG113_14PL = 0xFFFF; данные MG113_14PL. */ +#define MG113_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G115PL >= G113PL) или (G115PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G115PL >= G113PL) || (G115PL == 0) +/* Задаёт MG113_15PL = ~(1 << 4); данные MG113_15PL. */ +#define MG113_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG113_15PL = 0xFFFF; данные MG113_15PL. */ +#define MG113_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G116PL >= G113PL) или (G116PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G116PL >= G113PL) || (G116PL == 0) +/* Задаёт MG113_16PL = ~(1 << 5); данные MG113_16PL. */ +#define MG113_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG113_16PL = 0xFFFF; данные MG113_16PL. */ +#define MG113_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G117PL >= G113PL) или (G117PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G117PL >= G113PL) || (G117PL == 0) +/* Задаёт MG113_17PL = ~(1 << 6); данные MG113_17PL. */ +#define MG113_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG113_17PL = 0xFFFF; данные MG113_17PL. */ +#define MG113_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G118PL >= G113PL) или (G118PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G118PL >= G113PL) || (G118PL == 0) +/* Задаёт MG113_18PL = ~(1 << 7); данные MG113_18PL. */ +#define MG113_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG113_18PL = 0xFFFF; данные MG113_18PL. */ +#define MG113_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG113_13PL = 0x00FB; данные MG113_13PL. */ +#define MG113_13PL 0x00FB +/* Задаёт MG113 = (MG113_11PL & MG113_12PL & MG113_13PL & MG113_14PL &; маска разрешённых прерываний внутри группы PIE 113. */ +#define MG113 (MG113_11PL & MG113_12PL & MG113_13PL & MG113_14PL & \ + MG113_15PL & MG113_16PL & MG113_17PL & MG113_18PL) /* Продолжает список аргументов, полей или выражение MG113_15PL & MG113_16PL & MG113_17PL & MG113_18PL); порядок элементов сохраняется. */ +// End of MG113: + +// Beginning of MG114: +/* Условие компиляции (G111PL >= G114PL) или (G111PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G111PL >= G114PL) || (G111PL == 0) +/* Задаёт MG114_11PL = ~(1); данные MG114_11PL. */ +#define MG114_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG114_11PL = 0xFFFF; данные MG114_11PL. */ +#define MG114_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G112PL >= G114PL) или (G112PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G112PL >= G114PL) || (G112PL == 0) +/* Задаёт MG114_12PL = ~(1 << 1); данные MG114_12PL. */ +#define MG114_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG114_12PL = 0xFFFF; данные MG114_12PL. */ +#define MG114_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G113PL >= G114PL) или (G113PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G113PL >= G114PL) || (G113PL == 0) +/* Задаёт MG114_13PL = ~(1 << 2); данные MG114_13PL. */ +#define MG114_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG114_13PL = 0xFFFF; данные MG114_13PL. */ +#define MG114_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G115PL >= G114PL) или (G115PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G115PL >= G114PL) || (G115PL == 0) +/* Задаёт MG114_15PL = ~(1 << 4); данные MG114_15PL. */ +#define MG114_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG114_15PL = 0xFFFF; данные MG114_15PL. */ +#define MG114_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G116PL >= G114PL) или (G116PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G116PL >= G114PL) || (G116PL == 0) +/* Задаёт MG114_16PL = ~(1 << 5); данные MG114_16PL. */ +#define MG114_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG114_16PL = 0xFFFF; данные MG114_16PL. */ +#define MG114_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G117PL >= G114PL) или (G117PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G117PL >= G114PL) || (G117PL == 0) +/* Задаёт MG114_17PL = ~(1 << 6); данные MG114_17PL. */ +#define MG114_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG114_17PL = 0xFFFF; данные MG114_17PL. */ +#define MG114_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G118PL >= G114PL) или (G118PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G118PL >= G114PL) || (G118PL == 0) +/* Задаёт MG114_18PL = ~(1 << 7); данные MG114_18PL. */ +#define MG114_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG114_18PL = 0xFFFF; данные MG114_18PL. */ +#define MG114_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG114_14PL = 0x00F7; данные MG114_14PL. */ +#define MG114_14PL 0x00F7 +/* Задаёт MG114 = (MG114_11PL & MG114_12PL & MG114_13PL & MG114_14PL &; маска разрешённых прерываний внутри группы PIE 114. */ +#define MG114 (MG114_11PL & MG114_12PL & MG114_13PL & MG114_14PL & \ + MG114_15PL & MG114_16PL & MG114_17PL & MG114_18PL) /* Продолжает список аргументов, полей или выражение MG114_15PL & MG114_16PL & MG114_17PL & MG114_18PL); порядок элементов сохраняется. */ +// End of MG114: + +// Beginning of MG115: +/* Условие компиляции (G111PL >= G115PL) или (G111PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G111PL >= G115PL) || (G111PL == 0) +/* Задаёт MG115_11PL = ~(1); данные MG115_11PL. */ +#define MG115_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG115_11PL = 0xFFFF; данные MG115_11PL. */ +#define MG115_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G112PL >= G115PL) или (G112PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G112PL >= G115PL) || (G112PL == 0) +/* Задаёт MG115_12PL = ~(1 << 1); данные MG115_12PL. */ +#define MG115_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG115_12PL = 0xFFFF; данные MG115_12PL. */ +#define MG115_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G113PL >= G115PL) или (G113PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G113PL >= G115PL) || (G113PL == 0) +/* Задаёт MG115_13PL = ~(1 << 2); данные MG115_13PL. */ +#define MG115_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG115_13PL = 0xFFFF; данные MG115_13PL. */ +#define MG115_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G114PL >= G115PL) или (G114PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G114PL >= G115PL) || (G114PL == 0) +/* Задаёт MG115_14PL = ~(1 << 3); данные MG115_14PL. */ +#define MG115_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG115_14PL = 0xFFFF; данные MG115_14PL. */ +#define MG115_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G116PL >= G115PL) или (G116PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G116PL >= G115PL) || (G116PL == 0) +/* Задаёт MG115_16PL = ~(1 << 5); данные MG115_16PL. */ +#define MG115_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG115_16PL = 0xFFFF; данные MG115_16PL. */ +#define MG115_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G117PL >= G115PL) или (G117PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G117PL >= G115PL) || (G117PL == 0) +/* Задаёт MG115_17PL = ~(1 << 6); данные MG115_17PL. */ +#define MG115_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG115_17PL = 0xFFFF; данные MG115_17PL. */ +#define MG115_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G118PL >= G115PL) или (G118PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G118PL >= G115PL) || (G118PL == 0) +/* Задаёт MG115_18PL = ~(1 << 7); данные MG115_18PL. */ +#define MG115_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG115_18PL = 0xFFFF; данные MG115_18PL. */ +#define MG115_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG115_15PL = 0x00EF; данные MG115_15PL. */ +#define MG115_15PL 0x00EF +/* Задаёт MG115 = (MG115_11PL & MG115_12PL & MG115_13PL & MG115_14PL &; маска разрешённых прерываний внутри группы PIE 115. */ +#define MG115 (MG115_11PL & MG115_12PL & MG115_13PL & MG115_14PL & \ + MG115_15PL & MG115_16PL & MG115_17PL & MG115_18PL) /* Продолжает список аргументов, полей или выражение MG115_15PL & MG115_16PL & MG115_17PL & MG115_18PL); порядок элементов сохраняется. */ +// End of MG115: + +// Beginning of MG116: +/* Условие компиляции (G111PL >= G116PL) или (G111PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G111PL >= G116PL) || (G111PL == 0) +/* Задаёт MG116_11PL = ~(1); данные MG116_11PL. */ +#define MG116_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG116_11PL = 0xFFFF; данные MG116_11PL. */ +#define MG116_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G112PL >= G116PL) или (G112PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G112PL >= G116PL) || (G112PL == 0) +/* Задаёт MG116_12PL = ~(1 << 1); данные MG116_12PL. */ +#define MG116_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG116_12PL = 0xFFFF; данные MG116_12PL. */ +#define MG116_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G113PL >= G116PL) или (G113PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G113PL >= G116PL) || (G113PL == 0) +/* Задаёт MG116_13PL = ~(1 << 2); данные MG116_13PL. */ +#define MG116_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG116_13PL = 0xFFFF; данные MG116_13PL. */ +#define MG116_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G114PL >= G116PL) или (G114PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G114PL >= G116PL) || (G114PL == 0) +/* Задаёт MG116_14PL = ~(1 << 3); данные MG116_14PL. */ +#define MG116_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG116_14PL = 0xFFFF; данные MG116_14PL. */ +#define MG116_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G115PL >= G116PL) или (G115PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G115PL >= G116PL) || (G115PL == 0) +/* Задаёт MG116_15PL = ~(1 << 4); данные MG116_15PL. */ +#define MG116_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG116_15PL = 0xFFFF; данные MG116_15PL. */ +#define MG116_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G117PL >= G116PL) или (G117PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G117PL >= G116PL) || (G117PL == 0) +/* Задаёт MG116_17PL = ~(1 << 6); данные MG116_17PL. */ +#define MG116_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG116_17PL = 0xFFFF; данные MG116_17PL. */ +#define MG116_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G118PL >= G116PL) или (G118PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G118PL >= G116PL) || (G118PL == 0) +/* Задаёт MG116_18PL = ~(1 << 7); данные MG116_18PL. */ +#define MG116_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG116_18PL = 0xFFFF; данные MG116_18PL. */ +#define MG116_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG116_16PL = 0x00DF; данные MG116_16PL. */ +#define MG116_16PL 0x00DF +/* Задаёт MG116 = (MG116_11PL & MG116_12PL & MG116_13PL & MG116_14PL &; маска разрешённых прерываний внутри группы PIE 116. */ +#define MG116 (MG116_11PL & MG116_12PL & MG116_13PL & MG116_14PL & \ + MG116_15PL & MG116_16PL & MG116_17PL & MG116_18PL) /* Продолжает список аргументов, полей или выражение MG116_15PL & MG116_16PL & MG116_17PL & MG116_18PL); порядок элементов сохраняется. */ +// End of MG116: + +// Beginning of MG117: +/* Условие компиляции (G111PL >= G117PL) или (G111PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G111PL >= G117PL) || (G111PL == 0) +/* Задаёт MG117_11PL = ~(1); данные MG117_11PL. */ +#define MG117_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG117_11PL = 0xFFFF; данные MG117_11PL. */ +#define MG117_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G112PL >= G117PL) или (G112PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G112PL >= G117PL) || (G112PL == 0) +/* Задаёт MG117_12PL = ~(1 << 1); данные MG117_12PL. */ +#define MG117_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG117_12PL = 0xFFFF; данные MG117_12PL. */ +#define MG117_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G113PL >= G117PL) или (G113PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G113PL >= G117PL) || (G113PL == 0) +/* Задаёт MG117_13PL = ~(1 << 2); данные MG117_13PL. */ +#define MG117_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG117_13PL = 0xFFFF; данные MG117_13PL. */ +#define MG117_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G114PL >= G117PL) или (G114PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G114PL >= G117PL) || (G114PL == 0) +/* Задаёт MG117_14PL = ~(1 << 3); данные MG117_14PL. */ +#define MG117_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG117_14PL = 0xFFFF; данные MG117_14PL. */ +#define MG117_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G115PL >= G117PL) или (G115PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G115PL >= G117PL) || (G115PL == 0) +/* Задаёт MG117_15PL = ~(1 << 4); данные MG117_15PL. */ +#define MG117_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG117_15PL = 0xFFFF; данные MG117_15PL. */ +#define MG117_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G116PL >= G117PL) или (G116PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G116PL >= G117PL) || (G116PL == 0) +/* Задаёт MG117_16PL = ~(1 << 5); данные MG117_16PL. */ +#define MG117_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG117_16PL = 0xFFFF; данные MG117_16PL. */ +#define MG117_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G118PL >= G117PL) или (G118PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G118PL >= G117PL) || (G118PL == 0) +/* Задаёт MG117_18PL = ~(1 << 7); данные MG117_18PL. */ +#define MG117_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG117_18PL = 0xFFFF; данные MG117_18PL. */ +#define MG117_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG117_17PL = 0x00BF; данные MG117_17PL. */ +#define MG117_17PL 0x00BF +/* Задаёт MG117 = (MG117_11PL & MG117_12PL & MG117_13PL & MG117_14PL &; маска разрешённых прерываний внутри группы PIE 117. */ +#define MG117 (MG117_11PL & MG117_12PL & MG117_13PL & MG117_14PL & \ + MG117_15PL & MG117_16PL & MG117_17PL & MG117_18PL) /* Продолжает список аргументов, полей или выражение MG117_15PL & MG117_16PL & MG117_17PL & MG117_18PL); порядок элементов сохраняется. */ +// End of MG117: + +// Beginning of MG118: +/* Условие компиляции (G111PL >= G118PL) или (G111PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G111PL >= G118PL) || (G111PL == 0) +/* Задаёт MG118_11PL = ~(1); данные MG118_11PL. */ +#define MG118_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG118_11PL = 0xFFFF; данные MG118_11PL. */ +#define MG118_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G112PL >= G118PL) или (G112PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G112PL >= G118PL) || (G112PL == 0) +/* Задаёт MG118_12PL = ~(1 << 1); данные MG118_12PL. */ +#define MG118_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG118_12PL = 0xFFFF; данные MG118_12PL. */ +#define MG118_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G113PL >= G118PL) или (G113PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G113PL >= G118PL) || (G113PL == 0) +/* Задаёт MG118_13PL = ~(1 << 2); данные MG118_13PL. */ +#define MG118_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG118_13PL = 0xFFFF; данные MG118_13PL. */ +#define MG118_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G114PL >= G118PL) или (G114PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G114PL >= G118PL) || (G114PL == 0) +/* Задаёт MG118_14PL = ~(1 << 3); данные MG118_14PL. */ +#define MG118_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG118_14PL = 0xFFFF; данные MG118_14PL. */ +#define MG118_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G115PL >= G118PL) или (G115PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G115PL >= G118PL) || (G115PL == 0) +/* Задаёт MG118_15PL = ~(1 << 4); данные MG118_15PL. */ +#define MG118_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG118_15PL = 0xFFFF; данные MG118_15PL. */ +#define MG118_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G116PL >= G118PL) или (G116PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G116PL >= G118PL) || (G116PL == 0) +/* Задаёт MG118_16PL = ~(1 << 5); данные MG118_16PL. */ +#define MG118_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG118_16PL = 0xFFFF; данные MG118_16PL. */ +#define MG118_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G117PL >= G118PL) или (G117PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G117PL >= G118PL) || (G117PL == 0) +/* Задаёт MG118_17PL = ~(1 << 6); данные MG118_17PL. */ +#define MG118_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG118_17PL = 0xFFFF; данные MG118_17PL. */ +#define MG118_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG118_18PL = 0x007F; данные MG118_18PL. */ +#define MG118_18PL 0x007F +/* Задаёт MG118 = (MG118_11PL & MG118_12PL & MG118_13PL & MG118_14PL &; маска разрешённых прерываний внутри группы PIE 118. */ +#define MG118 (MG118_11PL & MG118_12PL & MG118_13PL & MG118_14PL & \ + MG118_15PL & MG118_16PL & MG118_17PL & MG118_18PL) /* Продолжает список аргументов, полей или выражение MG118_15PL & MG118_16PL & MG118_17PL & MG118_18PL); порядок элементов сохраняется. */ +// End of MG118: + +//------------------------------------------------------------------------------- +// Automatically generate PIEIER1 interrupt masks MG121 to MG128: +// + +// Beginning of MG121: +/* Условие компиляции (G122PL >= G121PL) или (G122PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G122PL >= G121PL) || (G122PL == 0) +/* Задаёт MG121_12PL = ~(1 << 1); данные MG121_12PL. */ +#define MG121_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG121_12PL = 0xFFFF; данные MG121_12PL. */ +#define MG121_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G123PL >= G121PL) или (G123PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G123PL >= G121PL) || (G123PL == 0) +/* Задаёт MG121_13PL = ~(1 << 2); данные MG121_13PL. */ +#define MG121_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG121_13PL = 0xFFFF; данные MG121_13PL. */ +#define MG121_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G124PL >= G121PL) или (G124PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G124PL >= G121PL) || (G124PL == 0) +/* Задаёт MG121_14PL = ~(1 << 3); данные MG121_14PL. */ +#define MG121_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG121_14PL = 0xFFFF; данные MG121_14PL. */ +#define MG121_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G125PL >= G121PL) или (G125PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G125PL >= G121PL) || (G125PL == 0) +/* Задаёт MG121_15PL = ~(1 << 4); данные MG121_15PL. */ +#define MG121_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG121_15PL = 0xFFFF; данные MG121_15PL. */ +#define MG121_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G126PL >= G121PL) или (G126PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G126PL >= G121PL) || (G126PL == 0) +/* Задаёт MG121_16PL = ~(1 << 5); данные MG121_16PL. */ +#define MG121_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG121_16PL = 0xFFFF; данные MG121_16PL. */ +#define MG121_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G127PL >= G121PL) или (G127PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G127PL >= G121PL) || (G127PL == 0) +/* Задаёт MG121_17PL = ~(1 << 6); данные MG121_17PL. */ +#define MG121_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG121_17PL = 0xFFFF; данные MG121_17PL. */ +#define MG121_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G128PL >= G121PL) или (G128PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G128PL >= G121PL) || (G128PL == 0) +/* Задаёт MG121_18PL = ~(1 << 7); данные MG121_18PL. */ +#define MG121_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG121_18PL = 0xFFFF; данные MG121_18PL. */ +#define MG121_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG121_11PL = 0x00FE; данные MG121_11PL. */ +#define MG121_11PL 0x00FE +/* Задаёт MG121 = (MG121_11PL & MG121_12PL & MG121_13PL & MG121_14PL &; маска разрешённых прерываний внутри группы PIE 121. */ +#define MG121 (MG121_11PL & MG121_12PL & MG121_13PL & MG121_14PL & \ + MG121_15PL & MG121_16PL & MG121_17PL & MG121_18PL) /* Продолжает список аргументов, полей или выражение MG121_15PL & MG121_16PL & MG121_17PL & MG121_18PL); порядок элементов сохраняется. */ +// End of MG121: + +// Beginning of MG121: +/* Условие компиляции (G121PL >= G122PL) или (G121PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G121PL >= G122PL) || (G121PL == 0) +/* Задаёт MG122_11PL = ~(1); данные MG122_11PL. */ +#define MG122_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG122_11PL = 0xFFFF; данные MG122_11PL. */ +#define MG122_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G123PL >= G122PL) или (G123PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G123PL >= G122PL) || (G123PL == 0) +/* Задаёт MG122_13PL = ~(1 << 2); данные MG122_13PL. */ +#define MG122_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG122_13PL = 0xFFFF; данные MG122_13PL. */ +#define MG122_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G124PL >= G122PL) или (G124PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G124PL >= G122PL) || (G124PL == 0) +/* Задаёт MG122_14PL = ~(1 << 3); данные MG122_14PL. */ +#define MG122_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG122_14PL = 0xFFFF; данные MG122_14PL. */ +#define MG122_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G125PL >= G122PL) или (G125PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G125PL >= G122PL) || (G125PL == 0) +/* Задаёт MG122_15PL = ~(1 << 4); данные MG122_15PL. */ +#define MG122_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG122_15PL = 0xFFFF; данные MG122_15PL. */ +#define MG122_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G126PL >= G122PL) или (G126PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G126PL >= G122PL) || (G126PL == 0) +/* Задаёт MG122_16PL = ~(1 << 5); данные MG122_16PL. */ +#define MG122_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG122_16PL = 0xFFFF; данные MG122_16PL. */ +#define MG122_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G127PL >= G122PL) или (G127PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G127PL >= G122PL) || (G127PL == 0) +/* Задаёт MG122_17PL = ~(1 << 6); данные MG122_17PL. */ +#define MG122_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG122_17PL = 0xFFFF; данные MG122_17PL. */ +#define MG122_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G128PL >= G122PL) или (G128PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G128PL >= G122PL) || (G128PL == 0) +/* Задаёт MG122_18PL = ~(1 << 7); данные MG122_18PL. */ +#define MG122_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG122_18PL = 0xFFFF; данные MG122_18PL. */ +#define MG122_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG122_12PL = 0x00FD; данные MG122_12PL. */ +#define MG122_12PL 0x00FD +/* Задаёт MG122 = (MG122_11PL & MG122_12PL & MG122_13PL & MG122_14PL &; маска разрешённых прерываний внутри группы PIE 122. */ +#define MG122 (MG122_11PL & MG122_12PL & MG122_13PL & MG122_14PL & \ + MG122_15PL & MG122_16PL & MG122_17PL & MG122_18PL) /* Продолжает список аргументов, полей или выражение MG122_15PL & MG122_16PL & MG122_17PL & MG122_18PL); порядок элементов сохраняется. */ +// End of MG122: + +// Beginning of MG123: +/* Условие компиляции (G121PL >= G123PL) или (G121PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G121PL >= G123PL) || (G121PL == 0) +/* Задаёт MG123_11PL = ~(1); данные MG123_11PL. */ +#define MG123_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG123_11PL = 0xFFFF; данные MG123_11PL. */ +#define MG123_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G122PL >= G123PL) или (G122PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G122PL >= G123PL) || (G122PL == 0) +/* Задаёт MG123_12PL = ~(1 << 1); данные MG123_12PL. */ +#define MG123_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG123_12PL = 0xFFFF; данные MG123_12PL. */ +#define MG123_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G124PL >= G123PL) или (G124PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G124PL >= G123PL) || (G124PL == 0) +/* Задаёт MG123_14PL = ~(1 << 3); данные MG123_14PL. */ +#define MG123_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG123_14PL = 0xFFFF; данные MG123_14PL. */ +#define MG123_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G125PL >= G123PL) или (G125PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G125PL >= G123PL) || (G125PL == 0) +/* Задаёт MG123_15PL = ~(1 << 4); данные MG123_15PL. */ +#define MG123_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG123_15PL = 0xFFFF; данные MG123_15PL. */ +#define MG123_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G126PL >= G123PL) или (G126PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G126PL >= G123PL) || (G126PL == 0) +/* Задаёт MG123_16PL = ~(1 << 5); данные MG123_16PL. */ +#define MG123_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG123_16PL = 0xFFFF; данные MG123_16PL. */ +#define MG123_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G127PL >= G123PL) или (G127PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G127PL >= G123PL) || (G127PL == 0) +/* Задаёт MG123_17PL = ~(1 << 6); данные MG123_17PL. */ +#define MG123_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG123_17PL = 0xFFFF; данные MG123_17PL. */ +#define MG123_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G128PL >= G123PL) или (G128PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G128PL >= G123PL) || (G128PL == 0) +/* Задаёт MG123_18PL = ~(1 << 7); данные MG123_18PL. */ +#define MG123_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG123_18PL = 0xFFFF; данные MG123_18PL. */ +#define MG123_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG123_13PL = 0x00FB; данные MG123_13PL. */ +#define MG123_13PL 0x00FB +/* Задаёт MG123 = (MG123_11PL & MG123_12PL & MG123_13PL & MG123_14PL &; маска разрешённых прерываний внутри группы PIE 123. */ +#define MG123 (MG123_11PL & MG123_12PL & MG123_13PL & MG123_14PL & \ + MG123_15PL & MG123_16PL & MG123_17PL & MG123_18PL) /* Продолжает список аргументов, полей или выражение MG123_15PL & MG123_16PL & MG123_17PL & MG123_18PL); порядок элементов сохраняется. */ +// End of MG123: + +// Beginning of MG124: +/* Условие компиляции (G121PL >= G124PL) или (G121PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G121PL >= G124PL) || (G121PL == 0) +/* Задаёт MG124_11PL = ~(1); данные MG124_11PL. */ +#define MG124_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG124_11PL = 0xFFFF; данные MG124_11PL. */ +#define MG124_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G122PL >= G124PL) или (G122PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G122PL >= G124PL) || (G122PL == 0) +/* Задаёт MG124_12PL = ~(1 << 1); данные MG124_12PL. */ +#define MG124_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG124_12PL = 0xFFFF; данные MG124_12PL. */ +#define MG124_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G123PL >= G124PL) или (G123PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G123PL >= G124PL) || (G123PL == 0) +/* Задаёт MG124_13PL = ~(1 << 2); данные MG124_13PL. */ +#define MG124_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG124_13PL = 0xFFFF; данные MG124_13PL. */ +#define MG124_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G125PL >= G124PL) или (G125PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G125PL >= G124PL) || (G125PL == 0) +/* Задаёт MG124_15PL = ~(1 << 4); данные MG124_15PL. */ +#define MG124_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG124_15PL = 0xFFFF; данные MG124_15PL. */ +#define MG124_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G126PL >= G124PL) или (G126PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G126PL >= G124PL) || (G126PL == 0) +/* Задаёт MG124_16PL = ~(1 << 5); данные MG124_16PL. */ +#define MG124_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG124_16PL = 0xFFFF; данные MG124_16PL. */ +#define MG124_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G127PL >= G124PL) или (G127PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G127PL >= G124PL) || (G127PL == 0) +/* Задаёт MG124_17PL = ~(1 << 6); данные MG124_17PL. */ +#define MG124_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG124_17PL = 0xFFFF; данные MG124_17PL. */ +#define MG124_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G128PL >= G124PL) или (G128PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G128PL >= G124PL) || (G128PL == 0) +/* Задаёт MG124_18PL = ~(1 << 7); данные MG124_18PL. */ +#define MG124_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG124_18PL = 0xFFFF; данные MG124_18PL. */ +#define MG124_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG124_14PL = 0x00F7; данные MG124_14PL. */ +#define MG124_14PL 0x00F7 +/* Задаёт MG124 = (MG124_11PL & MG124_12PL & MG124_13PL & MG124_14PL &; маска разрешённых прерываний внутри группы PIE 124. */ +#define MG124 (MG124_11PL & MG124_12PL & MG124_13PL & MG124_14PL & \ + MG124_15PL & MG124_16PL & MG124_17PL & MG124_18PL) /* Продолжает список аргументов, полей или выражение MG124_15PL & MG124_16PL & MG124_17PL & MG124_18PL); порядок элементов сохраняется. */ +// End of MG124: + +// Beginning of MG125: +/* Условие компиляции (G121PL >= G125PL) или (G121PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G121PL >= G125PL) || (G121PL == 0) +/* Задаёт MG125_11PL = ~(1); данные MG125_11PL. */ +#define MG125_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG125_11PL = 0xFFFF; данные MG125_11PL. */ +#define MG125_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G122PL >= G125PL) или (G122PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G122PL >= G125PL) || (G122PL == 0) +/* Задаёт MG125_12PL = ~(1 << 1); данные MG125_12PL. */ +#define MG125_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG125_12PL = 0xFFFF; данные MG125_12PL. */ +#define MG125_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G123PL >= G125PL) или (G123PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G123PL >= G125PL) || (G123PL == 0) +/* Задаёт MG125_13PL = ~(1 << 2); данные MG125_13PL. */ +#define MG125_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG125_13PL = 0xFFFF; данные MG125_13PL. */ +#define MG125_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G124PL >= G125PL) или (G124PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G124PL >= G125PL) || (G124PL == 0) +/* Задаёт MG125_14PL = ~(1 << 3); данные MG125_14PL. */ +#define MG125_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG125_14PL = 0xFFFF; данные MG125_14PL. */ +#define MG125_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G126PL >= G125PL) или (G126PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G126PL >= G125PL) || (G126PL == 0) +/* Задаёт MG125_16PL = ~(1 << 5); данные MG125_16PL. */ +#define MG125_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG125_16PL = 0xFFFF; данные MG125_16PL. */ +#define MG125_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G127PL >= G125PL) или (G127PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G127PL >= G125PL) || (G127PL == 0) +/* Задаёт MG125_17PL = ~(1 << 6); данные MG125_17PL. */ +#define MG125_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG125_17PL = 0xFFFF; данные MG125_17PL. */ +#define MG125_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G128PL >= G125PL) или (G128PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G128PL >= G125PL) || (G128PL == 0) +/* Задаёт MG125_18PL = ~(1 << 7); данные MG125_18PL. */ +#define MG125_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG125_18PL = 0xFFFF; данные MG125_18PL. */ +#define MG125_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG125_15PL = 0x00EF; данные MG125_15PL. */ +#define MG125_15PL 0x00EF +/* Задаёт MG125 = (MG125_11PL & MG125_12PL & MG125_13PL & MG125_14PL &; маска разрешённых прерываний внутри группы PIE 125. */ +#define MG125 (MG125_11PL & MG125_12PL & MG125_13PL & MG125_14PL & \ + MG125_15PL & MG125_16PL & MG125_17PL & MG125_18PL) /* Продолжает список аргументов, полей или выражение MG125_15PL & MG125_16PL & MG125_17PL & MG125_18PL); порядок элементов сохраняется. */ +// End of MG125: + +// Beginning of MG126: +/* Условие компиляции (G121PL >= G126PL) или (G121PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G121PL >= G126PL) || (G121PL == 0) +/* Задаёт MG126_11PL = ~(1); данные MG126_11PL. */ +#define MG126_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG126_11PL = 0xFFFF; данные MG126_11PL. */ +#define MG126_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G122PL >= G126PL) или (G122PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G122PL >= G126PL) || (G122PL == 0) +/* Задаёт MG126_12PL = ~(1 << 1); данные MG126_12PL. */ +#define MG126_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG126_12PL = 0xFFFF; данные MG126_12PL. */ +#define MG126_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G123PL >= G126PL) или (G123PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G123PL >= G126PL) || (G123PL == 0) +/* Задаёт MG126_13PL = ~(1 << 2); данные MG126_13PL. */ +#define MG126_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG126_13PL = 0xFFFF; данные MG126_13PL. */ +#define MG126_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G124PL >= G126PL) или (G124PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G124PL >= G126PL) || (G124PL == 0) +/* Задаёт MG126_14PL = ~(1 << 3); данные MG126_14PL. */ +#define MG126_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG126_14PL = 0xFFFF; данные MG126_14PL. */ +#define MG126_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G125PL >= G126PL) или (G125PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G125PL >= G126PL) || (G125PL == 0) +/* Задаёт MG126_15PL = ~(1 << 4); данные MG126_15PL. */ +#define MG126_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG126_15PL = 0xFFFF; данные MG126_15PL. */ +#define MG126_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G127PL >= G126PL) или (G127PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G127PL >= G126PL) || (G127PL == 0) +/* Задаёт MG126_17PL = ~(1 << 6); данные MG126_17PL. */ +#define MG126_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG126_17PL = 0xFFFF; данные MG126_17PL. */ +#define MG126_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G128PL >= G126PL) или (G128PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G128PL >= G126PL) || (G128PL == 0) +/* Задаёт MG126_18PL = ~(1 << 7); данные MG126_18PL. */ +#define MG126_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG126_18PL = 0xFFFF; данные MG126_18PL. */ +#define MG126_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG126_16PL = 0x00DF; данные MG126_16PL. */ +#define MG126_16PL 0x00DF +/* Задаёт MG126 = (MG126_11PL & MG126_12PL & MG126_13PL & MG126_14PL &; маска разрешённых прерываний внутри группы PIE 126. */ +#define MG126 (MG126_11PL & MG126_12PL & MG126_13PL & MG126_14PL & \ + MG126_15PL & MG126_16PL & MG126_17PL & MG126_18PL) /* Продолжает список аргументов, полей или выражение MG126_15PL & MG126_16PL & MG126_17PL & MG126_18PL); порядок элементов сохраняется. */ +// End of MG126: + +// Beginning of MG127: +/* Условие компиляции (G121PL >= G127PL) или (G121PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G121PL >= G127PL) || (G121PL == 0) +/* Задаёт MG127_11PL = ~(1); данные MG127_11PL. */ +#define MG127_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG127_11PL = 0xFFFF; данные MG127_11PL. */ +#define MG127_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G122PL >= G127PL) или (G122PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G122PL >= G127PL) || (G122PL == 0) +/* Задаёт MG127_12PL = ~(1 << 1); данные MG127_12PL. */ +#define MG127_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG127_12PL = 0xFFFF; данные MG127_12PL. */ +#define MG127_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G123PL >= G127PL) или (G123PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G123PL >= G127PL) || (G123PL == 0) +/* Задаёт MG127_13PL = ~(1 << 2); данные MG127_13PL. */ +#define MG127_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG127_13PL = 0xFFFF; данные MG127_13PL. */ +#define MG127_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G124PL >= G127PL) или (G124PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G124PL >= G127PL) || (G124PL == 0) +/* Задаёт MG127_14PL = ~(1 << 3); данные MG127_14PL. */ +#define MG127_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG127_14PL = 0xFFFF; данные MG127_14PL. */ +#define MG127_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G125PL >= G127PL) или (G125PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G125PL >= G127PL) || (G125PL == 0) +/* Задаёт MG127_15PL = ~(1 << 4); данные MG127_15PL. */ +#define MG127_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG127_15PL = 0xFFFF; данные MG127_15PL. */ +#define MG127_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G126PL >= G127PL) или (G126PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G126PL >= G127PL) || (G126PL == 0) +/* Задаёт MG127_16PL = ~(1 << 5); данные MG127_16PL. */ +#define MG127_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG127_16PL = 0xFFFF; данные MG127_16PL. */ +#define MG127_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G128PL >= G127PL) или (G128PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G128PL >= G127PL) || (G128PL == 0) +/* Задаёт MG127_18PL = ~(1 << 7); данные MG127_18PL. */ +#define MG127_18PL ~(1 << 7) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG127_18PL = 0xFFFF; данные MG127_18PL. */ +#define MG127_18PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG127_17PL = 0x00BF; данные MG127_17PL. */ +#define MG127_17PL 0x00BF +/* Задаёт MG127 = (MG127_11PL & MG127_12PL & MG127_13PL & MG127_14PL &; маска разрешённых прерываний внутри группы PIE 127. */ +#define MG127 (MG127_11PL & MG127_12PL & MG127_13PL & MG127_14PL & \ + MG127_15PL & MG127_16PL & MG127_17PL & MG127_18PL) /* Продолжает список аргументов, полей или выражение MG127_15PL & MG127_16PL & MG127_17PL & MG127_18PL); порядок элементов сохраняется. */ +// End of MG127: + +// Beginning of MG128: +/* Условие компиляции (G121PL >= G128PL) или (G121PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G121PL >= G128PL) || (G121PL == 0) +/* Задаёт MG128_11PL = ~(1); данные MG128_11PL. */ +#define MG128_11PL ~(1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG128_11PL = 0xFFFF; данные MG128_11PL. */ +#define MG128_11PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G122PL >= G128PL) или (G122PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G122PL >= G128PL) || (G122PL == 0) +/* Задаёт MG128_12PL = ~(1 << 1); данные MG128_12PL. */ +#define MG128_12PL ~(1 << 1) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG128_12PL = 0xFFFF; данные MG128_12PL. */ +#define MG128_12PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G123PL >= G128PL) или (G123PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G123PL >= G128PL) || (G123PL == 0) +/* Задаёт MG128_13PL = ~(1 << 2); данные MG128_13PL. */ +#define MG128_13PL ~(1 << 2) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG128_13PL = 0xFFFF; данные MG128_13PL. */ +#define MG128_13PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G124PL >= G128PL) или (G124PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G124PL >= G128PL) || (G124PL == 0) +/* Задаёт MG128_14PL = ~(1 << 3); данные MG128_14PL. */ +#define MG128_14PL ~(1 << 3) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG128_14PL = 0xFFFF; данные MG128_14PL. */ +#define MG128_14PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G125PL >= G128PL) или (G125PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G125PL >= G128PL) || (G125PL == 0) +/* Задаёт MG128_15PL = ~(1 << 4); данные MG128_15PL. */ +#define MG128_15PL ~(1 << 4) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG128_15PL = 0xFFFF; данные MG128_15PL. */ +#define MG128_15PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G126PL >= G128PL) или (G126PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G126PL >= G128PL) || (G126PL == 0) +/* Задаёт MG128_16PL = ~(1 << 5); данные MG128_16PL. */ +#define MG128_16PL ~(1 << 5) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG128_16PL = 0xFFFF; данные MG128_16PL. */ +#define MG128_16PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции (G127PL >= G128PL) или (G127PL == 0): выбранный блок включается в текущий вариант прошивки. */ +#if (G127PL >= G128PL) || (G127PL == 0) +/* Задаёт MG128_17PL = ~(1 << 6); данные MG128_17PL. */ +#define MG128_17PL ~(1 << 6) +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Задаёт MG128_17PL = 0xFFFF; данные MG128_17PL. */ +#define MG128_17PL 0xFFFF +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Задаёт MG128_18PL = 0x007F; данные MG128_18PL. */ +#define MG128_18PL 0x007F +/* Задаёт MG128 = (MG128_11PL & MG128_12PL & MG128_13PL & MG128_14PL &; маска разрешённых прерываний внутри группы PIE 128. */ +#define MG128 (MG128_11PL & MG128_12PL & MG128_13PL & MG128_14PL & \ + MG128_15PL & MG128_16PL & MG128_17PL & MG128_18PL) /* Продолжает список аргументов, полей или выражение MG128_15PL & MG128_16PL & MG128_17PL & MG128_18PL); порядок элементов сохраняется. */ +// End of MG128: + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // eof + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/common/include/DSP28x_Project.h b/c/protocan-boot/vendor/ti/f28335/common/include/DSP28x_Project.h new file mode 100644 index 0000000..d94194a --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/common/include/DSP28x_Project.h @@ -0,0 +1,28 @@ +/* Настройки и интерфейс DSP28x_Project. Русские пояснения сохранены в UTF-8. */ + +// TI File $Revision: /main/1 $ +// Checkin $Date: April 22, 2008 14:35:56 $ +//########################################################################### +// +// FILE: DSP28x_Project.h +// +// TITLE: DSP28x Project Headerfile and Examples Include File +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP28x_PROJECT_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP28x_PROJECT_H +/* Определяет защитный символ или переключатель DSP28x_PROJECT_H для последующей компиляции. */ +#define DSP28x_PROJECT_H + +/* Подключает "DSP2833x_Device.h": поставляемое TI описание Device для семейства C2833x. */ +#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File +/* Подключает "DSP2833x_Examples.h": поставляемое TI описание Examples для семейства C2833x. */ +#include "DSP2833x_Examples.h" // DSP2833x Examples Include File + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP28x_PROJECT_H definition + diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Adc.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Adc.h new file mode 100644 index 0000000..289dea6 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Adc.h @@ -0,0 +1,465 @@ +/* Поставляемое TI описание Adc для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/1 $ +// Checkin $Date: August 18, 2006 13:51:50 $ +//########################################################################### +// +// FILE: DSP2833x_Adc.h +// +// TITLE: DSP2833x Device ADC Register Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_ADC_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_ADC_H +/* Определяет защитный символ или переключатель DSP2833x_ADC_H для последующей компиляции. */ +#define DSP2833x_ADC_H + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +//--------------------------------------------------------------------------- +// ADC Individual Register Bit Definitions: + +/* Описывает структуру ADCTRL1_BITS; порядок полей определяет расположение данных. */ +struct ADCTRL1_BITS { // bits description + /* Битовое поле rsvd1, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:4; // 3:0 reserved + /* Битовое поле SEQ_CASC, ширина 1 бит; данные SEQ_CASC. */ + Uint16 SEQ_CASC:1; // 4 Cascaded sequencer mode + /* Битовое поле SEQ_OVRD, ширина 1 бит; данные SEQ_OVRD. */ + Uint16 SEQ_OVRD:1; // 5 Sequencer override + /* Битовое поле CONT_RUN, ширина 1 бит; данные CONT_RUN. */ + Uint16 CONT_RUN:1; // 6 Continuous run + /* Битовое поле CPS, ширина 1 бит; данные CPS. */ + Uint16 CPS:1; // 7 ADC core clock pre-scalar + /* Битовое поле ACQ_PS, ширина 4 бит; данные ACQ_PS. */ + Uint16 ACQ_PS:4; // 11:8 Acquisition window size + /* Битовое поле SUSMOD, ширина 2 бит; данные SUSMOD. */ + Uint16 SUSMOD:2; // 13:12 Emulation suspend mode + /* Битовое поле RESET, ширина 1 бит; сброс. */ + Uint16 RESET:1; // 14 ADC reset + /* Битовое поле rsvd2, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:1; // 15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений ADCTRL1_REG в одной области памяти. */ +union ADCTRL1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCTRL1_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCTRL1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру ADCTRL2_BITS; порядок полей определяет расположение данных. */ +struct ADCTRL2_BITS { // bits description + /* Битовое поле EPWM_SOCB_SEQ2, ширина 1 бит; данные EPWM_SOCB_SEQ2. */ + Uint16 EPWM_SOCB_SEQ2:1; // 0 EPWM compare B SOC mask for SEQ2 + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 1 reserved + /* Битовое поле INT_MOD_SEQ2, ширина 1 бит; данные INT_MOD_SEQ2. */ + Uint16 INT_MOD_SEQ2:1; // 2 SEQ2 Interrupt mode + /* Битовое поле INT_ENA_SEQ2, ширина 1 бит; данные INT_ENA_SEQ2. */ + Uint16 INT_ENA_SEQ2:1; // 3 SEQ2 Interrupt enable + /* Битовое поле rsvd2, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:1; // 4 reserved + /* Битовое поле SOC_SEQ2, ширина 1 бит; данные SOC_SEQ2. */ + Uint16 SOC_SEQ2:1; // 5 Start of conversion for SEQ2 + /* Битовое поле RST_SEQ2, ширина 1 бит; данные RST_SEQ2. */ + Uint16 RST_SEQ2:1; // 6 Reset SEQ2 + /* Битовое поле EXT_SOC_SEQ1, ширина 1 бит; данные EXT_SOC_SEQ1. */ + Uint16 EXT_SOC_SEQ1:1; // 7 External start of conversion for SEQ1 + /* Битовое поле EPWM_SOCA_SEQ1, ширина 1 бит; данные EPWM_SOCA_SEQ1. */ + Uint16 EPWM_SOCA_SEQ1:1; // 8 EPWM compare B SOC mask for SEQ1 + /* Битовое поле rsvd3, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:1; // 9 reserved + /* Битовое поле INT_MOD_SEQ1, ширина 1 бит; данные INT_MOD_SEQ1. */ + Uint16 INT_MOD_SEQ1:1; // 10 SEQ1 Interrupt mode + /* Битовое поле INT_ENA_SEQ1, ширина 1 бит; данные INT_ENA_SEQ1. */ + Uint16 INT_ENA_SEQ1:1; // 11 SEQ1 Interrupt enable + /* Битовое поле rsvd4, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd4:1; // 12 reserved + /* Битовое поле SOC_SEQ1, ширина 1 бит; данные SOC_SEQ1. */ + Uint16 SOC_SEQ1:1; // 13 Start of conversion trigger for SEQ1 + /* Битовое поле RST_SEQ1, ширина 1 бит; данные RST_SEQ1. */ + Uint16 RST_SEQ1:1; // 14 Restart sequencer 1 + /* Битовое поле EPWM_SOCB_SEQ, ширина 1 бит; данные EPWM_SOCB_SEQ. */ + Uint16 EPWM_SOCB_SEQ:1; // 15 EPWM compare B SOC enable +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений ADCTRL2_REG в одной области памяти. */ +union ADCTRL2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCTRL2_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCTRL2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру ADCASEQSR_BITS; порядок полей определяет расположение данных. */ +struct ADCASEQSR_BITS { // bits description + /* Битовое поле SEQ1_STATE, ширина 4 бит; данные SEQ1_STATE. */ + Uint16 SEQ1_STATE:4; // 3:0 SEQ1 state + /* Битовое поле SEQ2_STATE, ширина 3 бит; данные SEQ2_STATE. */ + Uint16 SEQ2_STATE:3; // 6:4 SEQ2 state + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 7 reserved + /* Битовое поле SEQ_CNTR, ширина 4 бит; данные SEQ_CNTR. */ + Uint16 SEQ_CNTR:4; // 11:8 Sequencing counter status + /* Битовое поле rsvd2, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:4; // 15:12 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ADCASEQSR_REG в одной области памяти. */ +union ADCASEQSR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCASEQSR_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCASEQSR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру ADCMAXCONV_BITS; порядок полей определяет расположение данных. */ +struct ADCMAXCONV_BITS { // bits description + /* Битовое поле MAX_CONV1, ширина 4 бит; данные MAX_CONV1. */ + Uint16 MAX_CONV1:4; // 3:0 Max number of conversions + /* Битовое поле MAX_CONV2, ширина 3 бит; данные MAX_CONV2. */ + Uint16 MAX_CONV2:3; // 6:4 Max number of conversions + /* Битовое поле rsvd1, ширина 9 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:9; // 15:7 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ADCMAXCONV_REG в одной области памяти. */ +union ADCMAXCONV_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCMAXCONV_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCMAXCONV_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру ADCCHSELSEQ1_BITS; порядок полей определяет расположение данных. */ +struct ADCCHSELSEQ1_BITS { // bits description + /* Битовое поле CONV00, ширина 4 бит; данные CONV00. */ + Uint16 CONV00:4; // 3:0 Conversion selection 00 + /* Битовое поле CONV01, ширина 4 бит; данные CONV01. */ + Uint16 CONV01:4; // 7:4 Conversion selection 01 + /* Битовое поле CONV02, ширина 4 бит; данные CONV02. */ + Uint16 CONV02:4; // 11:8 Conversion selection 02 + /* Битовое поле CONV03, ширина 4 бит; данные CONV03. */ + Uint16 CONV03:4; // 15:12 Conversion selection 03 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ADCCHSELSEQ1_REG в одной области памяти. */ +union ADCCHSELSEQ1_REG{ + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCCHSELSEQ1_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCCHSELSEQ1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру ADCCHSELSEQ2_BITS; порядок полей определяет расположение данных. */ +struct ADCCHSELSEQ2_BITS { // bits description + /* Битовое поле CONV04, ширина 4 бит; данные CONV04. */ + Uint16 CONV04:4; // 3:0 Conversion selection 04 + /* Битовое поле CONV05, ширина 4 бит; данные CONV05. */ + Uint16 CONV05:4; // 7:4 Conversion selection 05 + /* Битовое поле CONV06, ширина 4 бит; данные CONV06. */ + Uint16 CONV06:4; // 11:8 Conversion selection 06 + /* Битовое поле CONV07, ширина 4 бит; данные CONV07. */ + Uint16 CONV07:4; // 15:12 Conversion selection 07 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ADCCHSELSEQ2_REG в одной области памяти. */ +union ADCCHSELSEQ2_REG{ + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCCHSELSEQ2_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCCHSELSEQ2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру ADCCHSELSEQ3_BITS; порядок полей определяет расположение данных. */ +struct ADCCHSELSEQ3_BITS { // bits description + /* Битовое поле CONV08, ширина 4 бит; данные CONV08. */ + Uint16 CONV08:4; // 3:0 Conversion selection 08 + /* Битовое поле CONV09, ширина 4 бит; данные CONV09. */ + Uint16 CONV09:4; // 7:4 Conversion selection 09 + /* Битовое поле CONV10, ширина 4 бит; данные CONV10. */ + Uint16 CONV10:4; // 11:8 Conversion selection 10 + /* Битовое поле CONV11, ширина 4 бит; данные CONV11. */ + Uint16 CONV11:4; // 15:12 Conversion selection 11 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ADCCHSELSEQ3_REG в одной области памяти. */ +union ADCCHSELSEQ3_REG{ + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCCHSELSEQ3_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCCHSELSEQ3_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру ADCCHSELSEQ4_BITS; порядок полей определяет расположение данных. */ +struct ADCCHSELSEQ4_BITS { // bits description + /* Битовое поле CONV12, ширина 4 бит; данные CONV12. */ + Uint16 CONV12:4; // 3:0 Conversion selection 12 + /* Битовое поле CONV13, ширина 4 бит; данные CONV13. */ + Uint16 CONV13:4; // 7:4 Conversion selection 13 + /* Битовое поле CONV14, ширина 4 бит; данные CONV14. */ + Uint16 CONV14:4; // 11:8 Conversion selection 14 + /* Битовое поле CONV15, ширина 4 бит; данные CONV15. */ + Uint16 CONV15:4; // 15:12 Conversion selection 15 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ADCCHSELSEQ4_REG в одной области памяти. */ +union ADCCHSELSEQ4_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCCHSELSEQ4_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCCHSELSEQ4_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру ADCTRL3_BITS; порядок полей определяет расположение данных. */ +struct ADCTRL3_BITS { // bits description + /* Битовое поле SMODE_SEL, ширина 1 бит; данные SMODE_SEL. */ + Uint16 SMODE_SEL:1; // 0 Sampling mode select + /* Битовое поле ADCCLKPS, ширина 4 бит; данные ADCCLKPS. */ + Uint16 ADCCLKPS:4; // 4:1 ADC core clock divider + /* Битовое поле ADCPWDN, ширина 1 бит; данные ADCPWDN. */ + Uint16 ADCPWDN:1; // 5 ADC powerdown + /* Битовое поле ADCBGRFDN, ширина 2 бит; данные ADCBGRFDN. */ + Uint16 ADCBGRFDN:2; // 7:6 ADC bandgap/ref power down + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ADCTRL3_REG в одной области памяти. */ +union ADCTRL3_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCTRL3_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCTRL3_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру ADCST_BITS; порядок полей определяет расположение данных. */ +struct ADCST_BITS { // bits description + /* Битовое поле INT_SEQ1, ширина 1 бит; данные INT_SEQ1. */ + Uint16 INT_SEQ1:1; // 0 SEQ1 Interrupt flag + /* Битовое поле INT_SEQ2, ширина 1 бит; данные INT_SEQ2. */ + Uint16 INT_SEQ2:1; // 1 SEQ2 Interrupt flag + /* Битовое поле SEQ1_BSY, ширина 1 бит; данные SEQ1_BSY. */ + Uint16 SEQ1_BSY:1; // 2 SEQ1 busy status + /* Битовое поле SEQ2_BSY, ширина 1 бит; данные SEQ2_BSY. */ + Uint16 SEQ2_BSY:1; // 3 SEQ2 busy status + /* Битовое поле INT_SEQ1_CLR, ширина 1 бит; данные INT_SEQ1_CLR. */ + Uint16 INT_SEQ1_CLR:1; // 4 SEQ1 Interrupt clear + /* Битовое поле INT_SEQ2_CLR, ширина 1 бит; данные INT_SEQ2_CLR. */ + Uint16 INT_SEQ2_CLR:1; // 5 SEQ2 Interrupt clear + /* Битовое поле EOS_BUF1, ширина 1 бит; данные EOS_BUF1. */ + Uint16 EOS_BUF1:1; // 6 End of sequence buffer1 + /* Битовое поле EOS_BUF2, ширина 1 бит; данные EOS_BUF2. */ + Uint16 EOS_BUF2:1; // 7 End of sequence buffer2 + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений ADCST_REG в одной области памяти. */ +union ADCST_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCST_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCST_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру ADCREFSEL_BITS; порядок полей определяет расположение данных. */ +struct ADCREFSEL_BITS { // bits description + /* Битовое поле rsvd1, ширина 14 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:14; // 13:0 reserved + /* Битовое поле REF_SEL, ширина 2 бит; данные REF_SEL. */ + Uint16 REF_SEL:2; // 15:14 Reference select +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; +/* Объединяет несколько представлений ADCREFSEL_REG в одной области памяти. */ +union ADCREFSEL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCREFSEL_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCREFSEL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру ADCOFFTRIM_BITS; порядок полей определяет расположение данных. */ +struct ADCOFFTRIM_BITS{ // bits description + /* Продолжает список аргументов, полей или выражение int16 OFFSET_TRIM:9;; порядок элементов сохраняется. */ + int16 OFFSET_TRIM:9; // 8:0 Offset Trim + /* Битовое поле rsvd1, ширина 7 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:7; // 15:9 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ADCOFFTRIM_REG в одной области памяти. */ +union ADCOFFTRIM_REG{ + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ADCOFFTRIM_BITS bit;; порядок полей определяет расположение данных. */ + struct ADCOFFTRIM_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; +/* Описывает структуру ADC_REGS; порядок полей определяет расположение данных. */ +struct ADC_REGS { + /* Объединяет несколько представлений ADCTRL1_REG ADCTRL1; в одной области памяти. */ + union ADCTRL1_REG ADCTRL1; // ADC Control 1 + /* Объединяет несколько представлений ADCTRL2_REG ADCTRL2; в одной области памяти. */ + union ADCTRL2_REG ADCTRL2; // ADC Control 2 + /* Объединяет несколько представлений ADCMAXCONV_REG ADCMAXCONV; в одной области памяти. */ + union ADCMAXCONV_REG ADCMAXCONV; // Max conversions + /* Объединяет несколько представлений ADCCHSELSEQ1_REG ADCCHSELSEQ1; в одной области памяти. */ + union ADCCHSELSEQ1_REG ADCCHSELSEQ1; // Channel select sequencing control 1 + /* Объединяет несколько представлений ADCCHSELSEQ2_REG ADCCHSELSEQ2; в одной области памяти. */ + union ADCCHSELSEQ2_REG ADCCHSELSEQ2; // Channel select sequencing control 2 + /* Объединяет несколько представлений ADCCHSELSEQ3_REG ADCCHSELSEQ3; в одной области памяти. */ + union ADCCHSELSEQ3_REG ADCCHSELSEQ3; // Channel select sequencing control 3 + /* Объединяет несколько представлений ADCCHSELSEQ4_REG ADCCHSELSEQ4; в одной области памяти. */ + union ADCCHSELSEQ4_REG ADCCHSELSEQ4; // Channel select sequencing control 4 + /* Объединяет несколько представлений ADCASEQSR_REG ADCASEQSR; в одной области памяти. */ + union ADCASEQSR_REG ADCASEQSR; // Autosequence status register + /* Объявляет ADCRESULT0 — данные ADCRESULT0. */ + Uint16 ADCRESULT0; // Conversion Result Buffer 0 + /* Объявляет ADCRESULT1 — данные ADCRESULT1. */ + Uint16 ADCRESULT1; // Conversion Result Buffer 1 + /* Объявляет ADCRESULT2 — данные ADCRESULT2. */ + Uint16 ADCRESULT2; // Conversion Result Buffer 2 + /* Объявляет ADCRESULT3 — данные ADCRESULT3. */ + Uint16 ADCRESULT3; // Conversion Result Buffer 3 + /* Объявляет ADCRESULT4 — данные ADCRESULT4. */ + Uint16 ADCRESULT4; // Conversion Result Buffer 4 + /* Объявляет ADCRESULT5 — данные ADCRESULT5. */ + Uint16 ADCRESULT5; // Conversion Result Buffer 5 + /* Объявляет ADCRESULT6 — данные ADCRESULT6. */ + Uint16 ADCRESULT6; // Conversion Result Buffer 6 + /* Объявляет ADCRESULT7 — данные ADCRESULT7. */ + Uint16 ADCRESULT7; // Conversion Result Buffer 7 + /* Объявляет ADCRESULT8 — данные ADCRESULT8. */ + Uint16 ADCRESULT8; // Conversion Result Buffer 8 + /* Объявляет ADCRESULT9 — данные ADCRESULT9. */ + Uint16 ADCRESULT9; // Conversion Result Buffer 9 + /* Объявляет ADCRESULT10 — данные ADCRESULT10. */ + Uint16 ADCRESULT10; // Conversion Result Buffer 10 + /* Объявляет ADCRESULT11 — данные ADCRESULT11. */ + Uint16 ADCRESULT11; // Conversion Result Buffer 11 + /* Объявляет ADCRESULT12 — данные ADCRESULT12. */ + Uint16 ADCRESULT12; // Conversion Result Buffer 12 + /* Объявляет ADCRESULT13 — данные ADCRESULT13. */ + Uint16 ADCRESULT13; // Conversion Result Buffer 13 + /* Объявляет ADCRESULT14 — данные ADCRESULT14. */ + Uint16 ADCRESULT14; // Conversion Result Buffer 14 + /* Объявляет ADCRESULT15 — данные ADCRESULT15. */ + Uint16 ADCRESULT15; // Conversion Result Buffer 15 + /* Объединяет несколько представлений ADCTRL3_REG ADCTRL3; в одной области памяти. */ + union ADCTRL3_REG ADCTRL3; // ADC Control 3 + /* Объединяет несколько представлений ADCST_REG ADCST; в одной области памяти. */ + union ADCST_REG ADCST; // ADC Status Register + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1; + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2; + /* Объединяет несколько представлений ADCREFSEL_REG ADCREFSEL; в одной области памяти. */ + union ADCREFSEL_REG ADCREFSEL; // Reference Select Register + /* Объединяет несколько представлений ADCOFFTRIM_REG ADCOFFTRIM; в одной области памяти. */ + union ADCOFFTRIM_REG ADCOFFTRIM; // Offset Trim Register +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру ADC_RESULT_MIRROR_REGS; порядок полей определяет расположение данных. */ +struct ADC_RESULT_MIRROR_REGS +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Объявляет ADCRESULT0 — данные ADCRESULT0. */ + Uint16 ADCRESULT0; // Conversion Result Buffer 0 + /* Объявляет ADCRESULT1 — данные ADCRESULT1. */ + Uint16 ADCRESULT1; // Conversion Result Buffer 1 + /* Объявляет ADCRESULT2 — данные ADCRESULT2. */ + Uint16 ADCRESULT2; // Conversion Result Buffer 2 + /* Объявляет ADCRESULT3 — данные ADCRESULT3. */ + Uint16 ADCRESULT3; // Conversion Result Buffer 3 + /* Объявляет ADCRESULT4 — данные ADCRESULT4. */ + Uint16 ADCRESULT4; // Conversion Result Buffer 4 + /* Объявляет ADCRESULT5 — данные ADCRESULT5. */ + Uint16 ADCRESULT5; // Conversion Result Buffer 5 + /* Объявляет ADCRESULT6 — данные ADCRESULT6. */ + Uint16 ADCRESULT6; // Conversion Result Buffer 6 + /* Объявляет ADCRESULT7 — данные ADCRESULT7. */ + Uint16 ADCRESULT7; // Conversion Result Buffer 7 + /* Объявляет ADCRESULT8 — данные ADCRESULT8. */ + Uint16 ADCRESULT8; // Conversion Result Buffer 8 + /* Объявляет ADCRESULT9 — данные ADCRESULT9. */ + Uint16 ADCRESULT9; // Conversion Result Buffer 9 + /* Объявляет ADCRESULT10 — данные ADCRESULT10. */ + Uint16 ADCRESULT10; // Conversion Result Buffer 10 + /* Объявляет ADCRESULT11 — данные ADCRESULT11. */ + Uint16 ADCRESULT11; // Conversion Result Buffer 11 + /* Объявляет ADCRESULT12 — данные ADCRESULT12. */ + Uint16 ADCRESULT12; // Conversion Result Buffer 12 + /* Объявляет ADCRESULT13 — данные ADCRESULT13. */ + Uint16 ADCRESULT13; // Conversion Result Buffer 13 + /* Объявляет ADCRESULT14 — данные ADCRESULT14. */ + Uint16 ADCRESULT14; // Conversion Result Buffer 14 + /* Объявляет ADCRESULT15 — данные ADCRESULT15. */ + Uint16 ADCRESULT15; // Conversion Result Buffer 15 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// ADC External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct ADC_REGS AdcRegs;; порядок элементов сохраняется. */ +extern volatile struct ADC_REGS AdcRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct ADC_RESULT_MIRROR_REGS AdcMirror;; порядок элементов сохраняется. */ +extern volatile struct ADC_RESULT_MIRROR_REGS AdcMirror; + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_ADC_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_CpuTimers.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_CpuTimers.h new file mode 100644 index 0000000..a3383fc --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_CpuTimers.h @@ -0,0 +1,283 @@ +/* Поставляемое TI описание CpuTimers для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/4 $ +// Checkin $Date: March 20, 2007 15:33:42 $ +//########################################################################### +// +// FILE: DSP2833x_CpuTimers.h +// +// TITLE: DSP2833x CPU 32-bit Timers Register Definitions. +// +// NOTES: CpuTimer1 and CpuTimer2 are reserved for use with DSP BIOS and +// other realtime operating systems. +// +// Do not use these two timers in your application if you ever plan +// on integrating DSP-BIOS or another realtime OS. +// +// For this reason, comment out the code to manipulate these two timers +// if using DSP-BIOS or another realtime OS. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_CPU_TIMERS_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_CPU_TIMERS_H +/* Определяет защитный символ или переключатель DSP2833x_CPU_TIMERS_H для последующей компиляции. */ +#define DSP2833x_CPU_TIMERS_H + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +//--------------------------------------------------------------------------- +// CPU Timer Register Bit Definitions: +// +// +// TCR: Control register bit definitions: +/* Описывает структуру TCR_BITS; порядок полей определяет расположение данных. */ +struct TCR_BITS { // bits description + /* Битовое поле rsvd1, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:4; // 3:0 reserved + /* Битовое поле TSS, ширина 1 бит; данные TSS. */ + Uint16 TSS:1; // 4 Timer Start/Stop + /* Битовое поле TRB, ширина 1 бит; данные TRB. */ + Uint16 TRB:1; // 5 Timer reload + /* Битовое поле rsvd2, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:4; // 9:6 reserved + /* Битовое поле SOFT, ширина 1 бит; данные SOFT. */ + Uint16 SOFT:1; // 10 Emulation modes + /* Битовое поле FREE, ширина 1 бит; данные FREE. */ + Uint16 FREE:1; // 11 + /* Битовое поле rsvd3, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:2; // 12:13 reserved + /* Битовое поле TIE, ширина 1 бит; данные TIE. */ + Uint16 TIE:1; // 14 Output enable + /* Битовое поле TIF, ширина 1 бит; данные TIF. */ + Uint16 TIF:1; // 15 Interrupt flag +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TCR_REG в одной области памяти. */ +union TCR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TCR_BITS bit;; порядок полей определяет расположение данных. */ + struct TCR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// TPR: Pre-scale low bit definitions: +/* Описывает структуру TPR_BITS; порядок полей определяет расположение данных. */ +struct TPR_BITS { // bits description + /* Битовое поле TDDR, ширина 8 бит; данные TDDR. */ + Uint16 TDDR:8; // 7:0 Divide-down low + /* Битовое поле PSC, ширина 8 бит; данные PSC. */ + Uint16 PSC:8; // 15:8 Prescale counter low +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TPR_REG в одной области памяти. */ +union TPR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TPR_BITS bit;; порядок полей определяет расположение данных. */ + struct TPR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// TPRH: Pre-scale high bit definitions: +/* Описывает структуру TPRH_BITS; порядок полей определяет расположение данных. */ +struct TPRH_BITS { // bits description + /* Битовое поле TDDRH, ширина 8 бит; данные TDDRH. */ + Uint16 TDDRH:8; // 7:0 Divide-down high + /* Битовое поле PSCH, ширина 8 бит; данные PSCH. */ + Uint16 PSCH:8; // 15:8 Prescale counter high +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TPRH_REG в одной области памяти. */ +union TPRH_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TPRH_BITS bit;; порядок полей определяет расположение данных. */ + struct TPRH_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// TIM, TIMH: Timer register definitions: +/* Описывает структуру TIM_REG; порядок полей определяет расположение данных. */ +struct TIM_REG { + /* Объявляет LSW — данные LSW. */ + Uint16 LSW; + /* Объявляет MSW — данные MSW. */ + Uint16 MSW; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TIM_GROUP в одной области памяти. */ +union TIM_GROUP { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру TIM_REG half;; порядок полей определяет расположение данных. */ + struct TIM_REG half; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// PRD, PRDH: Period register definitions: +/* Описывает структуру PRD_REG; порядок полей определяет расположение данных. */ +struct PRD_REG { + /* Объявляет LSW — данные LSW. */ + Uint16 LSW; + /* Объявляет MSW — данные MSW. */ + Uint16 MSW; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PRD_GROUP в одной области памяти. */ +union PRD_GROUP { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру PRD_REG half;; порядок полей определяет расположение данных. */ + struct PRD_REG half; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// CPU Timer Register File: +// +/* Описывает структуру CPUTIMER_REGS; порядок полей определяет расположение данных. */ +struct CPUTIMER_REGS { + /* Объединяет несколько представлений TIM_GROUP TIM; в одной области памяти. */ + union TIM_GROUP TIM; // Timer counter register + /* Объединяет несколько представлений PRD_GROUP PRD; в одной области памяти. */ + union PRD_GROUP PRD; // Period register + /* Объединяет несколько представлений TCR_REG TCR; в одной области памяти. */ + union TCR_REG TCR; // Timer control register + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1; // reserved + /* Объединяет несколько представлений TPR_REG TPR; в одной области памяти. */ + union TPR_REG TPR; // Timer pre-scale low + /* Объединяет несколько представлений TPRH_REG TPRH; в одной области памяти. */ + union TPRH_REG TPRH; // Timer pre-scale high +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// CPU Timer Support Variables: +// +/* Описывает структуру CPUTIMER_VARS; порядок полей определяет расположение данных. */ +struct CPUTIMER_VARS { + /* Продолжает список аргументов, полей или выражение volatile struct CPUTIMER_REGS *RegsAddr;; порядок элементов сохраняется. */ + volatile struct CPUTIMER_REGS *RegsAddr; + /* Объявляет InterruptCount — прерывание число. */ + Uint32 InterruptCount; + /* Объявляет CPUFreqInMHz — данные CPUFreqInMHz. */ + float CPUFreqInMHz; + /* Объявляет PeriodInUSec — период In U Sec. */ + float PeriodInUSec; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// Function prototypes and external definitions: +// +/* Объявляет интерфейс функции InitCpuTimers; реализация вызывается через этот прототип. */ +void InitCpuTimers(void); +/* Объявляет интерфейс функции ConfigCpuTimer; реализация вызывается через этот прототип. */ +void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period); + +/* Продолжает список аргументов, полей или выражение extern volatile struct CPUTIMER_REGS CpuTimer0Regs;; порядок элементов сохраняется. */ +extern volatile struct CPUTIMER_REGS CpuTimer0Regs; +/* Продолжает список аргументов, полей или выражение extern struct CPUTIMER_VARS CpuTimer0;; порядок элементов сохраняется. */ +extern struct CPUTIMER_VARS CpuTimer0; + +// CpuTimer 1 and CpuTimer2 are reserved for DSP BIOS & other RTOS. Comment out CpuTimer1 and CpuTimer2 if using DSP BIOS or other RTOS +/* Продолжает список аргументов, полей или выражение extern volatile struct CPUTIMER_REGS CpuTimer1Regs;; порядок элементов сохраняется. */ +extern volatile struct CPUTIMER_REGS CpuTimer1Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct CPUTIMER_REGS CpuTimer2Regs;; порядок элементов сохраняется. */ +extern volatile struct CPUTIMER_REGS CpuTimer2Regs; + +/* Продолжает список аргументов, полей или выражение extern struct CPUTIMER_VARS CpuTimer1;; порядок элементов сохраняется. */ +extern struct CPUTIMER_VARS CpuTimer1; +/* Продолжает список аргументов, полей или выражение extern struct CPUTIMER_VARS CpuTimer2;; порядок элементов сохраняется. */ +extern struct CPUTIMER_VARS CpuTimer2; + +//--------------------------------------------------------------------------- +// Usefull Timer Operations: +// +// Start Timer: +/* Задаёт StartCpuTimer0 = CpuTimer0Regs.TCR.bit.TSS = 0; Start Cpu таймер 0. */ +#define StartCpuTimer0() CpuTimer0Regs.TCR.bit.TSS = 0 + +// Stop Timer: +/* Задаёт StopCpuTimer0 = CpuTimer0Regs.TCR.bit.TSS = 1; Stop Cpu таймер 0. */ +#define StopCpuTimer0() CpuTimer0Regs.TCR.bit.TSS = 1 + +// Reload Timer With period Value: +/* Задаёт ReloadCpuTimer0 = CpuTimer0Regs.TCR.bit.TRB = 1; Reload Cpu таймер 0. */ +#define ReloadCpuTimer0() CpuTimer0Regs.TCR.bit.TRB = 1 + +// Read 32-Bit Timer Value: +/* Задаёт ReadCpuTimer0Counter = CpuTimer0Regs.TIM.all; чтение Cpu таймер 0 счётчик. */ +#define ReadCpuTimer0Counter() CpuTimer0Regs.TIM.all + +// Read 32-Bit Period Value: +/* Задаёт ReadCpuTimer0Period = CpuTimer0Regs.PRD.all; чтение Cpu таймер 0 период. */ +#define ReadCpuTimer0Period() CpuTimer0Regs.PRD.all + +// CpuTimer 1 and CpuTimer2 are reserved for DSP BIOS & other RTOS +// Do not use these two timers if you ever plan on integrating +// DSP-BIOS or another realtime OS. +// +// For this reason, comment out the code to manipulate these two timers +// if using DSP-BIOS or another realtime OS. + +// Start Timer: +/* Задаёт StartCpuTimer1 = CpuTimer1Regs.TCR.bit.TSS = 0; Start Cpu таймер 1. */ +#define StartCpuTimer1() CpuTimer1Regs.TCR.bit.TSS = 0 +/* Задаёт StartCpuTimer2 = CpuTimer2Regs.TCR.bit.TSS = 0; Start Cpu таймер 2. */ +#define StartCpuTimer2() CpuTimer2Regs.TCR.bit.TSS = 0 + + +// Stop Timer: +/* Задаёт StopCpuTimer1 = CpuTimer1Regs.TCR.bit.TSS = 1; Stop Cpu таймер 1. */ +#define StopCpuTimer1() CpuTimer1Regs.TCR.bit.TSS = 1 +/* Задаёт StopCpuTimer2 = CpuTimer2Regs.TCR.bit.TSS = 1; Stop Cpu таймер 2. */ +#define StopCpuTimer2() CpuTimer2Regs.TCR.bit.TSS = 1 + +// Reload Timer With period Value: +/* Задаёт ReloadCpuTimer1 = CpuTimer1Regs.TCR.bit.TRB = 1; Reload Cpu таймер 1. */ +#define ReloadCpuTimer1() CpuTimer1Regs.TCR.bit.TRB = 1 +/* Задаёт ReloadCpuTimer2 = CpuTimer2Regs.TCR.bit.TRB = 1; Reload Cpu таймер 2. */ +#define ReloadCpuTimer2() CpuTimer2Regs.TCR.bit.TRB = 1 + +// Read 32-Bit Timer Value: +/* Задаёт ReadCpuTimer1Counter = CpuTimer1Regs.TIM.all; чтение Cpu таймер 1 счётчик. */ +#define ReadCpuTimer1Counter() CpuTimer1Regs.TIM.all +/* Задаёт ReadCpuTimer2Counter = CpuTimer2Regs.TIM.all; чтение Cpu таймер 2 счётчик. */ +#define ReadCpuTimer2Counter() CpuTimer2Regs.TIM.all + +// Read 32-Bit Period Value: +/* Задаёт ReadCpuTimer1Period = CpuTimer1Regs.PRD.all; чтение Cpu таймер 1 период. */ +#define ReadCpuTimer1Period() CpuTimer1Regs.PRD.all +/* Задаёт ReadCpuTimer2Period = CpuTimer2Regs.PRD.all; чтение Cpu таймер 2 период. */ +#define ReadCpuTimer2Period() CpuTimer2Regs.PRD.all + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_CPU_TIMERS_H definition + + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_DMA.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_DMA.h new file mode 100644 index 0000000..5508e70 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_DMA.h @@ -0,0 +1,437 @@ +/* Поставляемое TI описание DMA для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/11 $ +// Checkin $Date: June 23, 2008 11:34:15 $ +//########################################################################### +// +// FILE: DSP2833x_DMA.h +// +// TITLE: DSP2833x DMA Module Register Bit Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_DMA_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_DMA_H +/* Определяет защитный символ или переключатель DSP2833x_DMA_H для последующей компиляции. */ +#define DSP2833x_DMA_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +//---------------------------------------------------- +// Channel MODE register bit definitions: +/* Описывает структуру MODE_BITS; порядок полей определяет расположение данных. */ +struct MODE_BITS { // bits description + /* Битовое поле PERINTSEL, ширина 5 бит; данные PERINTSEL. */ + Uint16 PERINTSEL:5; // 4:0 Peripheral Interrupt and Sync Select Bits (R/W): + // 0 no interrupt + // 1 SEQ1INT & ADCSYNC + // 2 SEQ2INT + // 3 XINT1 + // 4 XINT2 + // 5 XINT3 + // 6 XINT4 + // 7 XINT5 + // 8 XINT6 + // 9 XINT7 + // 10 XINT13 + // 11 TINT0 + // 12 TINT1 + // 13 TINT2 + // 14 MXEVTA & MXSYNCA + // 15 MREVTA & MRSYNCA + // 16 MXEVTB & MXSYNCB + // 17 MREVTB & MRSYNCB + // 18 ePWM1SOCA + // 19 ePWM1SOCB + // 20 ePWM2SOCA + // 21 ePWM2SOCB + // 22 ePWM3SOCA + // 23 ePWM3SOCB + // 24 ePWM4SOCA + // 25 ePWM4SOCB + // 26 ePWM5SOCA + // 27 ePWM5SOCB + // 28 ePWM6SOCA + // 29 ePWM6SOCB + // 30:31 no interrupt + /* Битовое поле rsvd1, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:2; // 6:5 (R=0:0) + /* Битовое поле OVRINTE, ширина 1 бит; данные OVRINTE. */ + Uint16 OVRINTE:1; // 7 Overflow Interrupt Enable (R/W): + // 0 overflow interrupt disabled + // 1 overflow interrupt enabled + /* Битовое поле PERINTE, ширина 1 бит; данные PERINTE. */ + Uint16 PERINTE:1; // 8 Peripheral Interrupt Enable Bit (R/W): + // 0 peripheral interrupt disabled + // 1 peripheral interrupt enabled + /* Битовое поле CHINTMODE, ширина 1 бит; данные CHINTMODE. */ + Uint16 CHINTMODE:1; // 9 Channel Interrupt Mode Bit (R/W): + // 0 generate interrupt at beginning of new transfer + // 1 generate interrupt at end of transfer + /* Битовое поле ONESHOT, ширина 1 бит; данные ONESHOT. */ + Uint16 ONESHOT:1; // 10 One Shot Mode Bit (R/W): + // 0 only interrupt event triggers single burst transfer + // 1 first interrupt triggers burst, continue until transfer count is zero + /* Битовое поле CONTINUOUS, ширина 1 бит; данные CONTINUOUS. */ + Uint16 CONTINUOUS:1; // 11 Continous Mode Bit (R/W): + // 0 stop when transfer count is zero + // 1 re-initialize when transfer count is zero + /* Битовое поле SYNCE, ширина 1 бит; данные SYNCE. */ + Uint16 SYNCE:1; // 12 Sync Enable Bit (R/W): + // 0 ignore selected interrupt sync signal + // 1 enable selected interrupt sync signal + /* Битовое поле SYNCSEL, ширина 1 бит; данные SYNCSEL. */ + Uint16 SYNCSEL:1; // 13 Sync Select Bit (R/W): + // 0 sync signal controls source wrap counter + // 1 sync signal controls destination wrap counter + /* Битовое поле DATASIZE, ширина 1 бит; данные DATASIZE. */ + Uint16 DATASIZE:1; // 14 Data Size Mode Bit (R/W): + // 0 16-bit data transfer size + // 1 32-bit data transfer size + /* Битовое поле CHINTE, ширина 1 бит; данные CHINTE. */ + Uint16 CHINTE:1; // 15 Channel Interrupt Enable Bit (R/W): + // 0 channel interrupt disabled + // 1 channel interrupt enabled +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений MODE_REG в одной области памяти. */ +union MODE_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру MODE_BITS bit;; порядок полей определяет расположение данных. */ + struct MODE_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Channel CONTROL register bit definitions: +/* Описывает структуру CONTROL_BITS; порядок полей определяет расположение данных. */ +struct CONTROL_BITS { // bits description + /* Битовое поле RUN, ширина 1 бит; данные RUN. */ + Uint16 RUN:1; // 0 Run Bit (R=0/W=1) + /* Битовое поле HALT, ширина 1 бит; данные HALT. */ + Uint16 HALT:1; // 1 Halt Bit (R=0/W=1) + /* Битовое поле SOFTRESET, ширина 1 бит; данные SOFTRESET. */ + Uint16 SOFTRESET:1; // 2 Soft Reset Bit (R=0/W=1) + /* Битовое поле PERINTFRC, ширина 1 бит; данные PERINTFRC. */ + Uint16 PERINTFRC:1; // 3 Interrupt Force Bit (R=0/W=1) + /* Битовое поле PERINTCLR, ширина 1 бит; данные PERINTCLR. */ + Uint16 PERINTCLR:1; // 4 Interrupt Clear Bit (R=0/W=1) + /* Битовое поле SYNCFRC, ширина 1 бит; данные SYNCFRC. */ + Uint16 SYNCFRC:1; // 5 Sync Force Bit (R=0/W=1) + /* Битовое поле SYNCCLR, ширина 1 бит; данные SYNCCLR. */ + Uint16 SYNCCLR:1; // 6 Sync Clear Bit (R=0/W=1) + /* Битовое поле ERRCLR, ширина 1 бит; данные ERRCLR. */ + Uint16 ERRCLR:1; // 7 Error Clear Bit (R=0/W=1) + /* Битовое поле PERINTFLG, ширина 1 бит; данные PERINTFLG. */ + Uint16 PERINTFLG:1; // 8 Interrupt Flag Bit (R): + // 0 no interrupt pending + // 1 interrupt pending + /* Битовое поле SYNCFLG, ширина 1 бит; данные SYNCFLG. */ + Uint16 SYNCFLG:1; // 9 Sync Flag Bit (R): + // 0 no sync pending + // 1 sync pending + /* Битовое поле SYNCERR, ширина 1 бит; данные SYNCERR. */ + Uint16 SYNCERR:1; // 10 Sync Error Flag Bit (R): + // 0 no sync error + // 1 sync error detected + /* Битовое поле TRANSFERSTS, ширина 1 бит; данные TRANSFERSTS. */ + Uint16 TRANSFERSTS:1; // 11 Transfer Status Bit (R): + // 0 no transfer in progress or pending + // 1 transfer in progress or pending + /* Битовое поле BURSTSTS, ширина 1 бит; данные BURSTSTS. */ + Uint16 BURSTSTS:1; // 12 Burst Status Bit (R): + // 0 no burst in progress or pending + // 1 burst in progress or pending + /* Битовое поле RUNSTS, ширина 1 бит; данные RUNSTS. */ + Uint16 RUNSTS:1; // 13 Run Status Bit (R): + // 0 channel not running or halted + // 1 channel running + /* Битовое поле OVRFLG, ширина 1 бит; данные OVRFLG. */ + Uint16 OVRFLG:1; // 14 Overflow Flag Bit(R) + // 0 no overflow event + // 1 overflow event + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 15 (R=0) +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений CONTROL_REG в одной области памяти. */ +union CONTROL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру CONTROL_BITS bit;; порядок полей определяет расположение данных. */ + struct CONTROL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// DMACTRL register bit definitions: +/* Описывает структуру DMACTRL_BITS; порядок полей определяет расположение данных. */ +struct DMACTRL_BITS { // bits description + /* Битовое поле HARDRESET, ширина 1 бит; данные HARDRESET. */ + Uint16 HARDRESET:1; // 0 Hard Reset Bit (R=0/W=1) + /* Битовое поле PRIORITYRESET, ширина 1 бит; данные PRIORITYRESET. */ + Uint16 PRIORITYRESET:1; // 1 Priority Reset Bit (R=0/W=1) + /* Битовое поле rsvd1, ширина 14 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:14; // 15:2 (R=0:0) +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений DMACTRL_REG в одной области памяти. */ +union DMACTRL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру DMACTRL_BITS bit;; порядок полей определяет расположение данных. */ + struct DMACTRL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// DEBUGCTRL register bit definitions: +/* Описывает структуру DEBUGCTRL_BITS; порядок полей определяет расположение данных. */ +struct DEBUGCTRL_BITS { // bits description + /* Битовое поле rsvd1, ширина 15 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:15; // 14:0 (R=0:0) + /* Битовое поле FREE, ширина 1 бит; данные FREE. */ + Uint16 FREE:1; // 15 Debug Mode Bit (R/W): + // 0 halt after current read-write operation + // 1 continue running +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений DEBUGCTRL_REG в одной области памяти. */ +union DEBUGCTRL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру DEBUGCTRL_BITS bit;; порядок полей определяет расположение данных. */ + struct DEBUGCTRL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// PRIORITYCTRL1 register bit definitions: +/* Описывает структуру PRIORITYCTRL1_BITS; порядок полей определяет расположение данных. */ +struct PRIORITYCTRL1_BITS { // bits description + /* Битовое поле CH1PRIORITY, ширина 1 бит; 1 приоритет. */ + Uint16 CH1PRIORITY:1; // 0 Ch1 Priority Bit (R/W): + // 0 same priority as all other channels + // 1 highest priority channel + /* Битовое поле rsvd1, ширина 15 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:15; // 15:1 (R=0:0) +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PRIORITYCTRL1_REG в одной области памяти. */ +union PRIORITYCTRL1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PRIORITYCTRL1_BITS bit;; порядок полей определяет расположение данных. */ + struct PRIORITYCTRL1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// PRIORITYSTAT register bit definitions: +/* Описывает структуру PRIORITYSTAT_BITS; порядок полей определяет расположение данных. */ +struct PRIORITYSTAT_BITS { // bits description + /* Битовое поле ACTIVESTS, ширина 3 бит; данные ACTIVESTS. */ + Uint16 ACTIVESTS:3; // 2:0 Active Channel Status Bits (R): + // 0,0,0 no channel active + // 0,0,1 Ch1 channel active + // 0,1,0 Ch2 channel active + // 0,1,1 Ch3 channel active + // 1,0,0 Ch4 channel active + // 1,0,1 Ch5 channel active + // 1,1,0 Ch6 channel active + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 3 (R=0) + /* Битовое поле ACTIVESTS_SHADOW, ширина 3 бит; данные ACTIVESTS_SHADOW. */ + Uint16 ACTIVESTS_SHADOW:3; // 6:4 Active Channel Status Shadow Bits (R): + // 0,0,0 no channel active and interrupted by Ch1 + // 0,0,1 cannot occur + // 0,1,0 Ch2 was active and interrupted by Ch1 + // 0,1,1 Ch3 was active and interrupted by Ch1 + // 1,0,0 Ch4 was active and interrupted by Ch1 + // 1,0,1 Ch5 was active and interrupted by Ch1 + // 1,1,0 Ch6 was active and interrupted by Ch1 + /* Битовое поле rsvd2, ширина 9 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:9; // 15:7 (R=0:0) +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PRIORITYSTAT_REG в одной области памяти. */ +union PRIORITYSTAT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PRIORITYSTAT_BITS bit;; порядок полей определяет расположение данных. */ + struct PRIORITYSTAT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// Burst Size +/* Описывает структуру BURST_SIZE_BITS; порядок полей определяет расположение данных. */ +struct BURST_SIZE_BITS { // bits description + /* Битовое поле BURSTSIZE, ширина 5 бит; данные BURSTSIZE. */ + Uint16 BURSTSIZE:5; // 4:0 Burst transfer size + /* Битовое поле rsvd1, ширина 11 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:11; // 15:5 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений BURST_SIZE_REG в одной области памяти. */ +union BURST_SIZE_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру BURST_SIZE_BITS bit;; порядок полей определяет расположение данных. */ + struct BURST_SIZE_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// Burst Count +/* Описывает структуру BURST_COUNT_BITS; порядок полей определяет расположение данных. */ +struct BURST_COUNT_BITS { // bits description + /* Битовое поле BURSTCOUNT, ширина 5 бит; данные BURSTCOUNT. */ + Uint16 BURSTCOUNT:5; // 4:0 Burst transfer size + /* Битовое поле rsvd1, ширина 11 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:11; // 15:5 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений BURST_COUNT_REG в одной области памяти. */ +union BURST_COUNT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру BURST_COUNT_BITS bit;; порядок полей определяет расположение данных. */ + struct BURST_COUNT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + +//---------------------------------------------------- +// DMA Channel Registers: +/* Описывает структуру CH_REGS; порядок полей определяет расположение данных. */ +struct CH_REGS { + /* Объединяет несколько представлений MODE_REG MODE; в одной области памяти. */ + union MODE_REG MODE; // Mode Register + /* Объединяет несколько представлений CONTROL_REG CONTROL; в одной области памяти. */ + union CONTROL_REG CONTROL; // Control Register + + /* Объединяет несколько представлений BURST_SIZE_REG BURST_SIZE; в одной области памяти. */ + union BURST_SIZE_REG BURST_SIZE; // Burst Size Register + /* Объединяет несколько представлений BURST_COUNT_REG BURST_COUNT; в одной области памяти. */ + union BURST_COUNT_REG BURST_COUNT; // Burst Count Register + /* Продолжает список аргументов, полей или выражение int16 SRC_BURST_STEP;; порядок элементов сохраняется. */ + int16 SRC_BURST_STEP; // Source Burst Step Register + /* Продолжает список аргументов, полей или выражение int16 DST_BURST_STEP;; порядок элементов сохраняется. */ + int16 DST_BURST_STEP; // Destination Burst Step Register + + /* Объявляет TRANSFER_SIZE — TRANSFER размер. */ + Uint16 TRANSFER_SIZE; // Transfer Size Register + /* Объявляет TRANSFER_COUNT — TRANSFER число. */ + Uint16 TRANSFER_COUNT; // Transfer Count Register + /* Продолжает список аргументов, полей или выражение int16 SRC_TRANSFER_STEP;; порядок элементов сохраняется. */ + int16 SRC_TRANSFER_STEP; // Source Transfer Step Register + /* Продолжает список аргументов, полей или выражение int16 DST_TRANSFER_STEP;; порядок элементов сохраняется. */ + int16 DST_TRANSFER_STEP; // Destination Transfer Step Register + + /* Объявляет SRC_WRAP_SIZE — SRC WRAP размер. */ + Uint16 SRC_WRAP_SIZE; // Source Wrap Size Register + /* Объявляет SRC_WRAP_COUNT — SRC WRAP число. */ + Uint16 SRC_WRAP_COUNT; // Source Wrap Count Register + /* Продолжает список аргументов, полей или выражение int16 SRC_WRAP_STEP;; порядок элементов сохраняется. */ + int16 SRC_WRAP_STEP; // Source Wrap Step Register + + /* Объявляет DST_WRAP_SIZE — DST WRAP размер. */ + Uint16 DST_WRAP_SIZE; // Destination Wrap Size Register + /* Объявляет DST_WRAP_COUNT — DST WRAP число. */ + Uint16 DST_WRAP_COUNT; // Destination Wrap Count Register + /* Продолжает список аргументов, полей или выражение int16 DST_WRAP_STEP;; порядок элементов сохраняется. */ + int16 DST_WRAP_STEP; // Destination Wrap Step Register + + /* Объявляет SRC_BEG_ADDR_SHADOW — данные SRC_BEG_ADDR_SHADOW. */ + Uint32 SRC_BEG_ADDR_SHADOW; // Source Begin Address Shadow Register + /* Объявляет SRC_ADDR_SHADOW — данные SRC_ADDR_SHADOW. */ + Uint32 SRC_ADDR_SHADOW; // Source Address Shadow Register + /* Объявляет SRC_BEG_ADDR_ACTIVE — данные SRC_BEG_ADDR_ACTIVE. */ + Uint32 SRC_BEG_ADDR_ACTIVE; // Source Begin Address Active Register + /* Объявляет SRC_ADDR_ACTIVE — данные SRC_ADDR_ACTIVE. */ + Uint32 SRC_ADDR_ACTIVE; // Source Address Active Register + + /* Объявляет DST_BEG_ADDR_SHADOW — данные DST_BEG_ADDR_SHADOW. */ + Uint32 DST_BEG_ADDR_SHADOW; // Destination Begin Address Shadow Register + /* Объявляет DST_ADDR_SHADOW — данные DST_ADDR_SHADOW. */ + Uint32 DST_ADDR_SHADOW; // Destination Address Shadow Register + /* Объявляет DST_BEG_ADDR_ACTIVE — данные DST_BEG_ADDR_ACTIVE. */ + Uint32 DST_BEG_ADDR_ACTIVE; // Destination Begin Address Active Register + /* Объявляет DST_ADDR_ACTIVE — данные DST_ADDR_ACTIVE. */ + Uint32 DST_ADDR_ACTIVE; // Destination Address Active Register +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// DMA Registers: +/* Описывает структуру DMA_REGS; порядок полей определяет расположение данных. */ +struct DMA_REGS { + /* Объединяет несколько представлений DMACTRL_REG DMACTRL; в одной области памяти. */ + union DMACTRL_REG DMACTRL; // DMA Control Register + /* Объединяет несколько представлений DEBUGCTRL_REG DEBUGCTRL; в одной области памяти. */ + union DEBUGCTRL_REG DEBUGCTRL; // Debug Control Register + /* Объявляет rsvd0 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd0; // reserved + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1; // + /* Объединяет несколько представлений PRIORITYCTRL1_REG PRIORITYCTRL1; в одной области памяти. */ + union PRIORITYCTRL1_REG PRIORITYCTRL1; // Priority Control 1 Register + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2; // + /* Объединяет несколько представлений PRIORITYSTAT_REG PRIORITYSTAT; в одной области памяти. */ + union PRIORITYSTAT_REG PRIORITYSTAT; // Priority Status Register + /* Объявляет rsvd3 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3[25]; // + /* Описывает структуру CH_REGS CH1;; порядок полей определяет расположение данных. */ + struct CH_REGS CH1; // DMA Channel 1 Registers + /* Описывает структуру CH_REGS CH2;; порядок полей определяет расположение данных. */ + struct CH_REGS CH2; // DMA Channel 2 Registers + /* Описывает структуру CH_REGS CH3;; порядок полей определяет расположение данных. */ + struct CH_REGS CH3; // DMA Channel 3 Registers + /* Описывает структуру CH_REGS CH4;; порядок полей определяет расположение данных. */ + struct CH_REGS CH4; // DMA Channel 4 Registers + /* Описывает структуру CH_REGS CH5;; порядок полей определяет расположение данных. */ + struct CH_REGS CH5; // DMA Channel 5 Registers + /* Описывает структуру CH_REGS CH6;; порядок полей определяет расположение данных. */ + struct CH_REGS CH6; // DMA Channel 6 Registers +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//--------------------------------------------------------------------------- +// External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct DMA_REGS DmaRegs;; порядок элементов сохраняется. */ +extern volatile struct DMA_REGS DmaRegs; + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_DMA_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_DevEmu.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_DevEmu.h new file mode 100644 index 0000000..b821aa7 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_DevEmu.h @@ -0,0 +1,154 @@ +/* Поставляемое TI описание DevEmu для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/3 $ +// Checkin $Date: June 2, 2008 11:12:30 $ +//########################################################################### +// +// FILE: DSP2833x_DevEmu.h +// +// TITLE: DSP2833x Device Emulation Register Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_DEV_EMU_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_DEV_EMU_H +/* Определяет защитный символ или переключатель DSP2833x_DEV_EMU_H для последующей компиляции. */ +#define DSP2833x_DEV_EMU_H + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +//--------------------------------------------------------------------------- +// Device Emulation Register Bit Definitions: +// +// Device Configuration Register Bit Definitions +/* Описывает структуру DEVICECNF_BITS; порядок полей определяет расположение данных. */ +struct DEVICECNF_BITS { // bits description + /* Битовое поле rsvd1, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:3; // 2:0 reserved + /* Битовое поле VMAPS, ширина 1 бит; данные VMAPS. */ + Uint16 VMAPS:1; // 3 VMAP Status + /* Битовое поле rsvd2, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:1; // 4 reserved + /* Битовое поле XRSn, ширина 1 бит; данные XRSn. */ + Uint16 XRSn:1; // 5 XRSn Signal Status + /* Битовое поле rsvd3, ширина 10 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:10; // 15:6 + /* Битовое поле rsvd4, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd4:3; // 18:16 + /* Битовое поле ENPROT, ширина 1 бит; данные ENPROT. */ + Uint16 ENPROT:1; // 19 Enable/Disable pipeline protection + /* Битовое поле MONPRIV, ширина 1 бит; данные MONPRIV. */ + Uint16 MONPRIV:1; // 20 MONPRIV enable bit + /* Битовое поле rsvd5, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd5:1; // 21 reserved + /* Битовое поле EMU0SEL, ширина 2 бит; данные EMU0SEL. */ + Uint16 EMU0SEL:2; // 23,22 EMU0 Mux select + /* Битовое поле EMU1SEL, ширина 2 бит; данные EMU1SEL. */ + Uint16 EMU1SEL:2; // 25,24 EMU1 Mux select + /* Битовое поле MCBSPCON, ширина 1 бит; данные MCBSPCON. */ + Uint16 MCBSPCON:1; // 26 McBSP-B to EMU0/EMU1 pins control + /* Битовое поле rsvd6, ширина 5 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd6:5; // 31:27 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений DEVICECNF_REG в одной области памяти. */ +union DEVICECNF_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру DEVICECNF_BITS bit;; порядок полей определяет расположение данных. */ + struct DEVICECNF_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// CLASSID +/* Описывает структуру CLASSID_BITS; порядок полей определяет расположение данных. */ +struct CLASSID_BITS { // bits description + /* Битовое поле CLASSNO, ширина 8 бит; данные CLASSNO. */ + Uint16 CLASSNO:8; // 7:0 Class Number + /* Битовое поле PARTTYPE, ширина 8 бит; данные PARTTYPE. */ + Uint16 PARTTYPE:8; // 15:8 Part Type +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений CLASSID_REG в одной области памяти. */ +union CLASSID_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру CLASSID_BITS bit;; порядок полей определяет расположение данных. */ + struct CLASSID_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру DEV_EMU_REGS; порядок полей определяет расположение данных. */ +struct DEV_EMU_REGS { + /* Объединяет несколько представлений DEVICECNF_REG DEVICECNF; в одной области памяти. */ + union DEVICECNF_REG DEVICECNF; // device configuration + /* Объединяет несколько представлений CLASSID_REG CLASSID; в одной области памяти. */ + union CLASSID_REG CLASSID; // Class ID + /* Объявляет REVID — данные REVID. */ + Uint16 REVID; // Device ID + /* Объявляет PROTSTART — данные PROTSTART. */ + Uint16 PROTSTART; // Write-Read protection start + /* Объявляет PROTRANGE — данные PROTRANGE. */ + Uint16 PROTRANGE; // Write-Read protection range + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2[202]; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// PARTID +/* Описывает структуру PARTID_BITS; порядок полей определяет расположение данных. */ +struct PARTID_BITS { // bits description + /* Битовое поле PARTNO, ширина 8 бит; данные PARTNO. */ + Uint16 PARTNO:8; // 7:0 Part Number + /* Битовое поле PARTTYPE, ширина 8 бит; данные PARTTYPE. */ + Uint16 PARTTYPE:8; // 15:8 Part Type +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PARTID_REG в одной области памяти. */ +union PARTID_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PARTID_BITS bit;; порядок полей определяет расположение данных. */ + struct PARTID_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру PARTID_REGS; порядок полей определяет расположение данных. */ +struct PARTID_REGS { + /* Объединяет несколько представлений PARTID_REG PARTID; в одной области памяти. */ + union PARTID_REG PARTID; // Part ID +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + +//--------------------------------------------------------------------------- +// Device Emulation Register References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct DEV_EMU_REGS DevEmuRegs;; порядок элементов сохраняется. */ +extern volatile struct DEV_EMU_REGS DevEmuRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct PARTID_REGS PartIdRegs;; порядок элементов сохраняется. */ +extern volatile struct PARTID_REGS PartIdRegs; + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_DEV_EMU_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Device.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Device.h new file mode 100644 index 0000000..138d251 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Device.h @@ -0,0 +1,655 @@ +/* Поставляемое TI описание Device для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/5 $ +// Checkin $Date: January 22, 2008 16:55:35 $ +//########################################################################### +// +// FILE: DSP2833x_Device.h +// +// TITLE: DSP2833x Device Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_DEVICE_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_DEVICE_H +/* Определяет защитный символ или переключатель DSP2833x_DEVICE_H для последующей компиляции. */ +#define DSP2833x_DEVICE_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +/* Задаёт TARGET = 1; данные TARGET. */ +#define TARGET 1 +//--------------------------------------------------------------------------- +// User To Select Target Device: + +/* Задаёт DSP28_28335 = TARGET; данные DSP28_28335. */ +#define DSP28_28335 TARGET // Selects '28335/'28235 +/* Задаёт DSP28_28334 = 0; данные DSP28_28334. */ +#define DSP28_28334 0 // Selects '28334/'28234 +/* Задаёт DSP28_28332 = 0; данные DSP28_28332. */ +#define DSP28_28332 0 // Selects '28332/'28232 + + +//--------------------------------------------------------------------------- +// Common CPU Definitions: +// + +/* Продолжает список аргументов, полей или выражение extern cregister volatile unsigned int IFR;; порядок элементов сохраняется. */ +extern cregister volatile unsigned int IFR; +/* Продолжает список аргументов, полей или выражение extern cregister volatile unsigned int IER;; порядок элементов сохраняется. */ +extern cregister volatile unsigned int IER; + +/* Задаёт EINT = asm(" clrc INTM"); разрешение маскируемых прерываний ядра. */ +#define EINT asm(" clrc INTM") +/* Задаёт DINT = asm(" setc INTM"); запрет маскируемых прерываний ядра. */ +#define DINT asm(" setc INTM") +/* Задаёт ERTM = asm(" clrc DBGM"); данные ERTM. */ +#define ERTM asm(" clrc DBGM") +/* Задаёт DRTM = asm(" setc DBGM"); данные DRTM. */ +#define DRTM asm(" setc DBGM") +/* Задаёт EALLOW = asm(" EALLOW"); разрешение записи в защищённые регистры периферии. */ +#define EALLOW asm(" EALLOW") +/* Задаёт EDIS = asm(" EDIS"); закрытие доступа к защищённым регистрам периферии. */ +#define EDIS asm(" EDIS") +/* Задаёт ESTOP0 = asm(" ESTOP0"); данные ESTOP0. */ +#define ESTOP0 asm(" ESTOP0") + +/* Задаёт M_INT1 = 0x0001; данные M_INT1. */ +#define M_INT1 0x0001 +/* Задаёт M_INT2 = 0x0002; данные M_INT2. */ +#define M_INT2 0x0002 +/* Задаёт M_INT3 = 0x0004; данные M_INT3. */ +#define M_INT3 0x0004 +/* Задаёт M_INT4 = 0x0008; данные M_INT4. */ +#define M_INT4 0x0008 +/* Задаёт M_INT5 = 0x0010; данные M_INT5. */ +#define M_INT5 0x0010 +/* Задаёт M_INT6 = 0x0020; данные M_INT6. */ +#define M_INT6 0x0020 +/* Задаёт M_INT7 = 0x0040; данные M_INT7. */ +#define M_INT7 0x0040 +/* Задаёт M_INT8 = 0x0080; данные M_INT8. */ +#define M_INT8 0x0080 +/* Задаёт M_INT9 = 0x0100; данные M_INT9. */ +#define M_INT9 0x0100 +/* Задаёт M_INT10 = 0x0200; данные M_INT10. */ +#define M_INT10 0x0200 +/* Задаёт M_INT11 = 0x0400; данные M_INT11. */ +#define M_INT11 0x0400 +/* Задаёт M_INT12 = 0x0800; данные M_INT12. */ +#define M_INT12 0x0800 +/* Задаёт M_INT13 = 0x1000; данные M_INT13. */ +#define M_INT13 0x1000 +/* Задаёт M_INT14 = 0x2000; данные M_INT14. */ +#define M_INT14 0x2000 +/* Задаёт M_DLOG = 0x4000; данные M_DLOG. */ +#define M_DLOG 0x4000 +/* Задаёт M_RTOS = 0x8000; данные M_RTOS. */ +#define M_RTOS 0x8000 + +/* Задаёт BIT0 = 0x0001; данные BIT0. */ +#define BIT0 0x0001 +/* Задаёт BIT1 = 0x0002; данные BIT1. */ +#define BIT1 0x0002 +/* Задаёт BIT2 = 0x0004; данные BIT2. */ +#define BIT2 0x0004 +/* Задаёт BIT3 = 0x0008; данные BIT3. */ +#define BIT3 0x0008 +/* Задаёт BIT4 = 0x0010; данные BIT4. */ +#define BIT4 0x0010 +/* Задаёт BIT5 = 0x0020; данные BIT5. */ +#define BIT5 0x0020 +/* Задаёт BIT6 = 0x0040; данные BIT6. */ +#define BIT6 0x0040 +/* Задаёт BIT7 = 0x0080; данные BIT7. */ +#define BIT7 0x0080 +/* Задаёт BIT8 = 0x0100; данные BIT8. */ +#define BIT8 0x0100 +/* Задаёт BIT9 = 0x0200; данные BIT9. */ +#define BIT9 0x0200 +/* Задаёт BIT10 = 0x0400; данные BIT10. */ +#define BIT10 0x0400 +/* Задаёт BIT11 = 0x0800; данные BIT11. */ +#define BIT11 0x0800 +/* Задаёт BIT12 = 0x1000; данные BIT12. */ +#define BIT12 0x1000 +/* Задаёт BIT13 = 0x2000; данные BIT13. */ +#define BIT13 0x2000 +/* Задаёт BIT14 = 0x4000; данные BIT14. */ +#define BIT14 0x4000 +/* Задаёт BIT15 = 0x8000; данные BIT15. */ +#define BIT15 0x8000 + + + +//--------------------------------------------------------------------------- +// For Portability, User Is Recommended To Use Following Data Type Size +// Definitions For 16-bit and 32-Bit Signed/Unsigned Integers: +// + +/* Начинает условие: DSP28_DATA_TYPES ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP28_DATA_TYPES +/* Определяет защитный символ или переключатель DSP28_DATA_TYPES для последующей компиляции. */ +#define DSP28_DATA_TYPES +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef int int16; +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef long int32; +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef long long int64; +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef unsigned int Uint16; +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef unsigned long Uint32; +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef unsigned long long Uint64; +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef float float32; +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef long double float64; +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef union +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Продолжает список аргументов, полей или выражение struct; порядок элементов сохраняется. */ + struct + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Битовое поле bit0, ширина 1 бит; бит 0. */ + unsigned int bit0: 1; + /* Битовое поле bit1, ширина 1 бит; бит 1. */ + unsigned int bit1: 1; + /* Битовое поле bit2, ширина 1 бит; бит 2. */ + unsigned int bit2: 1; + /* Битовое поле bit3, ширина 1 бит; бит 3. */ + unsigned int bit3: 1; + /* Битовое поле bit4, ширина 1 бит; бит 4. */ + unsigned int bit4: 1; + /* Битовое поле bit5, ширина 1 бит; бит 5. */ + unsigned int bit5: 1; + /* Битовое поле bit6, ширина 1 бит; бит 6. */ + unsigned int bit6: 1; + /* Битовое поле bit7, ширина 1 бит; бит 7. */ + unsigned int bit7: 1; + + /* Продолжает список аргументов, полей или выражение } bit;; порядок элементов сохраняется. */ + } bit; + + /* Продолжает список аргументов, полей или выражение struct; порядок элементов сохраняется. */ + struct + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Битовое поле quad_0, ширина 4 бит; данные quad_0. */ + unsigned int quad_0 :4; + /* Битовое поле quad_1, ширина 4 бит; данные quad_1. */ + unsigned int quad_1 :4; + + /* Продолжает список аргументов, полей или выражение } qua;; порядок элементов сохраняется. */ + } qua; + + /* Продолжает список аргументов, полей или выражение unsigned short all;; порядок элементов сохраняется. */ + unsigned short all; + +/* Продолжает список аргументов, полей или выражение } BAITE;; порядок элементов сохраняется. */ +} BAITE; + +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef union +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Продолжает список аргументов, полей или выражение struct; порядок элементов сохраняется. */ + struct + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Битовое поле bit0, ширина 1 бит; бит 0. */ + unsigned int bit0: 1; + /* Битовое поле bit1, ширина 1 бит; бит 1. */ + unsigned int bit1: 1; + /* Битовое поле bit2, ширина 1 бит; бит 2. */ + unsigned int bit2: 1; + /* Битовое поле bit3, ширина 1 бит; бит 3. */ + unsigned int bit3: 1; + /* Битовое поле bit4, ширина 1 бит; бит 4. */ + unsigned int bit4: 1; + /* Битовое поле bit5, ширина 1 бит; бит 5. */ + unsigned int bit5: 1; + /* Битовое поле bit6, ширина 1 бит; бит 6. */ + unsigned int bit6: 1; + /* Битовое поле bit7, ширина 1 бит; бит 7. */ + unsigned int bit7: 1; + /* Битовое поле bit8, ширина 1 бит; бит 8. */ + unsigned int bit8: 1; + /* Битовое поле bit9, ширина 1 бит; бит 9. */ + unsigned int bit9: 1; + /* Битовое поле bitA, ширина 1 бит; бит A. */ + unsigned int bitA: 1; + /* Битовое поле bitB, ширина 1 бит; бит B. */ + unsigned int bitB: 1; + /* Битовое поле bitC, ширина 1 бит; бит C. */ + unsigned int bitC: 1; + /* Битовое поле bitD, ширина 1 бит; бит D. */ + unsigned int bitD: 1; + /* Битовое поле bitE, ширина 1 бит; бит E. */ + unsigned int bitE: 1; + /* Битовое поле bitF, ширина 1 бит; бит F. */ + unsigned int bitF: 1; + + /* Продолжает список аргументов, полей или выражение } bit;; порядок элементов сохраняется. */ + } bit; + + /* Продолжает список аргументов, полей или выражение struct; порядок элементов сохраняется. */ + struct + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Битовое поле quad_0, ширина 4 бит; данные quad_0. */ + unsigned int quad_0 :4; + /* Битовое поле quad_1, ширина 4 бит; данные quad_1. */ + unsigned int quad_1 :4; + /* Битовое поле quad_2, ширина 4 бит; данные quad_2. */ + unsigned int quad_2 :4; + /* Битовое поле quad_3, ширина 4 бит; данные quad_3. */ + unsigned int quad_3 :4; + + /* Продолжает список аргументов, полей или выражение } qua;; порядок элементов сохраняется. */ + } qua; + + /* Продолжает список аргументов, полей или выражение struct; порядок элементов сохраняется. */ + struct + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Битовое поле byte_0, ширина 8 бит; данные byte_0. */ + unsigned int byte_0 :8; + /* Битовое поле byte_1, ширина 8 бит; данные byte_1. */ + unsigned int byte_1 :8; + + /* Продолжает список аргументов, полей или выражение } byt;; порядок элементов сохраняется. */ + } byt; + + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + int all; + +/* Продолжает список аргументов, полей или выражение } WORDE;; порядок элементов сохраняется. */ +} WORDE; + +/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */ +typedef union +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Продолжает список аргументов, полей или выражение struct; порядок элементов сохраняется. */ + struct + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Битовое поле bit00, ширина 1 бит; бит 00. */ + unsigned int bit00: 1; + /* Битовое поле bit01, ширина 1 бит; бит 01. */ + unsigned int bit01: 1; + /* Битовое поле bit02, ширина 1 бит; бит 02. */ + unsigned int bit02: 1; + /* Битовое поле bit03, ширина 1 бит; бит 03. */ + unsigned int bit03: 1; + /* Битовое поле bit04, ширина 1 бит; бит 04. */ + unsigned int bit04: 1; + /* Битовое поле bit05, ширина 1 бит; бит 05. */ + unsigned int bit05: 1; + /* Битовое поле bit06, ширина 1 бит; бит 06. */ + unsigned int bit06: 1; + /* Битовое поле bit07, ширина 1 бит; бит 07. */ + unsigned int bit07: 1; + /* Битовое поле bit08, ширина 1 бит; бит 08. */ + unsigned int bit08: 1; + /* Битовое поле bit09, ширина 1 бит; бит 09. */ + unsigned int bit09: 1; + /* Битовое поле bit0A, ширина 1 бит; бит 0 A. */ + unsigned int bit0A: 1; + /* Битовое поле bit0B, ширина 1 бит; бит 0 B. */ + unsigned int bit0B: 1; + /* Битовое поле bit0C, ширина 1 бит; бит 0 C. */ + unsigned int bit0C: 1; + /* Битовое поле bit0D, ширина 1 бит; бит 0 D. */ + unsigned int bit0D: 1; + /* Битовое поле bit0E, ширина 1 бит; бит 0 E. */ + unsigned int bit0E: 1; + /* Битовое поле bit0F, ширина 1 бит; бит 0 F. */ + unsigned int bit0F: 1; + /* Битовое поле bit10, ширина 1 бит; бит 10. */ + unsigned int bit10: 1; + /* Битовое поле bit11, ширина 1 бит; бит 11. */ + unsigned int bit11: 1; + /* Битовое поле bit12, ширина 1 бит; бит 12. */ + unsigned int bit12: 1; + /* Битовое поле bit13, ширина 1 бит; бит 13. */ + unsigned int bit13: 1; + /* Битовое поле bit14, ширина 1 бит; бит 14. */ + unsigned int bit14: 1; + /* Битовое поле bit15, ширина 1 бит; бит 15. */ + unsigned int bit15: 1; + /* Битовое поле bit16, ширина 1 бит; бит 16. */ + unsigned int bit16: 1; + /* Битовое поле bit17, ширина 1 бит; бит 17. */ + unsigned int bit17: 1; + /* Битовое поле bit18, ширина 1 бит; бит 18. */ + unsigned int bit18: 1; + /* Битовое поле bit19, ширина 1 бит; бит 19. */ + unsigned int bit19: 1; + /* Битовое поле bit1A, ширина 1 бит; бит 1 A. */ + unsigned int bit1A: 1; + /* Битовое поле bit1B, ширина 1 бит; бит 1 B. */ + unsigned int bit1B: 1; + /* Битовое поле bit1C, ширина 1 бит; бит 1 C. */ + unsigned int bit1C: 1; + /* Битовое поле bit1D, ширина 1 бит; бит 1 D. */ + unsigned int bit1D: 1; + /* Битовое поле bit1E, ширина 1 бит; бит 1 E. */ + unsigned int bit1E: 1; + /* Битовое поле bit1F, ширина 1 бит; бит 1 F. */ + unsigned int bit1F: 1; + + /* Продолжает список аргументов, полей или выражение } bit;; порядок элементов сохраняется. */ + } bit; + + /* Продолжает список аргументов, полей или выражение struct; порядок элементов сохраняется. */ + struct + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Битовое поле quad_0, ширина 4 бит; данные quad_0. */ + unsigned int quad_0 :4; + /* Битовое поле quad_1, ширина 4 бит; данные quad_1. */ + unsigned int quad_1 :4; + /* Битовое поле quad_2, ширина 4 бит; данные quad_2. */ + unsigned int quad_2 :4; + /* Битовое поле quad_3, ширина 4 бит; данные quad_3. */ + unsigned int quad_3 :4; + /* Битовое поле quad_4, ширина 4 бит; данные quad_4. */ + unsigned int quad_4 :4; + /* Битовое поле quad_5, ширина 4 бит; данные quad_5. */ + unsigned int quad_5 :4; + /* Битовое поле quad_6, ширина 4 бит; данные quad_6. */ + unsigned int quad_6 :4; + /* Битовое поле quad_7, ширина 4 бит; данные quad_7. */ + unsigned int quad_7 :4; + + /* Продолжает список аргументов, полей или выражение } qua;; порядок элементов сохраняется. */ + } qua; + + /* Продолжает список аргументов, полей или выражение struct; порядок элементов сохраняется. */ + struct + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Битовое поле byte_0, ширина 8 бит; данные byte_0. */ + unsigned int byte_0 :8; + /* Битовое поле byte_1, ширина 8 бит; данные byte_1. */ + unsigned int byte_1 :8; + /* Битовое поле byte_2, ширина 8 бит; данные byte_2. */ + unsigned int byte_2 :8; + /* Битовое поле byte_3, ширина 8 бит; данные byte_3. */ + unsigned int byte_3 :8; + + /* Продолжает список аргументов, полей или выражение } byt;; порядок элементов сохраняется. */ + } byt; + + /* Продолжает список аргументов, полей или выражение struct; порядок элементов сохраняется. */ + struct + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Битовое поле word_0, ширина 16 бит; слово 0. */ + unsigned int word_0 :16; + /* Битовое поле word_1, ширина 16 бит; слово 1. */ + unsigned int word_1 :16; + + /* Продолжает список аргументов, полей или выражение } wrd;; порядок элементов сохраняется. */ + } wrd; + + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + unsigned long all; + +/* Продолжает список аргументов, полей или выражение } LONGE;; порядок элементов сохраняется. */ +} LONGE; + +/* Задаёт XCLKIN = 30000000; данные XCLKIN. */ +#define XCLKIN 30000000 // external oscillator frequency +/* Объявляет SYSCLKOUT — данные SYSCLKOUT; LSPCLK — данные LSPCLK; HSPCLK — данные HSPCLK. Память определена в другом модуле. */ +extern long SYSCLKOUT, LSPCLK, HSPCLK; + +/* Задаёт CLKMULT = 2L; данные CLKMULT. */ +#define CLKMULT 2L // 1 to 5 + +/* Задаёт LOWORD = int)( (long int)(l) &0xFFFF)); данные LOWORD. */ +#define LOWORD(l)((short int)( (long int)(l) &0xFFFF)) +/* Задаёт HIWORD = int)(((long int)(l)>>16)&0xFFFF)); данные HIWORD. */ +#define HIWORD(l)((short int)(((long int)(l)>>16)&0xFFFF)) + +/* Задаёт LOBYTE = (short int)(w) &0xFF)); данные LOBYTE. */ +#define LOBYTE(w)((char)( (short int)(w) &0xFF)) +/* Задаёт HIBYTE = int)(w)>>8)&0xFF)); данные HIBYTE. */ +#define HIBYTE(w)((char)(((short int)(w)>>8)&0xFF)) + +/* Задаёт BYTE3 = int)(l)>>24)&0xFF)); данные BYTE3. */ +#define BYTE3(l)((char)(((long int)(l)>>24)&0xFF)) +/* Задаёт BYTE2 = int)(l)>>16)&0xFF)); данные BYTE2. */ +#define BYTE2(l)((char)(((long int)(l)>>16)&0xFF)) +/* Задаёт BYTE1 = int)(l)>> 8)&0xFF)); данные BYTE1. */ +#define BYTE1(l)((char)(((long int)(l)>> 8)&0xFF)) +/* Задаёт BYTE0 = (long int)(l) &0xFF)); данные BYTE0. */ +#define BYTE0(l)((char)( (long int)(l) &0xFF)) + +//--------------------------------------------------------------------------- +// Include All Peripheral Header Files: +// +/* Подключает "DSP2833x_Adc.h": поставляемое TI описание Adc для семейства C2833x. */ +#include "DSP2833x_Adc.h" // ADC Registers +/* Подключает "DSP2833x_DevEmu.h": поставляемое TI описание DevEmu для семейства C2833x. */ +#include "DSP2833x_DevEmu.h" // Device Emulation Registers +/* Подключает "DSP2833x_CpuTimers.h": поставляемое TI описание CpuTimers для семейства C2833x. */ +#include "DSP2833x_CpuTimers.h" // 32-bit CPU Timers +/* Подключает "DSP2833x_ECan.h": поставляемое TI описание ECan для семейства C2833x. */ +#include "DSP2833x_ECan.h" // Enhanced eCAN Registers +/* Подключает "DSP2833x_ECap.h": поставляемое TI описание ECap для семейства C2833x. */ +#include "DSP2833x_ECap.h" // Enhanced Capture +/* Подключает "DSP2833x_DMA.h": поставляемое TI описание DMA для семейства C2833x. */ +#include "DSP2833x_DMA.h" // DMA Registers +/* Подключает "DSP2833x_EPwm.h": поставляемое TI описание EPwm для семейства C2833x. */ +#include "DSP2833x_EPwm.h" // Enhanced PWM +/* Подключает "DSP2833x_EQep.h": поставляемое TI описание EQep для семейства C2833x. */ +#include "DSP2833x_EQep.h" // Enhanced QEP +/* Подключает "DSP2833x_Gpio.h": поставляемое TI описание Gpio для семейства C2833x. */ +#include "DSP2833x_Gpio.h" // General Purpose I/O Registers +/* Подключает "DSP2833x_I2c.h": поставляемое TI описание I2c для семейства C2833x. */ +#include "DSP2833x_I2c.h" // I2C Registers +/* Подключает "DSP2833x_McBSP.h": поставляемое TI описание McBSP для семейства C2833x. */ +#include "DSP2833x_McBSP.h" // McBSP +/* Подключает "DSP2833x_PieCtrl.h": поставляемое TI описание PieCtrl для семейства C2833x. */ +#include "DSP2833x_PieCtrl.h" // PIE Control Registers +/* Подключает "DSP2833x_PieVect.h": поставляемое TI описание PieVect для семейства C2833x. */ +#include "DSP2833x_PieVect.h" // PIE Vector Table +/* Подключает "DSP2833x_Spi.h": поставляемое TI описание Spi для семейства C2833x. */ +#include "DSP2833x_Spi.h" // SPI Registers +/* Подключает "DSP2833x_Sci.h": поставляемое TI описание Sci для семейства C2833x. */ +#include "DSP2833x_Sci.h" // SCI Registers +/* Подключает "DSP2833x_SysCtrl.h": поставляемое TI описание SysCtrl для семейства C2833x. */ +#include "DSP2833x_SysCtrl.h" // System Control/Power Modes +/* Подключает "DSP2833x_XIntrupt.h": поставляемое TI описание XIntrupt для семейства C2833x. */ +#include "DSP2833x_XIntrupt.h" // External Interrupts +/* Подключает "DSP2833x_Xintf.h": поставляемое TI описание Xintf для семейства C2833x. */ +#include "DSP2833x_Xintf.h" // XINTF External Interface + +/* Подключает "DSP2833x_GlobalPrototypes.h": поставляемое TI описание GlobalPrototypes для семейства C2833x. */ +#include "DSP2833x_GlobalPrototypes.h" // Prototypes for global functions within the + +/* Условие компиляции DSP28_28335: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_28335 +/* Задаёт DSP28_EPWM1 = 1; данные DSP28_EPWM1. */ +#define DSP28_EPWM1 1 +/* Задаёт DSP28_EPWM2 = 1; данные DSP28_EPWM2. */ +#define DSP28_EPWM2 1 +/* Задаёт DSP28_EPWM3 = 1; данные DSP28_EPWM3. */ +#define DSP28_EPWM3 1 +/* Задаёт DSP28_EPWM4 = 1; данные DSP28_EPWM4. */ +#define DSP28_EPWM4 1 +/* Задаёт DSP28_EPWM5 = 1; данные DSP28_EPWM5. */ +#define DSP28_EPWM5 1 +/* Задаёт DSP28_EPWM6 = 1; данные DSP28_EPWM6. */ +#define DSP28_EPWM6 1 +/* Задаёт DSP28_ECAP1 = 1; данные DSP28_ECAP1. */ +#define DSP28_ECAP1 1 +/* Задаёт DSP28_ECAP2 = 1; данные DSP28_ECAP2. */ +#define DSP28_ECAP2 1 +/* Задаёт DSP28_ECAP3 = 1; данные DSP28_ECAP3. */ +#define DSP28_ECAP3 1 +/* Задаёт DSP28_ECAP4 = 1; данные DSP28_ECAP4. */ +#define DSP28_ECAP4 1 +/* Задаёт DSP28_ECAP5 = 1; данные DSP28_ECAP5. */ +#define DSP28_ECAP5 1 +/* Задаёт DSP28_ECAP6 = 1; данные DSP28_ECAP6. */ +#define DSP28_ECAP6 1 +/* Задаёт DSP28_EQEP1 = 1; данные DSP28_EQEP1. */ +#define DSP28_EQEP1 1 +/* Задаёт DSP28_EQEP2 = 1; данные DSP28_EQEP2. */ +#define DSP28_EQEP2 1 +/* Задаёт DSP28_ECANA = 1; данные DSP28_ECANA. */ +#define DSP28_ECANA 1 +/* Задаёт DSP28_ECANB = 1; данные DSP28_ECANB. */ +#define DSP28_ECANB 1 +/* Задаёт DSP28_MCBSPA = 1; данные DSP28_MCBSPA. */ +#define DSP28_MCBSPA 1 +/* Задаёт DSP28_MCBSPB = 1; данные DSP28_MCBSPB. */ +#define DSP28_MCBSPB 1 +/* Задаёт DSP28_SPIA = 1; данные DSP28_SPIA. */ +#define DSP28_SPIA 1 +/* Задаёт DSP28_SCIA = 1; данные DSP28_SCIA. */ +#define DSP28_SCIA 1 +/* Задаёт DSP28_SCIB = 1; данные DSP28_SCIB. */ +#define DSP28_SCIB 1 +/* Задаёт DSP28_SCIC = 1; данные DSP28_SCIC. */ +#define DSP28_SCIC 1 +/* Задаёт DSP28_I2CA = 1; данные DSP28_I2CA. */ +#define DSP28_I2CA 1 +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end DSP28_28335 + +/* Условие компиляции DSP28_28334: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_28334 +/* Задаёт DSP28_EPWM1 = 1; данные DSP28_EPWM1. */ +#define DSP28_EPWM1 1 +/* Задаёт DSP28_EPWM2 = 1; данные DSP28_EPWM2. */ +#define DSP28_EPWM2 1 +/* Задаёт DSP28_EPWM3 = 1; данные DSP28_EPWM3. */ +#define DSP28_EPWM3 1 +/* Задаёт DSP28_EPWM4 = 1; данные DSP28_EPWM4. */ +#define DSP28_EPWM4 1 +/* Задаёт DSP28_EPWM5 = 1; данные DSP28_EPWM5. */ +#define DSP28_EPWM5 1 +/* Задаёт DSP28_EPWM6 = 1; данные DSP28_EPWM6. */ +#define DSP28_EPWM6 1 +/* Задаёт DSP28_ECAP1 = 1; данные DSP28_ECAP1. */ +#define DSP28_ECAP1 1 +/* Задаёт DSP28_ECAP2 = 1; данные DSP28_ECAP2. */ +#define DSP28_ECAP2 1 +/* Задаёт DSP28_ECAP3 = 1; данные DSP28_ECAP3. */ +#define DSP28_ECAP3 1 +/* Задаёт DSP28_ECAP4 = 1; данные DSP28_ECAP4. */ +#define DSP28_ECAP4 1 +/* Задаёт DSP28_ECAP5 = 0; данные DSP28_ECAP5. */ +#define DSP28_ECAP5 0 +/* Задаёт DSP28_ECAP6 = 0; данные DSP28_ECAP6. */ +#define DSP28_ECAP6 0 +/* Задаёт DSP28_EQEP1 = 1; данные DSP28_EQEP1. */ +#define DSP28_EQEP1 1 +/* Задаёт DSP28_EQEP2 = 1; данные DSP28_EQEP2. */ +#define DSP28_EQEP2 1 +/* Задаёт DSP28_ECANA = 1; данные DSP28_ECANA. */ +#define DSP28_ECANA 1 +/* Задаёт DSP28_ECANB = 1; данные DSP28_ECANB. */ +#define DSP28_ECANB 1 +/* Задаёт DSP28_MCBSPA = 1; данные DSP28_MCBSPA. */ +#define DSP28_MCBSPA 1 +/* Задаёт DSP28_MCBSPB = 1; данные DSP28_MCBSPB. */ +#define DSP28_MCBSPB 1 +/* Задаёт DSP28_SPIA = 1; данные DSP28_SPIA. */ +#define DSP28_SPIA 1 +/* Задаёт DSP28_SCIA = 1; данные DSP28_SCIA. */ +#define DSP28_SCIA 1 +/* Задаёт DSP28_SCIB = 1; данные DSP28_SCIB. */ +#define DSP28_SCIB 1 +/* Задаёт DSP28_SCIC = 1; данные DSP28_SCIC. */ +#define DSP28_SCIC 1 +/* Задаёт DSP28_I2CA = 1; данные DSP28_I2CA. */ +#define DSP28_I2CA 1 +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end DSP28_28334 + +/* Условие компиляции DSP28_28332: выбранный блок включается в текущий вариант прошивки. */ +#if DSP28_28332 +/* Задаёт DSP28_EPWM1 = 1; данные DSP28_EPWM1. */ +#define DSP28_EPWM1 1 +/* Задаёт DSP28_EPWM2 = 1; данные DSP28_EPWM2. */ +#define DSP28_EPWM2 1 +/* Задаёт DSP28_EPWM3 = 1; данные DSP28_EPWM3. */ +#define DSP28_EPWM3 1 +/* Задаёт DSP28_EPWM4 = 1; данные DSP28_EPWM4. */ +#define DSP28_EPWM4 1 +/* Задаёт DSP28_EPWM5 = 1; данные DSP28_EPWM5. */ +#define DSP28_EPWM5 1 +/* Задаёт DSP28_EPWM6 = 1; данные DSP28_EPWM6. */ +#define DSP28_EPWM6 1 +/* Задаёт DSP28_ECAP1 = 1; данные DSP28_ECAP1. */ +#define DSP28_ECAP1 1 +/* Задаёт DSP28_ECAP2 = 1; данные DSP28_ECAP2. */ +#define DSP28_ECAP2 1 +/* Задаёт DSP28_ECAP3 = 1; данные DSP28_ECAP3. */ +#define DSP28_ECAP3 1 +/* Задаёт DSP28_ECAP4 = 1; данные DSP28_ECAP4. */ +#define DSP28_ECAP4 1 +/* Задаёт DSP28_ECAP5 = 0; данные DSP28_ECAP5. */ +#define DSP28_ECAP5 0 +/* Задаёт DSP28_ECAP6 = 0; данные DSP28_ECAP6. */ +#define DSP28_ECAP6 0 +/* Задаёт DSP28_EQEP1 = 1; данные DSP28_EQEP1. */ +#define DSP28_EQEP1 1 +/* Задаёт DSP28_EQEP2 = 1; данные DSP28_EQEP2. */ +#define DSP28_EQEP2 1 +/* Задаёт DSP28_ECANA = 1; данные DSP28_ECANA. */ +#define DSP28_ECANA 1 +/* Задаёт DSP28_ECANB = 1; данные DSP28_ECANB. */ +#define DSP28_ECANB 1 +/* Задаёт DSP28_MCBSPA = 1; данные DSP28_MCBSPA. */ +#define DSP28_MCBSPA 1 +/* Задаёт DSP28_MCBSPB = 0; данные DSP28_MCBSPB. */ +#define DSP28_MCBSPB 0 +/* Задаёт DSP28_SPIA = 1; данные DSP28_SPIA. */ +#define DSP28_SPIA 1 +/* Задаёт DSP28_SCIA = 1; данные DSP28_SCIA. */ +#define DSP28_SCIA 1 +/* Задаёт DSP28_SCIB = 1; данные DSP28_SCIB. */ +#define DSP28_SCIB 1 +/* Задаёт DSP28_SCIC = 0; данные DSP28_SCIC. */ +#define DSP28_SCIC 0 +/* Задаёт DSP28_I2CA = 1; данные DSP28_I2CA. */ +#define DSP28_I2CA 1 +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end DSP28_28332 + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_DEVICE_H definition + + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_ECan.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_ECan.h new file mode 100644 index 0000000..965ee77 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_ECan.h @@ -0,0 +1,2109 @@ +/* Поставляемое TI описание ECan для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/2 $ +// Checkin $Date: May 7, 2007 16:05:39 $ +//########################################################################### +// +// FILE: DSP2833x_ECan.h +// +// TITLE: DSP2833x Device eCAN Register Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_ECAN_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_ECAN_H +/* Определяет защитный символ или переключатель DSP2833x_ECAN_H для последующей компиляции. */ +#define DSP2833x_ECAN_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +/* --------------------------------------------------- */ +/* eCAN Control & Status Registers */ +/* ----------------------------------------------------*/ + +/* eCAN Mailbox enable register (CANME) bit definitions */ +/* Описывает структуру CANME_BITS; порядок полей определяет расположение данных. */ +struct CANME_BITS { // bit description + /* Битовое поле ME0, ширина 1 бит; данные ME0. */ + Uint16 ME0:1; // 0 Enable Mailbox 0 + /* Битовое поле ME1, ширина 1 бит; данные ME1. */ + Uint16 ME1:1; // 1 Enable Mailbox 1 + /* Битовое поле ME2, ширина 1 бит; данные ME2. */ + Uint16 ME2:1; // 2 Enable Mailbox 2 + /* Битовое поле ME3, ширина 1 бит; данные ME3. */ + Uint16 ME3:1; // 3 Enable Mailbox 3 + /* Битовое поле ME4, ширина 1 бит; данные ME4. */ + Uint16 ME4:1; // 4 Enable Mailbox 4 + /* Битовое поле ME5, ширина 1 бит; данные ME5. */ + Uint16 ME5:1; // 5 Enable Mailbox 5 + /* Битовое поле ME6, ширина 1 бит; данные ME6. */ + Uint16 ME6:1; // 6 Enable Mailbox 6 + /* Битовое поле ME7, ширина 1 бит; данные ME7. */ + Uint16 ME7:1; // 7 Enable Mailbox 7 + /* Битовое поле ME8, ширина 1 бит; данные ME8. */ + Uint16 ME8:1; // 8 Enable Mailbox 8 + /* Битовое поле ME9, ширина 1 бит; данные ME9. */ + Uint16 ME9:1; // 9 Enable Mailbox 9 + /* Битовое поле ME10, ширина 1 бит; данные ME10. */ + Uint16 ME10:1; // 10 Enable Mailbox 10 + /* Битовое поле ME11, ширина 1 бит; данные ME11. */ + Uint16 ME11:1; // 11 Enable Mailbox 11 + /* Битовое поле ME12, ширина 1 бит; данные ME12. */ + Uint16 ME12:1; // 12 Enable Mailbox 12 + /* Битовое поле ME13, ширина 1 бит; данные ME13. */ + Uint16 ME13:1; // 13 Enable Mailbox 13 + /* Битовое поле ME14, ширина 1 бит; данные ME14. */ + Uint16 ME14:1; // 14 Enable Mailbox 14 + /* Битовое поле ME15, ширина 1 бит; данные ME15. */ + Uint16 ME15:1; // 15 Enable Mailbox 15 + /* Битовое поле ME16, ширина 1 бит; данные ME16. */ + Uint16 ME16:1; // 16 Enable Mailbox 16 + /* Битовое поле ME17, ширина 1 бит; данные ME17. */ + Uint16 ME17:1; // 17 Enable Mailbox 17 + /* Битовое поле ME18, ширина 1 бит; данные ME18. */ + Uint16 ME18:1; // 18 Enable Mailbox 18 + /* Битовое поле ME19, ширина 1 бит; данные ME19. */ + Uint16 ME19:1; // 19 Enable Mailbox 19 + /* Битовое поле ME20, ширина 1 бит; данные ME20. */ + Uint16 ME20:1; // 20 Enable Mailbox 20 + /* Битовое поле ME21, ширина 1 бит; данные ME21. */ + Uint16 ME21:1; // 21 Enable Mailbox 21 + /* Битовое поле ME22, ширина 1 бит; данные ME22. */ + Uint16 ME22:1; // 22 Enable Mailbox 22 + /* Битовое поле ME23, ширина 1 бит; данные ME23. */ + Uint16 ME23:1; // 23 Enable Mailbox 23 + /* Битовое поле ME24, ширина 1 бит; данные ME24. */ + Uint16 ME24:1; // 24 Enable Mailbox 24 + /* Битовое поле ME25, ширина 1 бит; данные ME25. */ + Uint16 ME25:1; // 25 Enable Mailbox 25 + /* Битовое поле ME26, ширина 1 бит; данные ME26. */ + Uint16 ME26:1; // 26 Enable Mailbox 26 + /* Битовое поле ME27, ширина 1 бит; данные ME27. */ + Uint16 ME27:1; // 27 Enable Mailbox 27 + /* Битовое поле ME28, ширина 1 бит; данные ME28. */ + Uint16 ME28:1; // 28 Enable Mailbox 28 + /* Битовое поле ME29, ширина 1 бит; данные ME29. */ + Uint16 ME29:1; // 29 Enable Mailbox 29 + /* Битовое поле ME30, ширина 1 бит; данные ME30. */ + Uint16 ME30:1; // 30 Enable Mailbox 30 + /* Битовое поле ME31, ширина 1 бит; данные ME31. */ + Uint16 ME31:1; // 31 Enable Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANME_REG в одной области памяти. */ +union CANME_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANME_BITS bit;; порядок полей определяет расположение данных. */ + struct CANME_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Mailbox direction register (CANMD) bit definitions */ +/* Описывает структуру CANMD_BITS; порядок полей определяет расположение данных. */ +struct CANMD_BITS { // bit description + /* Битовое поле MD0, ширина 1 бит; данные MD0. */ + Uint16 MD0:1; // 0 0 -> Tx 1 -> Rx + /* Битовое поле MD1, ширина 1 бит; данные MD1. */ + Uint16 MD1:1; // 1 0 -> Tx 1 -> Rx + /* Битовое поле MD2, ширина 1 бит; данные MD2. */ + Uint16 MD2:1; // 2 0 -> Tx 1 -> Rx + /* Битовое поле MD3, ширина 1 бит; данные MD3. */ + Uint16 MD3:1; // 3 0 -> Tx 1 -> Rx + /* Битовое поле MD4, ширина 1 бит; данные MD4. */ + Uint16 MD4:1; // 4 0 -> Tx 1 -> Rx + /* Битовое поле MD5, ширина 1 бит; данные MD5. */ + Uint16 MD5:1; // 5 0 -> Tx 1 -> Rx + /* Битовое поле MD6, ширина 1 бит; данные MD6. */ + Uint16 MD6:1; // 6 0 -> Tx 1 -> Rx + /* Битовое поле MD7, ширина 1 бит; данные MD7. */ + Uint16 MD7:1; // 7 0 -> Tx 1 -> Rx + /* Битовое поле MD8, ширина 1 бит; данные MD8. */ + Uint16 MD8:1; // 8 0 -> Tx 1 -> Rx + /* Битовое поле MD9, ширина 1 бит; данные MD9. */ + Uint16 MD9:1; // 9 0 -> Tx 1 -> Rx + /* Битовое поле MD10, ширина 1 бит; данные MD10. */ + Uint16 MD10:1; // 10 0 -> Tx 1 -> Rx + /* Битовое поле MD11, ширина 1 бит; данные MD11. */ + Uint16 MD11:1; // 11 0 -> Tx 1 -> Rx + /* Битовое поле MD12, ширина 1 бит; данные MD12. */ + Uint16 MD12:1; // 12 0 -> Tx 1 -> Rx + /* Битовое поле MD13, ширина 1 бит; данные MD13. */ + Uint16 MD13:1; // 13 0 -> Tx 1 -> Rx + /* Битовое поле MD14, ширина 1 бит; данные MD14. */ + Uint16 MD14:1; // 14 0 -> Tx 1 -> Rx + /* Битовое поле MD15, ширина 1 бит; данные MD15. */ + Uint16 MD15:1; // 15 0 -> Tx 1 -> Rx + /* Битовое поле MD16, ширина 1 бит; данные MD16. */ + Uint16 MD16:1; // 16 0 -> Tx 1 -> Rx + /* Битовое поле MD17, ширина 1 бит; данные MD17. */ + Uint16 MD17:1; // 17 0 -> Tx 1 -> Rx + /* Битовое поле MD18, ширина 1 бит; данные MD18. */ + Uint16 MD18:1; // 18 0 -> Tx 1 -> Rx + /* Битовое поле MD19, ширина 1 бит; данные MD19. */ + Uint16 MD19:1; // 19 0 -> Tx 1 -> Rx + /* Битовое поле MD20, ширина 1 бит; данные MD20. */ + Uint16 MD20:1; // 20 0 -> Tx 1 -> Rx + /* Битовое поле MD21, ширина 1 бит; данные MD21. */ + Uint16 MD21:1; // 21 0 -> Tx 1 -> Rx + /* Битовое поле MD22, ширина 1 бит; данные MD22. */ + Uint16 MD22:1; // 22 0 -> Tx 1 -> Rx + /* Битовое поле MD23, ширина 1 бит; данные MD23. */ + Uint16 MD23:1; // 23 0 -> Tx 1 -> Rx + /* Битовое поле MD24, ширина 1 бит; данные MD24. */ + Uint16 MD24:1; // 24 0 -> Tx 1 -> Rx + /* Битовое поле MD25, ширина 1 бит; данные MD25. */ + Uint16 MD25:1; // 25 0 -> Tx 1 -> Rx + /* Битовое поле MD26, ширина 1 бит; данные MD26. */ + Uint16 MD26:1; // 26 0 -> Tx 1 -> Rx + /* Битовое поле MD27, ширина 1 бит; данные MD27. */ + Uint16 MD27:1; // 27 0 -> Tx 1 -> Rx + /* Битовое поле MD28, ширина 1 бит; данные MD28. */ + Uint16 MD28:1; // 28 0 -> Tx 1 -> Rx + /* Битовое поле MD29, ширина 1 бит; данные MD29. */ + Uint16 MD29:1; // 29 0 -> Tx 1 -> Rx + /* Битовое поле MD30, ширина 1 бит; данные MD30. */ + Uint16 MD30:1; // 30 0 -> Tx 1 -> Rx + /* Битовое поле MD31, ширина 1 бит; данные MD31. */ + Uint16 MD31:1; // 31 0 -> Tx 1 -> Rx + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANMD_REG в одной области памяти. */ +union CANMD_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANMD_BITS bit;; порядок полей определяет расположение данных. */ + struct CANMD_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Transmit Request Set register (CANTRS) bit definitions */ +/* Описывает структуру CANTRS_BITS; порядок полей определяет расположение данных. */ +struct CANTRS_BITS { // bit description + /* Битовое поле TRS0, ширина 1 бит; данные TRS0. */ + Uint16 TRS0:1; // 0 TRS for Mailbox 0 + /* Битовое поле TRS1, ширина 1 бит; данные TRS1. */ + Uint16 TRS1:1; // 1 TRS for Mailbox 1 + /* Битовое поле TRS2, ширина 1 бит; данные TRS2. */ + Uint16 TRS2:1; // 2 TRS for Mailbox 2 + /* Битовое поле TRS3, ширина 1 бит; данные TRS3. */ + Uint16 TRS3:1; // 3 TRS for Mailbox 3 + /* Битовое поле TRS4, ширина 1 бит; данные TRS4. */ + Uint16 TRS4:1; // 4 TRS for Mailbox 4 + /* Битовое поле TRS5, ширина 1 бит; данные TRS5. */ + Uint16 TRS5:1; // 5 TRS for Mailbox 5 + /* Битовое поле TRS6, ширина 1 бит; данные TRS6. */ + Uint16 TRS6:1; // 6 TRS for Mailbox 6 + /* Битовое поле TRS7, ширина 1 бит; данные TRS7. */ + Uint16 TRS7:1; // 7 TRS for Mailbox 7 + /* Битовое поле TRS8, ширина 1 бит; данные TRS8. */ + Uint16 TRS8:1; // 8 TRS for Mailbox 8 + /* Битовое поле TRS9, ширина 1 бит; данные TRS9. */ + Uint16 TRS9:1; // 9 TRS for Mailbox 9 + /* Битовое поле TRS10, ширина 1 бит; данные TRS10. */ + Uint16 TRS10:1; // 10 TRS for Mailbox 10 + /* Битовое поле TRS11, ширина 1 бит; данные TRS11. */ + Uint16 TRS11:1; // 11 TRS for Mailbox 11 + /* Битовое поле TRS12, ширина 1 бит; данные TRS12. */ + Uint16 TRS12:1; // 12 TRS for Mailbox 12 + /* Битовое поле TRS13, ширина 1 бит; данные TRS13. */ + Uint16 TRS13:1; // 13 TRS for Mailbox 13 + /* Битовое поле TRS14, ширина 1 бит; данные TRS14. */ + Uint16 TRS14:1; // 14 TRS for Mailbox 14 + /* Битовое поле TRS15, ширина 1 бит; данные TRS15. */ + Uint16 TRS15:1; // 15 TRS for Mailbox 15 + /* Битовое поле TRS16, ширина 1 бит; данные TRS16. */ + Uint16 TRS16:1; // 16 TRS for Mailbox 16 + /* Битовое поле TRS17, ширина 1 бит; данные TRS17. */ + Uint16 TRS17:1; // 17 TRS for Mailbox 17 + /* Битовое поле TRS18, ширина 1 бит; данные TRS18. */ + Uint16 TRS18:1; // 18 TRS for Mailbox 18 + /* Битовое поле TRS19, ширина 1 бит; данные TRS19. */ + Uint16 TRS19:1; // 19 TRS for Mailbox 19 + /* Битовое поле TRS20, ширина 1 бит; данные TRS20. */ + Uint16 TRS20:1; // 20 TRS for Mailbox 20 + /* Битовое поле TRS21, ширина 1 бит; данные TRS21. */ + Uint16 TRS21:1; // 21 TRS for Mailbox 21 + /* Битовое поле TRS22, ширина 1 бит; данные TRS22. */ + Uint16 TRS22:1; // 22 TRS for Mailbox 22 + /* Битовое поле TRS23, ширина 1 бит; данные TRS23. */ + Uint16 TRS23:1; // 23 TRS for Mailbox 23 + /* Битовое поле TRS24, ширина 1 бит; данные TRS24. */ + Uint16 TRS24:1; // 24 TRS for Mailbox 24 + /* Битовое поле TRS25, ширина 1 бит; данные TRS25. */ + Uint16 TRS25:1; // 25 TRS for Mailbox 25 + /* Битовое поле TRS26, ширина 1 бит; данные TRS26. */ + Uint16 TRS26:1; // 26 TRS for Mailbox 26 + /* Битовое поле TRS27, ширина 1 бит; данные TRS27. */ + Uint16 TRS27:1; // 27 TRS for Mailbox 27 + /* Битовое поле TRS28, ширина 1 бит; данные TRS28. */ + Uint16 TRS28:1; // 28 TRS for Mailbox 28 + /* Битовое поле TRS29, ширина 1 бит; данные TRS29. */ + Uint16 TRS29:1; // 29 TRS for Mailbox 29 + /* Битовое поле TRS30, ширина 1 бит; данные TRS30. */ + Uint16 TRS30:1; // 30 TRS for Mailbox 30 + /* Битовое поле TRS31, ширина 1 бит; данные TRS31. */ + Uint16 TRS31:1; // 31 TRS for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANTRS_REG в одной области памяти. */ +union CANTRS_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANTRS_BITS bit;; порядок полей определяет расположение данных. */ + struct CANTRS_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Transmit Request Reset register (CANTRR) bit definitions */ +/* Описывает структуру CANTRR_BITS; порядок полей определяет расположение данных. */ +struct CANTRR_BITS { // bit description + /* Битовое поле TRR0, ширина 1 бит; данные TRR0. */ + Uint16 TRR0:1; // 0 TRR for Mailbox 0 + /* Битовое поле TRR1, ширина 1 бит; данные TRR1. */ + Uint16 TRR1:1; // 1 TRR for Mailbox 1 + /* Битовое поле TRR2, ширина 1 бит; данные TRR2. */ + Uint16 TRR2:1; // 2 TRR for Mailbox 2 + /* Битовое поле TRR3, ширина 1 бит; данные TRR3. */ + Uint16 TRR3:1; // 3 TRR for Mailbox 3 + /* Битовое поле TRR4, ширина 1 бит; данные TRR4. */ + Uint16 TRR4:1; // 4 TRR for Mailbox 4 + /* Битовое поле TRR5, ширина 1 бит; данные TRR5. */ + Uint16 TRR5:1; // 5 TRR for Mailbox 5 + /* Битовое поле TRR6, ширина 1 бит; данные TRR6. */ + Uint16 TRR6:1; // 6 TRR for Mailbox 6 + /* Битовое поле TRR7, ширина 1 бит; данные TRR7. */ + Uint16 TRR7:1; // 7 TRR for Mailbox 7 + /* Битовое поле TRR8, ширина 1 бит; данные TRR8. */ + Uint16 TRR8:1; // 8 TRR for Mailbox 8 + /* Битовое поле TRR9, ширина 1 бит; данные TRR9. */ + Uint16 TRR9:1; // 9 TRR for Mailbox 9 + /* Битовое поле TRR10, ширина 1 бит; данные TRR10. */ + Uint16 TRR10:1; // 10 TRR for Mailbox 10 + /* Битовое поле TRR11, ширина 1 бит; данные TRR11. */ + Uint16 TRR11:1; // 11 TRR for Mailbox 11 + /* Битовое поле TRR12, ширина 1 бит; данные TRR12. */ + Uint16 TRR12:1; // 12 TRR for Mailbox 12 + /* Битовое поле TRR13, ширина 1 бит; данные TRR13. */ + Uint16 TRR13:1; // 13 TRR for Mailbox 13 + /* Битовое поле TRR14, ширина 1 бит; данные TRR14. */ + Uint16 TRR14:1; // 14 TRR for Mailbox 14 + /* Битовое поле TRR15, ширина 1 бит; данные TRR15. */ + Uint16 TRR15:1; // 15 TRR for Mailbox 15 + /* Битовое поле TRR16, ширина 1 бит; данные TRR16. */ + Uint16 TRR16:1; // 16 TRR for Mailbox 16 + /* Битовое поле TRR17, ширина 1 бит; данные TRR17. */ + Uint16 TRR17:1; // 17 TRR for Mailbox 17 + /* Битовое поле TRR18, ширина 1 бит; данные TRR18. */ + Uint16 TRR18:1; // 18 TRR for Mailbox 18 + /* Битовое поле TRR19, ширина 1 бит; данные TRR19. */ + Uint16 TRR19:1; // 19 TRR for Mailbox 19 + /* Битовое поле TRR20, ширина 1 бит; данные TRR20. */ + Uint16 TRR20:1; // 20 TRR for Mailbox 20 + /* Битовое поле TRR21, ширина 1 бит; данные TRR21. */ + Uint16 TRR21:1; // 21 TRR for Mailbox 21 + /* Битовое поле TRR22, ширина 1 бит; данные TRR22. */ + Uint16 TRR22:1; // 22 TRR for Mailbox 22 + /* Битовое поле TRR23, ширина 1 бит; данные TRR23. */ + Uint16 TRR23:1; // 23 TRR for Mailbox 23 + /* Битовое поле TRR24, ширина 1 бит; данные TRR24. */ + Uint16 TRR24:1; // 24 TRR for Mailbox 24 + /* Битовое поле TRR25, ширина 1 бит; данные TRR25. */ + Uint16 TRR25:1; // 25 TRR for Mailbox 25 + /* Битовое поле TRR26, ширина 1 бит; данные TRR26. */ + Uint16 TRR26:1; // 26 TRR for Mailbox 26 + /* Битовое поле TRR27, ширина 1 бит; данные TRR27. */ + Uint16 TRR27:1; // 27 TRR for Mailbox 27 + /* Битовое поле TRR28, ширина 1 бит; данные TRR28. */ + Uint16 TRR28:1; // 28 TRR for Mailbox 28 + /* Битовое поле TRR29, ширина 1 бит; данные TRR29. */ + Uint16 TRR29:1; // 29 TRR for Mailbox 29 + /* Битовое поле TRR30, ширина 1 бит; данные TRR30. */ + Uint16 TRR30:1; // 30 TRR for Mailbox 30 + /* Битовое поле TRR31, ширина 1 бит; данные TRR31. */ + Uint16 TRR31:1; // 31 TRR for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANTRR_REG в одной области памяти. */ +union CANTRR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANTRR_BITS bit;; порядок полей определяет расположение данных. */ + struct CANTRR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Transmit Acknowledge register (CANTA) bit definitions */ +/* Описывает структуру CANTA_BITS; порядок полей определяет расположение данных. */ +struct CANTA_BITS { // bit description + /* Битовое поле TA0, ширина 1 бит; данные TA0. */ + Uint16 TA0:1; // 0 TA for Mailbox 0 + /* Битовое поле TA1, ширина 1 бит; данные TA1. */ + Uint16 TA1:1; // 1 TA for Mailbox 1 + /* Битовое поле TA2, ширина 1 бит; данные TA2. */ + Uint16 TA2:1; // 2 TA for Mailbox 2 + /* Битовое поле TA3, ширина 1 бит; данные TA3. */ + Uint16 TA3:1; // 3 TA for Mailbox 3 + /* Битовое поле TA4, ширина 1 бит; данные TA4. */ + Uint16 TA4:1; // 4 TA for Mailbox 4 + /* Битовое поле TA5, ширина 1 бит; данные TA5. */ + Uint16 TA5:1; // 5 TA for Mailbox 5 + /* Битовое поле TA6, ширина 1 бит; данные TA6. */ + Uint16 TA6:1; // 6 TA for Mailbox 6 + /* Битовое поле TA7, ширина 1 бит; данные TA7. */ + Uint16 TA7:1; // 7 TA for Mailbox 7 + /* Битовое поле TA8, ширина 1 бит; данные TA8. */ + Uint16 TA8:1; // 8 TA for Mailbox 8 + /* Битовое поле TA9, ширина 1 бит; данные TA9. */ + Uint16 TA9:1; // 9 TA for Mailbox 9 + /* Битовое поле TA10, ширина 1 бит; данные TA10. */ + Uint16 TA10:1; // 10 TA for Mailbox 10 + /* Битовое поле TA11, ширина 1 бит; данные TA11. */ + Uint16 TA11:1; // 11 TA for Mailbox 11 + /* Битовое поле TA12, ширина 1 бит; данные TA12. */ + Uint16 TA12:1; // 12 TA for Mailbox 12 + /* Битовое поле TA13, ширина 1 бит; данные TA13. */ + Uint16 TA13:1; // 13 TA for Mailbox 13 + /* Битовое поле TA14, ширина 1 бит; данные TA14. */ + Uint16 TA14:1; // 14 TA for Mailbox 14 + /* Битовое поле TA15, ширина 1 бит; данные TA15. */ + Uint16 TA15:1; // 15 TA for Mailbox 15 + /* Битовое поле TA16, ширина 1 бит; данные TA16. */ + Uint16 TA16:1; // 16 TA for Mailbox 16 + /* Битовое поле TA17, ширина 1 бит; данные TA17. */ + Uint16 TA17:1; // 17 TA for Mailbox 17 + /* Битовое поле TA18, ширина 1 бит; данные TA18. */ + Uint16 TA18:1; // 18 TA for Mailbox 18 + /* Битовое поле TA19, ширина 1 бит; данные TA19. */ + Uint16 TA19:1; // 19 TA for Mailbox 19 + /* Битовое поле TA20, ширина 1 бит; данные TA20. */ + Uint16 TA20:1; // 20 TA for Mailbox 20 + /* Битовое поле TA21, ширина 1 бит; данные TA21. */ + Uint16 TA21:1; // 21 TA for Mailbox 21 + /* Битовое поле TA22, ширина 1 бит; данные TA22. */ + Uint16 TA22:1; // 22 TA for Mailbox 22 + /* Битовое поле TA23, ширина 1 бит; данные TA23. */ + Uint16 TA23:1; // 23 TA for Mailbox 23 + /* Битовое поле TA24, ширина 1 бит; данные TA24. */ + Uint16 TA24:1; // 24 TA for Mailbox 24 + /* Битовое поле TA25, ширина 1 бит; данные TA25. */ + Uint16 TA25:1; // 25 TA for Mailbox 25 + /* Битовое поле TA26, ширина 1 бит; данные TA26. */ + Uint16 TA26:1; // 26 TA for Mailbox 26 + /* Битовое поле TA27, ширина 1 бит; данные TA27. */ + Uint16 TA27:1; // 27 TA for Mailbox 27 + /* Битовое поле TA28, ширина 1 бит; данные TA28. */ + Uint16 TA28:1; // 28 TA for Mailbox 28 + /* Битовое поле TA29, ширина 1 бит; данные TA29. */ + Uint16 TA29:1; // 29 TA for Mailbox 29 + /* Битовое поле TA30, ширина 1 бит; данные TA30. */ + Uint16 TA30:1; // 30 TA for Mailbox 30 + /* Битовое поле TA31, ширина 1 бит; данные TA31. */ + Uint16 TA31:1; // 31 TA for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANTA_REG в одной области памяти. */ +union CANTA_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANTA_BITS bit;; порядок полей определяет расположение данных. */ + struct CANTA_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Transmit Abort Acknowledge register (CANAA) bit definitions */ +/* Описывает структуру CANAA_BITS; порядок полей определяет расположение данных. */ +struct CANAA_BITS { // bit description + /* Битовое поле AA0, ширина 1 бит; данные AA0. */ + Uint16 AA0:1; // 0 AA for Mailbox 0 + /* Битовое поле AA1, ширина 1 бит; данные AA1. */ + Uint16 AA1:1; // 1 AA for Mailbox 1 + /* Битовое поле AA2, ширина 1 бит; данные AA2. */ + Uint16 AA2:1; // 2 AA for Mailbox 2 + /* Битовое поле AA3, ширина 1 бит; данные AA3. */ + Uint16 AA3:1; // 3 AA for Mailbox 3 + /* Битовое поле AA4, ширина 1 бит; данные AA4. */ + Uint16 AA4:1; // 4 AA for Mailbox 4 + /* Битовое поле AA5, ширина 1 бит; данные AA5. */ + Uint16 AA5:1; // 5 AA for Mailbox 5 + /* Битовое поле AA6, ширина 1 бит; данные AA6. */ + Uint16 AA6:1; // 6 AA for Mailbox 6 + /* Битовое поле AA7, ширина 1 бит; данные AA7. */ + Uint16 AA7:1; // 7 AA for Mailbox 7 + /* Битовое поле AA8, ширина 1 бит; данные AA8. */ + Uint16 AA8:1; // 8 AA for Mailbox 8 + /* Битовое поле AA9, ширина 1 бит; данные AA9. */ + Uint16 AA9:1; // 9 AA for Mailbox 9 + /* Битовое поле AA10, ширина 1 бит; данные AA10. */ + Uint16 AA10:1; // 10 AA for Mailbox 10 + /* Битовое поле AA11, ширина 1 бит; данные AA11. */ + Uint16 AA11:1; // 11 AA for Mailbox 11 + /* Битовое поле AA12, ширина 1 бит; данные AA12. */ + Uint16 AA12:1; // 12 AA for Mailbox 12 + /* Битовое поле AA13, ширина 1 бит; данные AA13. */ + Uint16 AA13:1; // 13 AA for Mailbox 13 + /* Битовое поле AA14, ширина 1 бит; данные AA14. */ + Uint16 AA14:1; // 14 AA for Mailbox 14 + /* Битовое поле AA15, ширина 1 бит; данные AA15. */ + Uint16 AA15:1; // 15 AA for Mailbox 15 + /* Битовое поле AA16, ширина 1 бит; данные AA16. */ + Uint16 AA16:1; // 16 AA for Mailbox 16 + /* Битовое поле AA17, ширина 1 бит; данные AA17. */ + Uint16 AA17:1; // 17 AA for Mailbox 17 + /* Битовое поле AA18, ширина 1 бит; данные AA18. */ + Uint16 AA18:1; // 18 AA for Mailbox 18 + /* Битовое поле AA19, ширина 1 бит; данные AA19. */ + Uint16 AA19:1; // 19 AA for Mailbox 19 + /* Битовое поле AA20, ширина 1 бит; данные AA20. */ + Uint16 AA20:1; // 20 AA for Mailbox 20 + /* Битовое поле AA21, ширина 1 бит; данные AA21. */ + Uint16 AA21:1; // 21 AA for Mailbox 21 + /* Битовое поле AA22, ширина 1 бит; данные AA22. */ + Uint16 AA22:1; // 22 AA for Mailbox 22 + /* Битовое поле AA23, ширина 1 бит; данные AA23. */ + Uint16 AA23:1; // 23 AA for Mailbox 23 + /* Битовое поле AA24, ширина 1 бит; данные AA24. */ + Uint16 AA24:1; // 24 AA for Mailbox 24 + /* Битовое поле AA25, ширина 1 бит; данные AA25. */ + Uint16 AA25:1; // 25 AA for Mailbox 25 + /* Битовое поле AA26, ширина 1 бит; данные AA26. */ + Uint16 AA26:1; // 26 AA for Mailbox 26 + /* Битовое поле AA27, ширина 1 бит; данные AA27. */ + Uint16 AA27:1; // 27 AA for Mailbox 27 + /* Битовое поле AA28, ширина 1 бит; данные AA28. */ + Uint16 AA28:1; // 28 AA for Mailbox 28 + /* Битовое поле AA29, ширина 1 бит; данные AA29. */ + Uint16 AA29:1; // 29 AA for Mailbox 29 + /* Битовое поле AA30, ширина 1 бит; данные AA30. */ + Uint16 AA30:1; // 30 AA for Mailbox 30 + /* Битовое поле AA31, ширина 1 бит; данные AA31. */ + Uint16 AA31:1; // 31 AA for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANAA_REG в одной области памяти. */ +union CANAA_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANAA_BITS bit;; порядок полей определяет расположение данных. */ + struct CANAA_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Received Message Pending register (CANRMP) bit definitions */ +/* Описывает структуру CANRMP_BITS; порядок полей определяет расположение данных. */ +struct CANRMP_BITS { // bit description + /* Битовое поле RMP0, ширина 1 бит; данные RMP0. */ + Uint16 RMP0:1; // 0 RMP for Mailbox 0 + /* Битовое поле RMP1, ширина 1 бит; данные RMP1. */ + Uint16 RMP1:1; // 1 RMP for Mailbox 1 + /* Битовое поле RMP2, ширина 1 бит; данные RMP2. */ + Uint16 RMP2:1; // 2 RMP for Mailbox 2 + /* Битовое поле RMP3, ширина 1 бит; данные RMP3. */ + Uint16 RMP3:1; // 3 RMP for Mailbox 3 + /* Битовое поле RMP4, ширина 1 бит; данные RMP4. */ + Uint16 RMP4:1; // 4 RMP for Mailbox 4 + /* Битовое поле RMP5, ширина 1 бит; данные RMP5. */ + Uint16 RMP5:1; // 5 RMP for Mailbox 5 + /* Битовое поле RMP6, ширина 1 бит; данные RMP6. */ + Uint16 RMP6:1; // 6 RMP for Mailbox 6 + /* Битовое поле RMP7, ширина 1 бит; данные RMP7. */ + Uint16 RMP7:1; // 7 RMP for Mailbox 7 + /* Битовое поле RMP8, ширина 1 бит; данные RMP8. */ + Uint16 RMP8:1; // 8 RMP for Mailbox 8 + /* Битовое поле RMP9, ширина 1 бит; данные RMP9. */ + Uint16 RMP9:1; // 9 RMP for Mailbox 9 + /* Битовое поле RMP10, ширина 1 бит; данные RMP10. */ + Uint16 RMP10:1; // 10 RMP for Mailbox 10 + /* Битовое поле RMP11, ширина 1 бит; данные RMP11. */ + Uint16 RMP11:1; // 11 RMP for Mailbox 11 + /* Битовое поле RMP12, ширина 1 бит; данные RMP12. */ + Uint16 RMP12:1; // 12 RMP for Mailbox 12 + /* Битовое поле RMP13, ширина 1 бит; данные RMP13. */ + Uint16 RMP13:1; // 13 RMP for Mailbox 13 + /* Битовое поле RMP14, ширина 1 бит; данные RMP14. */ + Uint16 RMP14:1; // 14 RMP for Mailbox 14 + /* Битовое поле RMP15, ширина 1 бит; данные RMP15. */ + Uint16 RMP15:1; // 15 RMP for Mailbox 15 + /* Битовое поле RMP16, ширина 1 бит; данные RMP16. */ + Uint16 RMP16:1; // 16 RMP for Mailbox 16 + /* Битовое поле RMP17, ширина 1 бит; данные RMP17. */ + Uint16 RMP17:1; // 17 RMP for Mailbox 17 + /* Битовое поле RMP18, ширина 1 бит; данные RMP18. */ + Uint16 RMP18:1; // 18 RMP for Mailbox 18 + /* Битовое поле RMP19, ширина 1 бит; данные RMP19. */ + Uint16 RMP19:1; // 19 RMP for Mailbox 19 + /* Битовое поле RMP20, ширина 1 бит; данные RMP20. */ + Uint16 RMP20:1; // 20 RMP for Mailbox 20 + /* Битовое поле RMP21, ширина 1 бит; данные RMP21. */ + Uint16 RMP21:1; // 21 RMP for Mailbox 21 + /* Битовое поле RMP22, ширина 1 бит; данные RMP22. */ + Uint16 RMP22:1; // 22 RMP for Mailbox 22 + /* Битовое поле RMP23, ширина 1 бит; данные RMP23. */ + Uint16 RMP23:1; // 23 RMP for Mailbox 23 + /* Битовое поле RMP24, ширина 1 бит; данные RMP24. */ + Uint16 RMP24:1; // 24 RMP for Mailbox 24 + /* Битовое поле RMP25, ширина 1 бит; данные RMP25. */ + Uint16 RMP25:1; // 25 RMP for Mailbox 25 + /* Битовое поле RMP26, ширина 1 бит; данные RMP26. */ + Uint16 RMP26:1; // 26 RMP for Mailbox 26 + /* Битовое поле RMP27, ширина 1 бит; данные RMP27. */ + Uint16 RMP27:1; // 27 RMP for Mailbox 27 + /* Битовое поле RMP28, ширина 1 бит; данные RMP28. */ + Uint16 RMP28:1; // 28 RMP for Mailbox 28 + /* Битовое поле RMP29, ширина 1 бит; данные RMP29. */ + Uint16 RMP29:1; // 29 RMP for Mailbox 29 + /* Битовое поле RMP30, ширина 1 бит; данные RMP30. */ + Uint16 RMP30:1; // 30 RMP for Mailbox 30 + /* Битовое поле RMP31, ширина 1 бит; данные RMP31. */ + Uint16 RMP31:1; // 31 RMP for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANRMP_REG в одной области памяти. */ +union CANRMP_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANRMP_BITS bit;; порядок полей определяет расположение данных. */ + struct CANRMP_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Received Message Lost register (CANRML) bit definitions */ +/* Описывает структуру CANRML_BITS; порядок полей определяет расположение данных. */ +struct CANRML_BITS { // bit description + /* Битовое поле RML0, ширина 1 бит; данные RML0. */ + Uint16 RML0:1; // 0 RML for Mailbox 0 + /* Битовое поле RML1, ширина 1 бит; данные RML1. */ + Uint16 RML1:1; // 1 RML for Mailbox 1 + /* Битовое поле RML2, ширина 1 бит; данные RML2. */ + Uint16 RML2:1; // 2 RML for Mailbox 2 + /* Битовое поле RML3, ширина 1 бит; данные RML3. */ + Uint16 RML3:1; // 3 RML for Mailbox 3 + /* Битовое поле RML4, ширина 1 бит; данные RML4. */ + Uint16 RML4:1; // 4 RML for Mailbox 4 + /* Битовое поле RML5, ширина 1 бит; данные RML5. */ + Uint16 RML5:1; // 5 RML for Mailbox 5 + /* Битовое поле RML6, ширина 1 бит; данные RML6. */ + Uint16 RML6:1; // 6 RML for Mailbox 6 + /* Битовое поле RML7, ширина 1 бит; данные RML7. */ + Uint16 RML7:1; // 7 RML for Mailbox 7 + /* Битовое поле RML8, ширина 1 бит; данные RML8. */ + Uint16 RML8:1; // 8 RML for Mailbox 8 + /* Битовое поле RML9, ширина 1 бит; данные RML9. */ + Uint16 RML9:1; // 9 RML for Mailbox 9 + /* Битовое поле RML10, ширина 1 бит; данные RML10. */ + Uint16 RML10:1; // 10 RML for Mailbox 10 + /* Битовое поле RML11, ширина 1 бит; данные RML11. */ + Uint16 RML11:1; // 11 RML for Mailbox 11 + /* Битовое поле RML12, ширина 1 бит; данные RML12. */ + Uint16 RML12:1; // 12 RML for Mailbox 12 + /* Битовое поле RML13, ширина 1 бит; данные RML13. */ + Uint16 RML13:1; // 13 RML for Mailbox 13 + /* Битовое поле RML14, ширина 1 бит; данные RML14. */ + Uint16 RML14:1; // 14 RML for Mailbox 14 + /* Битовое поле RML15, ширина 1 бит; данные RML15. */ + Uint16 RML15:1; // 15 RML for Mailbox 15 + /* Битовое поле RML16, ширина 1 бит; данные RML16. */ + Uint16 RML16:1; // 16 RML for Mailbox 16 + /* Битовое поле RML17, ширина 1 бит; данные RML17. */ + Uint16 RML17:1; // 17 RML for Mailbox 17 + /* Битовое поле RML18, ширина 1 бит; данные RML18. */ + Uint16 RML18:1; // 18 RML for Mailbox 18 + /* Битовое поле RML19, ширина 1 бит; данные RML19. */ + Uint16 RML19:1; // 19 RML for Mailbox 19 + /* Битовое поле RML20, ширина 1 бит; данные RML20. */ + Uint16 RML20:1; // 20 RML for Mailbox 20 + /* Битовое поле RML21, ширина 1 бит; данные RML21. */ + Uint16 RML21:1; // 21 RML for Mailbox 21 + /* Битовое поле RML22, ширина 1 бит; данные RML22. */ + Uint16 RML22:1; // 22 RML for Mailbox 22 + /* Битовое поле RML23, ширина 1 бит; данные RML23. */ + Uint16 RML23:1; // 23 RML for Mailbox 23 + /* Битовое поле RML24, ширина 1 бит; данные RML24. */ + Uint16 RML24:1; // 24 RML for Mailbox 24 + /* Битовое поле RML25, ширина 1 бит; данные RML25. */ + Uint16 RML25:1; // 25 RML for Mailbox 25 + /* Битовое поле RML26, ширина 1 бит; данные RML26. */ + Uint16 RML26:1; // 26 RML for Mailbox 26 + /* Битовое поле RML27, ширина 1 бит; данные RML27. */ + Uint16 RML27:1; // 27 RML for Mailbox 27 + /* Битовое поле RML28, ширина 1 бит; данные RML28. */ + Uint16 RML28:1; // 28 RML for Mailbox 28 + /* Битовое поле RML29, ширина 1 бит; данные RML29. */ + Uint16 RML29:1; // 29 RML for Mailbox 29 + /* Битовое поле RML30, ширина 1 бит; данные RML30. */ + Uint16 RML30:1; // 30 RML for Mailbox 30 + /* Битовое поле RML31, ширина 1 бит; данные RML31. */ + Uint16 RML31:1; // 31 RML for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANRML_REG в одной области памяти. */ +union CANRML_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANRML_BITS bit;; порядок полей определяет расположение данных. */ + struct CANRML_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Remote Frame Pending register (CANRFP) bit definitions */ +/* Описывает структуру CANRFP_BITS; порядок полей определяет расположение данных. */ +struct CANRFP_BITS { // bit description + /* Битовое поле RFP0, ширина 1 бит; данные RFP0. */ + Uint16 RFP0:1; // 0 RFP for Mailbox 0 + /* Битовое поле RFP1, ширина 1 бит; данные RFP1. */ + Uint16 RFP1:1; // 1 RFP for Mailbox 1 + /* Битовое поле RFP2, ширина 1 бит; данные RFP2. */ + Uint16 RFP2:1; // 2 RFP for Mailbox 2 + /* Битовое поле RFP3, ширина 1 бит; данные RFP3. */ + Uint16 RFP3:1; // 3 RFP for Mailbox 3 + /* Битовое поле RFP4, ширина 1 бит; данные RFP4. */ + Uint16 RFP4:1; // 4 RFP for Mailbox 4 + /* Битовое поле RFP5, ширина 1 бит; данные RFP5. */ + Uint16 RFP5:1; // 5 RFP for Mailbox 5 + /* Битовое поле RFP6, ширина 1 бит; данные RFP6. */ + Uint16 RFP6:1; // 6 RFP for Mailbox 6 + /* Битовое поле RFP7, ширина 1 бит; данные RFP7. */ + Uint16 RFP7:1; // 7 RFP for Mailbox 7 + /* Битовое поле RFP8, ширина 1 бит; данные RFP8. */ + Uint16 RFP8:1; // 8 RFP for Mailbox 8 + /* Битовое поле RFP9, ширина 1 бит; данные RFP9. */ + Uint16 RFP9:1; // 9 RFP for Mailbox 9 + /* Битовое поле RFP10, ширина 1 бит; данные RFP10. */ + Uint16 RFP10:1; // 10 RFP for Mailbox 10 + /* Битовое поле RFP11, ширина 1 бит; данные RFP11. */ + Uint16 RFP11:1; // 11 RFP for Mailbox 11 + /* Битовое поле RFP12, ширина 1 бит; данные RFP12. */ + Uint16 RFP12:1; // 12 RFP for Mailbox 12 + /* Битовое поле RFP13, ширина 1 бит; данные RFP13. */ + Uint16 RFP13:1; // 13 RFP for Mailbox 13 + /* Битовое поле RFP14, ширина 1 бит; данные RFP14. */ + Uint16 RFP14:1; // 14 RFP for Mailbox 14 + /* Битовое поле RFP15, ширина 1 бит; данные RFP15. */ + Uint16 RFP15:1; // 15 RFP for Mailbox 15 + /* Битовое поле RFP16, ширина 1 бит; данные RFP16. */ + Uint16 RFP16:1; // 16 RFP for Mailbox 16 + /* Битовое поле RFP17, ширина 1 бит; данные RFP17. */ + Uint16 RFP17:1; // 17 RFP for Mailbox 17 + /* Битовое поле RFP18, ширина 1 бит; данные RFP18. */ + Uint16 RFP18:1; // 18 RFP for Mailbox 18 + /* Битовое поле RFP19, ширина 1 бит; данные RFP19. */ + Uint16 RFP19:1; // 19 RFP for Mailbox 19 + /* Битовое поле RFP20, ширина 1 бит; данные RFP20. */ + Uint16 RFP20:1; // 20 RFP for Mailbox 20 + /* Битовое поле RFP21, ширина 1 бит; данные RFP21. */ + Uint16 RFP21:1; // 21 RFP for Mailbox 21 + /* Битовое поле RFP22, ширина 1 бит; данные RFP22. */ + Uint16 RFP22:1; // 22 RFP for Mailbox 22 + /* Битовое поле RFP23, ширина 1 бит; данные RFP23. */ + Uint16 RFP23:1; // 23 RFP for Mailbox 23 + /* Битовое поле RFP24, ширина 1 бит; данные RFP24. */ + Uint16 RFP24:1; // 24 RFP for Mailbox 24 + /* Битовое поле RFP25, ширина 1 бит; данные RFP25. */ + Uint16 RFP25:1; // 25 RFP for Mailbox 25 + /* Битовое поле RFP26, ширина 1 бит; данные RFP26. */ + Uint16 RFP26:1; // 26 RFP for Mailbox 26 + /* Битовое поле RFP27, ширина 1 бит; данные RFP27. */ + Uint16 RFP27:1; // 27 RFP for Mailbox 27 + /* Битовое поле RFP28, ширина 1 бит; данные RFP28. */ + Uint16 RFP28:1; // 28 RFP for Mailbox 28 + /* Битовое поле RFP29, ширина 1 бит; данные RFP29. */ + Uint16 RFP29:1; // 29 RFP for Mailbox 29 + /* Битовое поле RFP30, ширина 1 бит; данные RFP30. */ + Uint16 RFP30:1; // 30 RFP for Mailbox 30 + /* Битовое поле RFP31, ширина 1 бит; данные RFP31. */ + Uint16 RFP31:1; // 31 RFP for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANRFP_REG в одной области памяти. */ +union CANRFP_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANRFP_BITS bit;; порядок полей определяет расположение данных. */ + struct CANRFP_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Global Acceptance Mask register (CANGAM) bit definitions */ +/* Описывает структуру CANGAM_BITS; порядок полей определяет расположение данных. */ +struct CANGAM_BITS { // bits description + /* Битовое поле GAM150, ширина 16 бит; данные GAM150. */ + Uint16 GAM150:16; // 15:0 Global acceptance mask bits 0-15 + /* Битовое поле GAM2816, ширина 13 бит; данные GAM2816. */ + Uint16 GAM2816:13; // 28:16 Global acceptance mask bits 16-28 + /* Битовое поле rsvd, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:2; // 30:29 reserved + /* Битовое поле AMI, ширина 1 бит; данные AMI. */ + Uint16 AMI:1; // 31 AMI bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANGAM_REG в одной области памяти. */ +union CANGAM_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANGAM_BITS bit;; порядок полей определяет расположение данных. */ + struct CANGAM_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* eCAN Master Control register (CANMC) bit definitions */ +/* Описывает структуру CANMC_BITS; порядок полей определяет расположение данных. */ +struct CANMC_BITS { // bits description + /* Битовое поле MBNR, ширина 5 бит; данные MBNR. */ + Uint16 MBNR:5; // 4:0 MBX # for CDR bit + /* Битовое поле SRES, ширина 1 бит; данные SRES. */ + Uint16 SRES:1; // 5 Soft reset + /* Битовое поле STM, ширина 1 бит; данные STM. */ + Uint16 STM:1; // 6 Self-test mode + /* Битовое поле ABO, ширина 1 бит; данные ABO. */ + Uint16 ABO:1; // 7 Auto bus-on + /* Битовое поле CDR, ширина 1 бит; данные CDR. */ + Uint16 CDR:1; // 8 Change data request + /* Битовое поле WUBA, ширина 1 бит; данные WUBA. */ + Uint16 WUBA:1; // 9 Wake-up on bus activity + /* Битовое поле DBO, ширина 1 бит; данные DBO. */ + Uint16 DBO:1; // 10 Data-byte order + /* Битовое поле PDR, ширина 1 бит; данные PDR. */ + Uint16 PDR:1; // 11 Power-down mode request + /* Битовое поле CCR, ширина 1 бит; данные CCR. */ + Uint16 CCR:1; // 12 Change configuration request + /* Битовое поле SCB, ширина 1 бит; данные SCB. */ + Uint16 SCB:1; // 13 SCC compatibility bit + /* Битовое поле TCC, ширина 1 бит; данные TCC. */ + Uint16 TCC:1; // 14 TSC MSB clear bit + /* Битовое поле MBCC, ширина 1 бит; данные MBCC. */ + Uint16 MBCC:1; // 15 TSC clear bit thru mailbox 16 + /* Битовое поле SUSP, ширина 1 бит; данные SUSP. */ + Uint16 SUSP:1; // 16 SUSPEND free/soft bit + /* Битовое поле rsvd, ширина 15 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:15; // 31:17 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANMC_REG в одной области памяти. */ +union CANMC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANMC_BITS bit;; порядок полей определяет расположение данных. */ + struct CANMC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Bit -timing configuration register (CANBTC) bit definitions */ +/* Описывает структуру CANBTC_BITS; порядок полей определяет расположение данных. */ +struct CANBTC_BITS { // bits description + /* Битовое поле TSEG2REG, ширина 3 бит; данные TSEG2REG. */ + Uint16 TSEG2REG:3; // 2:0 TSEG2 register value + /* Битовое поле TSEG1REG, ширина 4 бит; данные TSEG1REG. */ + Uint16 TSEG1REG:4; // 6:3 TSEG1 register value + /* Битовое поле SAM, ширина 1 бит; данные SAM. */ + Uint16 SAM:1; // 7 Sample-point setting + /* Битовое поле SJWREG, ширина 2 бит; данные SJWREG. */ + Uint16 SJWREG:2; // 9:8 Synchroniztion Jump Width register value + /* Битовое поле rsvd1, ширина 6 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:6; // 15:10 reserved + /* Битовое поле BRPREG, ширина 8 бит; данные BRPREG. */ + Uint16 BRPREG:8; // 23:16 Baudrate prescaler register value + /* Битовое поле rsvd2, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:8; // 31:24 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANBTC_REG в одной области памяти. */ +union CANBTC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANBTC_BITS bit;; порядок полей определяет расположение данных. */ + struct CANBTC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Error & Status register (CANES) bit definitions */ +/* Описывает структуру CANES_BITS; порядок полей определяет расположение данных. */ +struct CANES_BITS { // bits description + /* Битовое поле TM, ширина 1 бит; данные TM. */ + Uint16 TM:1; // 0 Transmit Mode + /* Битовое поле RM, ширина 1 бит; данные RM. */ + Uint16 RM:1; // 1 Receive Mode + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 2 reserved + /* Битовое поле PDA, ширина 1 бит; данные PDA. */ + Uint16 PDA:1; // 3 Power-down acknowledge + /* Битовое поле CCE, ширина 1 бит; данные CCE. */ + Uint16 CCE:1; // 4 Change Configuration Enable + /* Битовое поле SMA, ширина 1 бит; данные SMA. */ + Uint16 SMA:1; // 5 Suspend Mode Acknowledge + /* Битовое поле rsvd2, ширина 10 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:10; // 15:6 reserved + /* Битовое поле EW, ширина 1 бит; данные EW. */ + Uint16 EW:1; // 16 Warning status + /* Битовое поле EP, ширина 1 бит; данные EP. */ + Uint16 EP:1; // 17 Error Passive status + /* Битовое поле BO, ширина 1 бит; данные BO. */ + Uint16 BO:1; // 18 Bus-off status + /* Битовое поле ACKE, ширина 1 бит; данные ACKE. */ + Uint16 ACKE:1; // 19 Acknowledge error + /* Битовое поле SE, ширина 1 бит; данные SE. */ + Uint16 SE:1; // 20 Stuff error + /* Битовое поле CRCE, ширина 1 бит; данные CRCE. */ + Uint16 CRCE:1; // 21 CRC error + /* Битовое поле SA1, ширина 1 бит; данные SA1. */ + Uint16 SA1:1; // 22 Stuck at Dominant error + /* Битовое поле BE, ширина 1 бит; данные BE. */ + Uint16 BE:1; // 23 Bit error + /* Битовое поле FE, ширина 1 бит; данные FE. */ + Uint16 FE:1; // 24 Framing error + /* Битовое поле rsvd3, ширина 7 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:7; // 31:25 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANES_REG в одной области памяти. */ +union CANES_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANES_BITS bit;; порядок полей определяет расположение данных. */ + struct CANES_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* eCAN Transmit Error Counter register (CANTEC) bit definitions */ +/* Описывает структуру CANTEC_BITS; порядок полей определяет расположение данных. */ +struct CANTEC_BITS { // bits description + /* Битовое поле TEC, ширина 8 бит; данные TEC. */ + Uint16 TEC:8; // 7:0 TEC + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 15:8 reserved + /* Битовое поле rsvd2, ширина 16 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:16; // 31:16 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANTEC_REG в одной области памяти. */ +union CANTEC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANTEC_BITS bit;; порядок полей определяет расположение данных. */ + struct CANTEC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Receive Error Counter register (CANREC) bit definitions */ +/* Описывает структуру CANREC_BITS; порядок полей определяет расположение данных. */ +struct CANREC_BITS { // bits description + /* Битовое поле REC, ширина 8 бит; данные REC. */ + Uint16 REC:8; // 7:0 REC + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 15:8 reserved + /* Битовое поле rsvd2, ширина 16 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:16; // 31:16 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANREC_REG в одной области памяти. */ +union CANREC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANREC_BITS bit;; порядок полей определяет расположение данных. */ + struct CANREC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Global Interrupt Flag 0 (CANGIF0) bit definitions */ +/* Описывает структуру CANGIF0_BITS; порядок полей определяет расположение данных. */ +struct CANGIF0_BITS { // bits description + /* Битовое поле MIV0, ширина 5 бит; данные MIV0. */ + Uint16 MIV0:5; // 4:0 Mailbox Interrupt Vector + /* Битовое поле rsvd1, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:3; // 7:5 reserved + /* Битовое поле WLIF0, ширина 1 бит; данные WLIF0. */ + Uint16 WLIF0:1; // 8 Warning level interrupt flag + /* Битовое поле EPIF0, ширина 1 бит; данные EPIF0. */ + Uint16 EPIF0:1; // 9 Error-passive interrupt flag + /* Битовое поле BOIF0, ширина 1 бит; данные BOIF0. */ + Uint16 BOIF0:1; // 10 Bus-off interrupt flag + /* Битовое поле RMLIF0, ширина 1 бит; данные RMLIF0. */ + Uint16 RMLIF0:1; // 11 Received message lost interrupt flag + /* Битовое поле WUIF0, ширина 1 бит; данные WUIF0. */ + Uint16 WUIF0:1; // 12 Wakeup interrupt flag + /* Битовое поле WDIF0, ширина 1 бит; данные WDIF0. */ + Uint16 WDIF0:1; // 13 Write denied interrupt flag + /* Битовое поле AAIF0, ширина 1 бит; данные AAIF0. */ + Uint16 AAIF0:1; // 14 Abort Ack interrupt flag + /* Битовое поле GMIF0, ширина 1 бит; данные GMIF0. */ + Uint16 GMIF0:1; // 15 Global MBX interrupt flag + /* Битовое поле TCOF0, ширина 1 бит; данные TCOF0. */ + Uint16 TCOF0:1; // 16 TSC Overflow flag + /* Битовое поле MTOF0, ширина 1 бит; данные MTOF0. */ + Uint16 MTOF0:1; // 17 Mailbox Timeout flag + /* Битовое поле rsvd2, ширина 14 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:14; // 31:18 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANGIF0_REG в одной области памяти. */ +union CANGIF0_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANGIF0_BITS bit;; порядок полей определяет расположение данных. */ + struct CANGIF0_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Global Interrupt Mask register (CANGIM) bit definitions */ +/* Описывает структуру CANGIM_BITS; порядок полей определяет расположение данных. */ +struct CANGIM_BITS { // bits description + /* Битовое поле I0EN, ширина 1 бит; данные I0EN. */ + Uint16 I0EN:1; // 0 Interrupt 0 enable + /* Битовое поле I1EN, ширина 1 бит; данные I1EN. */ + Uint16 I1EN:1; // 1 Interrupt 1 enable + /* Битовое поле GIL, ширина 1 бит; данные GIL. */ + Uint16 GIL:1; // 2 Global Interrupt Level + /* Битовое поле rsvd1, ширина 5 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:5; // 7:3 reserved + /* Битовое поле WLIM, ширина 1 бит; данные WLIM. */ + Uint16 WLIM:1; // 8 Warning level interrupt mask + /* Битовое поле EPIM, ширина 1 бит; данные EPIM. */ + Uint16 EPIM:1; // 9 Error-passive interrupt mask + /* Битовое поле BOIM, ширина 1 бит; данные BOIM. */ + Uint16 BOIM:1; // 10 Bus-off interrupt mask + /* Битовое поле RMLIM, ширина 1 бит; данные RMLIM. */ + Uint16 RMLIM:1; // 11 Received message lost interrupt mask + /* Битовое поле WUIM, ширина 1 бит; данные WUIM. */ + Uint16 WUIM:1; // 12 Wakeup interrupt mask + /* Битовое поле WDIM, ширина 1 бит; данные WDIM. */ + Uint16 WDIM:1; // 13 Write denied interrupt mask + /* Битовое поле AAIM, ширина 1 бит; данные AAIM. */ + Uint16 AAIM:1; // 14 Abort Ack interrupt mask + /* Битовое поле rsvd2, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:1; // 15 reserved + /* Битовое поле TCOM, ширина 1 бит; данные TCOM. */ + Uint16 TCOM:1; // 16 TSC overflow interrupt mask + /* Битовое поле MTOM, ширина 1 бит; данные MTOM. */ + Uint16 MTOM:1; // 17 MBX Timeout interrupt mask + /* Битовое поле rsvd3, ширина 14 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:14; // 31:18 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANGIM_REG в одной области памяти. */ +union CANGIM_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANGIM_BITS bit;; порядок полей определяет расположение данных. */ + struct CANGIM_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* eCAN Global Interrupt Flag 1 (eCANGIF1) bit definitions */ +/* Описывает структуру CANGIF1_BITS; порядок полей определяет расположение данных. */ +struct CANGIF1_BITS { // bits description + /* Битовое поле MIV1, ширина 5 бит; данные MIV1. */ + Uint16 MIV1:5; // 4:0 Mailbox Interrupt Vector + /* Битовое поле rsvd1, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:3; // 7:5 reserved + /* Битовое поле WLIF1, ширина 1 бит; данные WLIF1. */ + Uint16 WLIF1:1; // 8 Warning level interrupt flag + /* Битовое поле EPIF1, ширина 1 бит; данные EPIF1. */ + Uint16 EPIF1:1; // 9 Error-passive interrupt flag + /* Битовое поле BOIF1, ширина 1 бит; данные BOIF1. */ + Uint16 BOIF1:1; // 10 Bus-off interrupt flag + /* Битовое поле RMLIF1, ширина 1 бит; данные RMLIF1. */ + Uint16 RMLIF1:1; // 11 Received message lost interrupt flag + /* Битовое поле WUIF1, ширина 1 бит; данные WUIF1. */ + Uint16 WUIF1:1; // 12 Wakeup interrupt flag + /* Битовое поле WDIF1, ширина 1 бит; данные WDIF1. */ + Uint16 WDIF1:1; // 13 Write denied interrupt flag + /* Битовое поле AAIF1, ширина 1 бит; данные AAIF1. */ + Uint16 AAIF1:1; // 14 Abort Ack interrupt flag + /* Битовое поле GMIF1, ширина 1 бит; данные GMIF1. */ + Uint16 GMIF1:1; // 15 Global MBX interrupt flag + /* Битовое поле TCOF1, ширина 1 бит; данные TCOF1. */ + Uint16 TCOF1:1; // 16 TSC Overflow flag + /* Битовое поле MTOF1, ширина 1 бит; данные MTOF1. */ + Uint16 MTOF1:1; // 17 Mailbox Timeout flag + /* Битовое поле rsvd2, ширина 14 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:14; // 31:18 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANGIF1_REG в одной области памяти. */ +union CANGIF1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANGIF1_BITS bit;; порядок полей определяет расположение данных. */ + struct CANGIF1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* eCAN Mailbox Interrupt Mask register (CANMIM) bit definitions */ +/* Описывает структуру CANMIM_BITS; порядок полей определяет расположение данных. */ +struct CANMIM_BITS { // bit description + /* Битовое поле MIM0, ширина 1 бит; данные MIM0. */ + Uint16 MIM0:1; // 0 MIM for Mailbox 0 + /* Битовое поле MIM1, ширина 1 бит; данные MIM1. */ + Uint16 MIM1:1; // 1 MIM for Mailbox 1 + /* Битовое поле MIM2, ширина 1 бит; данные MIM2. */ + Uint16 MIM2:1; // 2 MIM for Mailbox 2 + /* Битовое поле MIM3, ширина 1 бит; данные MIM3. */ + Uint16 MIM3:1; // 3 MIM for Mailbox 3 + /* Битовое поле MIM4, ширина 1 бит; данные MIM4. */ + Uint16 MIM4:1; // 4 MIM for Mailbox 4 + /* Битовое поле MIM5, ширина 1 бит; данные MIM5. */ + Uint16 MIM5:1; // 5 MIM for Mailbox 5 + /* Битовое поле MIM6, ширина 1 бит; данные MIM6. */ + Uint16 MIM6:1; // 6 MIM for Mailbox 6 + /* Битовое поле MIM7, ширина 1 бит; данные MIM7. */ + Uint16 MIM7:1; // 7 MIM for Mailbox 7 + /* Битовое поле MIM8, ширина 1 бит; данные MIM8. */ + Uint16 MIM8:1; // 8 MIM for Mailbox 8 + /* Битовое поле MIM9, ширина 1 бит; данные MIM9. */ + Uint16 MIM9:1; // 9 MIM for Mailbox 9 + /* Битовое поле MIM10, ширина 1 бит; данные MIM10. */ + Uint16 MIM10:1; // 10 MIM for Mailbox 10 + /* Битовое поле MIM11, ширина 1 бит; данные MIM11. */ + Uint16 MIM11:1; // 11 MIM for Mailbox 11 + /* Битовое поле MIM12, ширина 1 бит; данные MIM12. */ + Uint16 MIM12:1; // 12 MIM for Mailbox 12 + /* Битовое поле MIM13, ширина 1 бит; данные MIM13. */ + Uint16 MIM13:1; // 13 MIM for Mailbox 13 + /* Битовое поле MIM14, ширина 1 бит; данные MIM14. */ + Uint16 MIM14:1; // 14 MIM for Mailbox 14 + /* Битовое поле MIM15, ширина 1 бит; данные MIM15. */ + Uint16 MIM15:1; // 15 MIM for Mailbox 15 + /* Битовое поле MIM16, ширина 1 бит; данные MIM16. */ + Uint16 MIM16:1; // 16 MIM for Mailbox 16 + /* Битовое поле MIM17, ширина 1 бит; данные MIM17. */ + Uint16 MIM17:1; // 17 MIM for Mailbox 17 + /* Битовое поле MIM18, ширина 1 бит; данные MIM18. */ + Uint16 MIM18:1; // 18 MIM for Mailbox 18 + /* Битовое поле MIM19, ширина 1 бит; данные MIM19. */ + Uint16 MIM19:1; // 19 MIM for Mailbox 19 + /* Битовое поле MIM20, ширина 1 бит; данные MIM20. */ + Uint16 MIM20:1; // 20 MIM for Mailbox 20 + /* Битовое поле MIM21, ширина 1 бит; данные MIM21. */ + Uint16 MIM21:1; // 21 MIM for Mailbox 21 + /* Битовое поле MIM22, ширина 1 бит; данные MIM22. */ + Uint16 MIM22:1; // 22 MIM for Mailbox 22 + /* Битовое поле MIM23, ширина 1 бит; данные MIM23. */ + Uint16 MIM23:1; // 23 MIM for Mailbox 23 + /* Битовое поле MIM24, ширина 1 бит; данные MIM24. */ + Uint16 MIM24:1; // 24 MIM for Mailbox 24 + /* Битовое поле MIM25, ширина 1 бит; данные MIM25. */ + Uint16 MIM25:1; // 25 MIM for Mailbox 25 + /* Битовое поле MIM26, ширина 1 бит; данные MIM26. */ + Uint16 MIM26:1; // 26 MIM for Mailbox 26 + /* Битовое поле MIM27, ширина 1 бит; данные MIM27. */ + Uint16 MIM27:1; // 27 MIM for Mailbox 27 + /* Битовое поле MIM28, ширина 1 бит; данные MIM28. */ + Uint16 MIM28:1; // 28 MIM for Mailbox 28 + /* Битовое поле MIM29, ширина 1 бит; данные MIM29. */ + Uint16 MIM29:1; // 29 MIM for Mailbox 29 + /* Битовое поле MIM30, ширина 1 бит; данные MIM30. */ + Uint16 MIM30:1; // 30 MIM for Mailbox 30 + /* Битовое поле MIM31, ширина 1 бит; данные MIM31. */ + Uint16 MIM31:1; // 31 MIM for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANMIM_REG в одной области памяти. */ +union CANMIM_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANMIM_BITS bit;; порядок полей определяет расположение данных. */ + struct CANMIM_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Mailbox Interrupt Level register (CANMIL) bit definitions */ +/* Описывает структуру CANMIL_BITS; порядок полей определяет расположение данных. */ +struct CANMIL_BITS { // bit description + /* Битовое поле MIL0, ширина 1 бит; данные MIL0. */ + Uint16 MIL0:1; // 0 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL1, ширина 1 бит; данные MIL1. */ + Uint16 MIL1:1; // 1 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL2, ширина 1 бит; данные MIL2. */ + Uint16 MIL2:1; // 2 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL3, ширина 1 бит; данные MIL3. */ + Uint16 MIL3:1; // 3 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL4, ширина 1 бит; данные MIL4. */ + Uint16 MIL4:1; // 4 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL5, ширина 1 бит; данные MIL5. */ + Uint16 MIL5:1; // 5 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL6, ширина 1 бит; данные MIL6. */ + Uint16 MIL6:1; // 6 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL7, ширина 1 бит; данные MIL7. */ + Uint16 MIL7:1; // 7 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL8, ширина 1 бит; данные MIL8. */ + Uint16 MIL8:1; // 8 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL9, ширина 1 бит; данные MIL9. */ + Uint16 MIL9:1; // 9 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL10, ширина 1 бит; данные MIL10. */ + Uint16 MIL10:1; // 10 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL11, ширина 1 бит; данные MIL11. */ + Uint16 MIL11:1; // 11 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL12, ширина 1 бит; данные MIL12. */ + Uint16 MIL12:1; // 12 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL13, ширина 1 бит; данные MIL13. */ + Uint16 MIL13:1; // 13 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL14, ширина 1 бит; данные MIL14. */ + Uint16 MIL14:1; // 14 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL15, ширина 1 бит; данные MIL15. */ + Uint16 MIL15:1; // 15 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL16, ширина 1 бит; данные MIL16. */ + Uint16 MIL16:1; // 16 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL17, ширина 1 бит; данные MIL17. */ + Uint16 MIL17:1; // 17 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL18, ширина 1 бит; данные MIL18. */ + Uint16 MIL18:1; // 18 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL19, ширина 1 бит; данные MIL19. */ + Uint16 MIL19:1; // 19 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL20, ширина 1 бит; данные MIL20. */ + Uint16 MIL20:1; // 20 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL21, ширина 1 бит; данные MIL21. */ + Uint16 MIL21:1; // 21 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL22, ширина 1 бит; данные MIL22. */ + Uint16 MIL22:1; // 22 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL23, ширина 1 бит; данные MIL23. */ + Uint16 MIL23:1; // 23 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL24, ширина 1 бит; данные MIL24. */ + Uint16 MIL24:1; // 24 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL25, ширина 1 бит; данные MIL25. */ + Uint16 MIL25:1; // 25 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL26, ширина 1 бит; данные MIL26. */ + Uint16 MIL26:1; // 26 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL27, ширина 1 бит; данные MIL27. */ + Uint16 MIL27:1; // 27 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL28, ширина 1 бит; данные MIL28. */ + Uint16 MIL28:1; // 28 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL29, ширина 1 бит; данные MIL29. */ + Uint16 MIL29:1; // 29 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL30, ширина 1 бит; данные MIL30. */ + Uint16 MIL30:1; // 30 0 -> Int 9.5 1 -> Int 9.6 + /* Битовое поле MIL31, ширина 1 бит; данные MIL31. */ + Uint16 MIL31:1; // 31 0 -> Int 9.5 1 -> Int 9.6 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANMIL_REG в одной области памяти. */ +union CANMIL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANMIL_BITS bit;; порядок полей определяет расположение данных. */ + struct CANMIL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* eCAN Overwrite Protection Control register (CANOPC) bit definitions */ +/* Описывает структуру CANOPC_BITS; порядок полей определяет расположение данных. */ +struct CANOPC_BITS { // bit description + /* Битовое поле OPC0, ширина 1 бит; данные OPC0. */ + Uint16 OPC0:1; // 0 OPC for Mailbox 0 + /* Битовое поле OPC1, ширина 1 бит; данные OPC1. */ + Uint16 OPC1:1; // 1 OPC for Mailbox 1 + /* Битовое поле OPC2, ширина 1 бит; данные OPC2. */ + Uint16 OPC2:1; // 2 OPC for Mailbox 2 + /* Битовое поле OPC3, ширина 1 бит; данные OPC3. */ + Uint16 OPC3:1; // 3 OPC for Mailbox 3 + /* Битовое поле OPC4, ширина 1 бит; данные OPC4. */ + Uint16 OPC4:1; // 4 OPC for Mailbox 4 + /* Битовое поле OPC5, ширина 1 бит; данные OPC5. */ + Uint16 OPC5:1; // 5 OPC for Mailbox 5 + /* Битовое поле OPC6, ширина 1 бит; данные OPC6. */ + Uint16 OPC6:1; // 6 OPC for Mailbox 6 + /* Битовое поле OPC7, ширина 1 бит; данные OPC7. */ + Uint16 OPC7:1; // 7 OPC for Mailbox 7 + /* Битовое поле OPC8, ширина 1 бит; данные OPC8. */ + Uint16 OPC8:1; // 8 OPC for Mailbox 8 + /* Битовое поле OPC9, ширина 1 бит; данные OPC9. */ + Uint16 OPC9:1; // 9 OPC for Mailbox 9 + /* Битовое поле OPC10, ширина 1 бит; данные OPC10. */ + Uint16 OPC10:1; // 10 OPC for Mailbox 10 + /* Битовое поле OPC11, ширина 1 бит; данные OPC11. */ + Uint16 OPC11:1; // 11 OPC for Mailbox 11 + /* Битовое поле OPC12, ширина 1 бит; данные OPC12. */ + Uint16 OPC12:1; // 12 OPC for Mailbox 12 + /* Битовое поле OPC13, ширина 1 бит; данные OPC13. */ + Uint16 OPC13:1; // 13 OPC for Mailbox 13 + /* Битовое поле OPC14, ширина 1 бит; данные OPC14. */ + Uint16 OPC14:1; // 14 OPC for Mailbox 14 + /* Битовое поле OPC15, ширина 1 бит; данные OPC15. */ + Uint16 OPC15:1; // 15 OPC for Mailbox 15 + /* Битовое поле OPC16, ширина 1 бит; данные OPC16. */ + Uint16 OPC16:1; // 16 OPC for Mailbox 16 + /* Битовое поле OPC17, ширина 1 бит; данные OPC17. */ + Uint16 OPC17:1; // 17 OPC for Mailbox 17 + /* Битовое поле OPC18, ширина 1 бит; данные OPC18. */ + Uint16 OPC18:1; // 18 OPC for Mailbox 18 + /* Битовое поле OPC19, ширина 1 бит; данные OPC19. */ + Uint16 OPC19:1; // 19 OPC for Mailbox 19 + /* Битовое поле OPC20, ширина 1 бит; данные OPC20. */ + Uint16 OPC20:1; // 20 OPC for Mailbox 20 + /* Битовое поле OPC21, ширина 1 бит; данные OPC21. */ + Uint16 OPC21:1; // 21 OPC for Mailbox 21 + /* Битовое поле OPC22, ширина 1 бит; данные OPC22. */ + Uint16 OPC22:1; // 22 OPC for Mailbox 22 + /* Битовое поле OPC23, ширина 1 бит; данные OPC23. */ + Uint16 OPC23:1; // 23 OPC for Mailbox 23 + /* Битовое поле OPC24, ширина 1 бит; данные OPC24. */ + Uint16 OPC24:1; // 24 OPC for Mailbox 24 + /* Битовое поле OPC25, ширина 1 бит; данные OPC25. */ + Uint16 OPC25:1; // 25 OPC for Mailbox 25 + /* Битовое поле OPC26, ширина 1 бит; данные OPC26. */ + Uint16 OPC26:1; // 26 OPC for Mailbox 26 + /* Битовое поле OPC27, ширина 1 бит; данные OPC27. */ + Uint16 OPC27:1; // 27 OPC for Mailbox 27 + /* Битовое поле OPC28, ширина 1 бит; данные OPC28. */ + Uint16 OPC28:1; // 28 OPC for Mailbox 28 + /* Битовое поле OPC29, ширина 1 бит; данные OPC29. */ + Uint16 OPC29:1; // 29 OPC for Mailbox 29 + /* Битовое поле OPC30, ширина 1 бит; данные OPC30. */ + Uint16 OPC30:1; // 30 OPC for Mailbox 30 + /* Битовое поле OPC31, ширина 1 бит; данные OPC31. */ + Uint16 OPC31:1; // 31 OPC for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANOPC_REG в одной области памяти. */ +union CANOPC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANOPC_BITS bit;; порядок полей определяет расположение данных. */ + struct CANOPC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* eCAN TX I/O Control Register (CANTIOC) bit definitions */ +/* Описывает структуру CANTIOC_BITS; порядок полей определяет расположение данных. */ +struct CANTIOC_BITS { // bits description + /* Битовое поле rsvd1, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:3; // 2:0 reserved + /* Битовое поле TXFUNC, ширина 1 бит; данные TXFUNC. */ + Uint16 TXFUNC:1; // 3 TXFUNC + /* Битовое поле rsvd2, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:12; // 15:4 reserved + /* Битовое поле rsvd3, ширина 16 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:16; // 31:16 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANTIOC_REG в одной области памяти. */ +union CANTIOC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANTIOC_BITS bit;; порядок полей определяет расположение данных. */ + struct CANTIOC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN RX I/O Control Register (CANRIOC) bit definitions */ +/* Описывает структуру CANRIOC_BITS; порядок полей определяет расположение данных. */ +struct CANRIOC_BITS { // bits description + /* Битовое поле rsvd1, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:3; // 2:0 reserved + /* Битовое поле RXFUNC, ширина 1 бит; данные RXFUNC. */ + Uint16 RXFUNC:1; // 3 RXFUNC + /* Битовое поле rsvd2, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:12; // 15:4 reserved + /* Битовое поле rsvd3, ширина 16 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:16; // 31:16 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANRIOC_REG в одной области памяти. */ +union CANRIOC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANRIOC_BITS bit;; порядок полей определяет расположение данных. */ + struct CANRIOC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* eCAN Time-out Control register (CANTOC) bit definitions */ +/* Описывает структуру CANTOC_BITS; порядок полей определяет расположение данных. */ +struct CANTOC_BITS { // bit description + /* Битовое поле TOC0, ширина 1 бит; данные TOC0. */ + Uint16 TOC0:1; // 0 TOC for Mailbox 0 + /* Битовое поле TOC1, ширина 1 бит; данные TOC1. */ + Uint16 TOC1:1; // 1 TOC for Mailbox 1 + /* Битовое поле TOC2, ширина 1 бит; данные TOC2. */ + Uint16 TOC2:1; // 2 TOC for Mailbox 2 + /* Битовое поле TOC3, ширина 1 бит; данные TOC3. */ + Uint16 TOC3:1; // 3 TOC for Mailbox 3 + /* Битовое поле TOC4, ширина 1 бит; данные TOC4. */ + Uint16 TOC4:1; // 4 TOC for Mailbox 4 + /* Битовое поле TOC5, ширина 1 бит; данные TOC5. */ + Uint16 TOC5:1; // 5 TOC for Mailbox 5 + /* Битовое поле TOC6, ширина 1 бит; данные TOC6. */ + Uint16 TOC6:1; // 6 TOC for Mailbox 6 + /* Битовое поле TOC7, ширина 1 бит; данные TOC7. */ + Uint16 TOC7:1; // 7 TOC for Mailbox 7 + /* Битовое поле TOC8, ширина 1 бит; данные TOC8. */ + Uint16 TOC8:1; // 8 TOC for Mailbox 8 + /* Битовое поле TOC9, ширина 1 бит; данные TOC9. */ + Uint16 TOC9:1; // 9 TOC for Mailbox 9 + /* Битовое поле TOC10, ширина 1 бит; данные TOC10. */ + Uint16 TOC10:1; // 10 TOC for Mailbox 10 + /* Битовое поле TOC11, ширина 1 бит; данные TOC11. */ + Uint16 TOC11:1; // 11 TOC for Mailbox 11 + /* Битовое поле TOC12, ширина 1 бит; данные TOC12. */ + Uint16 TOC12:1; // 12 TOC for Mailbox 12 + /* Битовое поле TOC13, ширина 1 бит; данные TOC13. */ + Uint16 TOC13:1; // 13 TOC for Mailbox 13 + /* Битовое поле TOC14, ширина 1 бит; данные TOC14. */ + Uint16 TOC14:1; // 14 TOC for Mailbox 14 + /* Битовое поле TOC15, ширина 1 бит; данные TOC15. */ + Uint16 TOC15:1; // 15 TOC for Mailbox 15 + /* Битовое поле TOC16, ширина 1 бит; данные TOC16. */ + Uint16 TOC16:1; // 16 TOC for Mailbox 16 + /* Битовое поле TOC17, ширина 1 бит; данные TOC17. */ + Uint16 TOC17:1; // 17 TOC for Mailbox 17 + /* Битовое поле TOC18, ширина 1 бит; данные TOC18. */ + Uint16 TOC18:1; // 18 TOC for Mailbox 18 + /* Битовое поле TOC19, ширина 1 бит; данные TOC19. */ + Uint16 TOC19:1; // 19 TOC for Mailbox 19 + /* Битовое поле TOC20, ширина 1 бит; данные TOC20. */ + Uint16 TOC20:1; // 20 TOC for Mailbox 20 + /* Битовое поле TOC21, ширина 1 бит; данные TOC21. */ + Uint16 TOC21:1; // 21 TOC for Mailbox 21 + /* Битовое поле TOC22, ширина 1 бит; данные TOC22. */ + Uint16 TOC22:1; // 22 TOC for Mailbox 22 + /* Битовое поле TOC23, ширина 1 бит; данные TOC23. */ + Uint16 TOC23:1; // 23 TOC for Mailbox 23 + /* Битовое поле TOC24, ширина 1 бит; данные TOC24. */ + Uint16 TOC24:1; // 24 TOC for Mailbox 24 + /* Битовое поле TOC25, ширина 1 бит; данные TOC25. */ + Uint16 TOC25:1; // 25 TOC for Mailbox 25 + /* Битовое поле TOC26, ширина 1 бит; данные TOC26. */ + Uint16 TOC26:1; // 26 TOC for Mailbox 26 + /* Битовое поле TOC27, ширина 1 бит; данные TOC27. */ + Uint16 TOC27:1; // 27 TOC for Mailbox 27 + /* Битовое поле TOC28, ширина 1 бит; данные TOC28. */ + Uint16 TOC28:1; // 28 TOC for Mailbox 28 + /* Битовое поле TOC29, ширина 1 бит; данные TOC29. */ + Uint16 TOC29:1; // 29 TOC for Mailbox 29 + /* Битовое поле TOC30, ширина 1 бит; данные TOC30. */ + Uint16 TOC30:1; // 30 TOC for Mailbox 30 + /* Битовое поле TOC31, ширина 1 бит; данные TOC31. */ + Uint16 TOC31:1; // 31 TOC for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANTOC_REG в одной области памяти. */ +union CANTOC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANTOC_BITS bit;; порядок полей определяет расположение данных. */ + struct CANTOC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* eCAN Time-out Status register (CANTOS) bit definitions */ +/* Описывает структуру CANTOS_BITS; порядок полей определяет расположение данных. */ +struct CANTOS_BITS { // bit description + /* Битовое поле TOS0, ширина 1 бит; данные TOS0. */ + Uint16 TOS0:1; // 0 TOS for Mailbox 0 + /* Битовое поле TOS1, ширина 1 бит; данные TOS1. */ + Uint16 TOS1:1; // 1 TOS for Mailbox 1 + /* Битовое поле TOS2, ширина 1 бит; данные TOS2. */ + Uint16 TOS2:1; // 2 TOS for Mailbox 2 + /* Битовое поле TOS3, ширина 1 бит; данные TOS3. */ + Uint16 TOS3:1; // 3 TOS for Mailbox 3 + /* Битовое поле TOS4, ширина 1 бит; данные TOS4. */ + Uint16 TOS4:1; // 4 TOS for Mailbox 4 + /* Битовое поле TOS5, ширина 1 бит; данные TOS5. */ + Uint16 TOS5:1; // 5 TOS for Mailbox 5 + /* Битовое поле TOS6, ширина 1 бит; данные TOS6. */ + Uint16 TOS6:1; // 6 TOS for Mailbox 6 + /* Битовое поле TOS7, ширина 1 бит; данные TOS7. */ + Uint16 TOS7:1; // 7 TOS for Mailbox 7 + /* Битовое поле TOS8, ширина 1 бит; данные TOS8. */ + Uint16 TOS8:1; // 8 TOS for Mailbox 8 + /* Битовое поле TOS9, ширина 1 бит; данные TOS9. */ + Uint16 TOS9:1; // 9 TOS for Mailbox 9 + /* Битовое поле TOS10, ширина 1 бит; данные TOS10. */ + Uint16 TOS10:1; // 10 TOS for Mailbox 10 + /* Битовое поле TOS11, ширина 1 бит; данные TOS11. */ + Uint16 TOS11:1; // 11 TOS for Mailbox 11 + /* Битовое поле TOS12, ширина 1 бит; данные TOS12. */ + Uint16 TOS12:1; // 12 TOS for Mailbox 12 + /* Битовое поле TOS13, ширина 1 бит; данные TOS13. */ + Uint16 TOS13:1; // 13 TOS for Mailbox 13 + /* Битовое поле TOS14, ширина 1 бит; данные TOS14. */ + Uint16 TOS14:1; // 14 TOS for Mailbox 14 + /* Битовое поле TOS15, ширина 1 бит; данные TOS15. */ + Uint16 TOS15:1; // 15 TOS for Mailbox 15 + /* Битовое поле TOS16, ширина 1 бит; данные TOS16. */ + Uint16 TOS16:1; // 16 TOS for Mailbox 16 + /* Битовое поле TOS17, ширина 1 бит; данные TOS17. */ + Uint16 TOS17:1; // 17 TOS for Mailbox 17 + /* Битовое поле TOS18, ширина 1 бит; данные TOS18. */ + Uint16 TOS18:1; // 18 TOS for Mailbox 18 + /* Битовое поле TOS19, ширина 1 бит; данные TOS19. */ + Uint16 TOS19:1; // 19 TOS for Mailbox 19 + /* Битовое поле TOS20, ширина 1 бит; данные TOS20. */ + Uint16 TOS20:1; // 20 TOS for Mailbox 20 + /* Битовое поле TOS21, ширина 1 бит; данные TOS21. */ + Uint16 TOS21:1; // 21 TOS for Mailbox 21 + /* Битовое поле TOS22, ширина 1 бит; данные TOS22. */ + Uint16 TOS22:1; // 22 TOS for Mailbox 22 + /* Битовое поле TOS23, ширина 1 бит; данные TOS23. */ + Uint16 TOS23:1; // 23 TOS for Mailbox 23 + /* Битовое поле TOS24, ширина 1 бит; данные TOS24. */ + Uint16 TOS24:1; // 24 TOS for Mailbox 24 + /* Битовое поле TOS25, ширина 1 бит; данные TOS25. */ + Uint16 TOS25:1; // 25 TOS for Mailbox 25 + /* Битовое поле TOS26, ширина 1 бит; данные TOS26. */ + Uint16 TOS26:1; // 26 TOS for Mailbox 26 + /* Битовое поле TOS27, ширина 1 бит; данные TOS27. */ + Uint16 TOS27:1; // 27 TOS for Mailbox 27 + /* Битовое поле TOS28, ширина 1 бит; данные TOS28. */ + Uint16 TOS28:1; // 28 TOS for Mailbox 28 + /* Битовое поле TOS29, ширина 1 бит; данные TOS29. */ + Uint16 TOS29:1; // 29 TOS for Mailbox 29 + /* Битовое поле TOS30, ширина 1 бит; данные TOS30. */ + Uint16 TOS30:1; // 30 TOS for Mailbox 30 + /* Битовое поле TOS31, ширина 1 бит; данные TOS31. */ + Uint16 TOS31:1; // 31 TOS for Mailbox 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANTOS_REG в одной области памяти. */ +union CANTOS_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANTOS_BITS bit;; порядок полей определяет расположение данных. */ + struct CANTOS_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/**************************************/ +/* eCAN Control & Status register file */ +/**************************************/ + +/* Описывает структуру ECAN_REGS; порядок полей определяет расположение данных. */ +struct ECAN_REGS { + /* Объединяет несколько представлений CANME_REG CANME; в одной области памяти. */ + union CANME_REG CANME; // Mailbox Enable + /* Объединяет несколько представлений CANMD_REG CANMD; в одной области памяти. */ + union CANMD_REG CANMD; // Mailbox Direction + /* Объединяет несколько представлений CANTRS_REG CANTRS; в одной области памяти. */ + union CANTRS_REG CANTRS; // Transmit Request Set + /* Объединяет несколько представлений CANTRR_REG CANTRR; в одной области памяти. */ + union CANTRR_REG CANTRR; // Transmit Request Reset + /* Объединяет несколько представлений CANTA_REG CANTA; в одной области памяти. */ + union CANTA_REG CANTA; // Transmit Acknowledge + /* Объединяет несколько представлений CANAA_REG CANAA; в одной области памяти. */ + union CANAA_REG CANAA; // Abort Acknowledge + /* Объединяет несколько представлений CANRMP_REG CANRMP; в одной области памяти. */ + union CANRMP_REG CANRMP; // Received Message Pending + /* Объединяет несколько представлений CANRML_REG CANRML; в одной области памяти. */ + union CANRML_REG CANRML; // Received Message Lost + /* Объединяет несколько представлений CANRFP_REG CANRFP; в одной области памяти. */ + union CANRFP_REG CANRFP; // Remote Frame Pending + /* Объединяет несколько представлений CANGAM_REG CANGAM; в одной области памяти. */ + union CANGAM_REG CANGAM; // Global Acceptance Mask + /* Объединяет несколько представлений CANMC_REG CANMC; в одной области памяти. */ + union CANMC_REG CANMC; // Master Control + /* Объединяет несколько представлений CANBTC_REG CANBTC; в одной области памяти. */ + union CANBTC_REG CANBTC; // Bit Timing + /* Объединяет несколько представлений CANES_REG CANES; в одной области памяти. */ + union CANES_REG CANES; // Error Status + /* Объединяет несколько представлений CANTEC_REG CANTEC; в одной области памяти. */ + union CANTEC_REG CANTEC; // Transmit Error Counter + /* Объединяет несколько представлений CANREC_REG CANREC; в одной области памяти. */ + union CANREC_REG CANREC; // Receive Error Counter + /* Объединяет несколько представлений CANGIF0_REG CANGIF0; в одной области памяти. */ + union CANGIF0_REG CANGIF0; // Global Interrupt Flag 0 + /* Объединяет несколько представлений CANGIM_REG CANGIM; в одной области памяти. */ + union CANGIM_REG CANGIM; // Global Interrupt Mask 0 + /* Объединяет несколько представлений CANGIF1_REG CANGIF1; в одной области памяти. */ + union CANGIF1_REG CANGIF1; // Global Interrupt Flag 1 + /* Объединяет несколько представлений CANMIM_REG CANMIM; в одной области памяти. */ + union CANMIM_REG CANMIM; // Mailbox Interrupt Mask + /* Объединяет несколько представлений CANMIL_REG CANMIL; в одной области памяти. */ + union CANMIL_REG CANMIL; // Mailbox Interrupt Level + /* Объединяет несколько представлений CANOPC_REG CANOPC; в одной области памяти. */ + union CANOPC_REG CANOPC; // Overwrite Protection Control + /* Объединяет несколько представлений CANTIOC_REG CANTIOC; в одной области памяти. */ + union CANTIOC_REG CANTIOC; // TX I/O Control + /* Объединяет несколько представлений CANRIOC_REG CANRIOC; в одной области памяти. */ + union CANRIOC_REG CANRIOC; // RX I/O Control + /* Объявляет CANTSC — данные CANTSC. */ + Uint32 CANTSC; // Time-stamp counter + /* Объединяет несколько представлений CANTOC_REG CANTOC; в одной области памяти. */ + union CANTOC_REG CANTOC; // Time-out Control + /* Объединяет несколько представлений CANTOS_REG CANTOS; в одной области памяти. */ + union CANTOS_REG CANTOS; // Time-out Status + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* --------------------------------------------------- */ +/* eCAN Mailbox Registers */ +/* ----------------------------------------------------*/ + +/* eCAN Message ID (MSGID) bit definitions */ +/* Описывает структуру CANMSGID_BITS; порядок полей определяет расположение данных. */ +struct CANMSGID_BITS { // bits description + /* Битовое поле EXTMSGID_L, ширина 16 бит; данные EXTMSGID_L. */ + Uint16 EXTMSGID_L:16; // 0:15 + /* Битовое поле EXTMSGID_H, ширина 2 бит; данные EXTMSGID_H. */ + Uint16 EXTMSGID_H:2; // 16:17 + /* Битовое поле STDMSGID, ширина 11 бит; данные STDMSGID. */ + Uint16 STDMSGID:11; // 18:28 + /* Битовое поле AAM, ширина 1 бит; данные AAM. */ + Uint16 AAM:1; // 29 + /* Битовое поле AME, ширина 1 бит; данные AME. */ + Uint16 AME:1; // 30 + /* Битовое поле IDE, ширина 1 бит; данные IDE. */ + Uint16 IDE:1; // 31 + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANMSGID_REG в одной области памяти. */ +union CANMSGID_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANMSGID_BITS bit;; порядок полей определяет расположение данных. */ + struct CANMSGID_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Message Control Register (MSGCTRL) bit definitions */ +/* Описывает структуру CANMSGCTRL_BITS; порядок полей определяет расположение данных. */ +struct CANMSGCTRL_BITS { // bits description + /* Битовое поле DLC, ширина 4 бит; данные DLC. */ + Uint16 DLC:4; // 0:3 + /* Битовое поле RTR, ширина 1 бит; данные RTR. */ + Uint16 RTR:1; // 4 + /* Битовое поле rsvd1, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:3; // 7:5 reserved + /* Битовое поле TPL, ширина 5 бит; данные TPL. */ + Uint16 TPL:5; // 12:8 + /* Битовое поле rsvd2, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:3; // 15:13 reserved + /* Битовое поле rsvd3, ширина 16 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:16; // 31:16 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANMSGCTRL_REG в одной области памяти. */ +union CANMSGCTRL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANMSGCTRL_BITS bit;; порядок полей определяет расположение данных. */ + struct CANMSGCTRL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Message Data Register low (MDR_L) word definitions */ +/* Описывает структуру CANMDL_WORDS; порядок полей определяет расположение данных. */ +struct CANMDL_WORDS { // bits description + /* Битовое поле LOW_WORD, ширина 16 бит; LOW слово. */ + Uint16 LOW_WORD:16; // 0:15 + /* Битовое поле HI_WORD, ширина 16 бит; HI слово. */ + Uint16 HI_WORD:16; // 31:16 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Message Data Register low (MDR_L) byte definitions */ +/* Описывает структуру CANMDL_BYTES; порядок полей определяет расположение данных. */ +struct CANMDL_BYTES { // bits description + /* Битовое поле BYTE3, ширина 8 бит; данные BYTE3. */ + Uint16 BYTE3:8; // 31:24 + /* Битовое поле BYTE2, ширина 8 бит; данные BYTE2. */ + Uint16 BYTE2:8; // 23:16 + /* Битовое поле BYTE1, ширина 8 бит; данные BYTE1. */ + Uint16 BYTE1:8; // 15:8 + /* Битовое поле BYTE0, ширина 8 бит; данные BYTE0. */ + Uint16 BYTE0:8; // 7:0 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Allow access to the bit fields or entire register */ + +/* Объединяет несколько представлений CANMDL_REG в одной области памяти. */ +union CANMDL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANMDL_WORDS word;; порядок полей определяет расположение данных. */ + struct CANMDL_WORDS word; + /* Описывает структуру CANMDL_BYTES byte;; порядок полей определяет расположение данных. */ + struct CANMDL_BYTES byte; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + +/* eCAN Message Data Register high (MDR_H) word definitions */ +/* Описывает структуру CANMDH_WORDS; порядок полей определяет расположение данных. */ +struct CANMDH_WORDS { // bits description + /* Битовое поле LOW_WORD, ширина 16 бит; LOW слово. */ + Uint16 LOW_WORD:16; // 0:15 + /* Битовое поле HI_WORD, ширина 16 бит; HI слово. */ + Uint16 HI_WORD:16; // 31:16 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Message Data Register low (MDR_H) byte definitions */ +/* Описывает структуру CANMDH_BYTES; порядок полей определяет расположение данных. */ +struct CANMDH_BYTES { // bits description + /* Битовое поле BYTE7, ширина 8 бит; данные BYTE7. */ + Uint16 BYTE7:8; // 63:56 + /* Битовое поле BYTE6, ширина 8 бит; данные BYTE6. */ + Uint16 BYTE6:8; // 55:48 + /* Битовое поле BYTE5, ширина 8 бит; данные BYTE5. */ + Uint16 BYTE5:8; // 47:40 + /* Битовое поле BYTE4, ширина 8 бит; данные BYTE4. */ + Uint16 BYTE4:8; // 39:32 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANMDH_REG в одной области памяти. */ +union CANMDH_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANMDH_WORDS word;; порядок полей определяет расположение данных. */ + struct CANMDH_WORDS word; + /* Описывает структуру CANMDH_BYTES byte;; порядок полей определяет расположение данных. */ + struct CANMDH_BYTES byte; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру MBOX; порядок полей определяет расположение данных. */ +struct MBOX { + /* Объединяет несколько представлений CANMSGID_REG MSGID; в одной области памяти. */ + union CANMSGID_REG MSGID; + /* Объединяет несколько представлений CANMSGCTRL_REG MSGCTRL; в одной области памяти. */ + union CANMSGCTRL_REG MSGCTRL; + /* Объединяет несколько представлений CANMDL_REG MDL; в одной области памяти. */ + union CANMDL_REG MDL; + /* Объединяет несколько представлений CANMDH_REG MDH; в одной области памяти. */ + union CANMDH_REG MDH; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/**************************************/ +/* eCAN Mailboxes */ +/**************************************/ + +/* Описывает структуру ECAN_MBOXES; порядок полей определяет расположение данных. */ +struct ECAN_MBOXES { + /* Описывает структуру MBOX MBOX0;; порядок полей определяет расположение данных. */ + struct MBOX MBOX0; + /* Описывает структуру MBOX MBOX1;; порядок полей определяет расположение данных. */ + struct MBOX MBOX1; + /* Описывает структуру MBOX MBOX2;; порядок полей определяет расположение данных. */ + struct MBOX MBOX2; + /* Описывает структуру MBOX MBOX3;; порядок полей определяет расположение данных. */ + struct MBOX MBOX3; + /* Описывает структуру MBOX MBOX4;; порядок полей определяет расположение данных. */ + struct MBOX MBOX4; + /* Описывает структуру MBOX MBOX5;; порядок полей определяет расположение данных. */ + struct MBOX MBOX5; + /* Описывает структуру MBOX MBOX6;; порядок полей определяет расположение данных. */ + struct MBOX MBOX6; + /* Описывает структуру MBOX MBOX7;; порядок полей определяет расположение данных. */ + struct MBOX MBOX7; + /* Описывает структуру MBOX MBOX8;; порядок полей определяет расположение данных. */ + struct MBOX MBOX8; + /* Описывает структуру MBOX MBOX9;; порядок полей определяет расположение данных. */ + struct MBOX MBOX9; + /* Описывает структуру MBOX MBOX10;; порядок полей определяет расположение данных. */ + struct MBOX MBOX10; + /* Описывает структуру MBOX MBOX11;; порядок полей определяет расположение данных. */ + struct MBOX MBOX11; + /* Описывает структуру MBOX MBOX12;; порядок полей определяет расположение данных. */ + struct MBOX MBOX12; + /* Описывает структуру MBOX MBOX13;; порядок полей определяет расположение данных. */ + struct MBOX MBOX13; + /* Описывает структуру MBOX MBOX14;; порядок полей определяет расположение данных. */ + struct MBOX MBOX14; + /* Описывает структуру MBOX MBOX15;; порядок полей определяет расположение данных. */ + struct MBOX MBOX15; + /* Описывает структуру MBOX MBOX16;; порядок полей определяет расположение данных. */ + struct MBOX MBOX16; + /* Описывает структуру MBOX MBOX17;; порядок полей определяет расположение данных. */ + struct MBOX MBOX17; + /* Описывает структуру MBOX MBOX18;; порядок полей определяет расположение данных. */ + struct MBOX MBOX18; + /* Описывает структуру MBOX MBOX19;; порядок полей определяет расположение данных. */ + struct MBOX MBOX19; + /* Описывает структуру MBOX MBOX20;; порядок полей определяет расположение данных. */ + struct MBOX MBOX20; + /* Описывает структуру MBOX MBOX21;; порядок полей определяет расположение данных. */ + struct MBOX MBOX21; + /* Описывает структуру MBOX MBOX22;; порядок полей определяет расположение данных. */ + struct MBOX MBOX22; + /* Описывает структуру MBOX MBOX23;; порядок полей определяет расположение данных. */ + struct MBOX MBOX23; + /* Описывает структуру MBOX MBOX24;; порядок полей определяет расположение данных. */ + struct MBOX MBOX24; + /* Описывает структуру MBOX MBOX25;; порядок полей определяет расположение данных. */ + struct MBOX MBOX25; + /* Описывает структуру MBOX MBOX26;; порядок полей определяет расположение данных. */ + struct MBOX MBOX26; + /* Описывает структуру MBOX MBOX27;; порядок полей определяет расположение данных. */ + struct MBOX MBOX27; + /* Описывает структуру MBOX MBOX28;; порядок полей определяет расположение данных. */ + struct MBOX MBOX28; + /* Описывает структуру MBOX MBOX29;; порядок полей определяет расположение данных. */ + struct MBOX MBOX29; + /* Описывает структуру MBOX MBOX30;; порядок полей определяет расположение данных. */ + struct MBOX MBOX30; + /* Описывает структуру MBOX MBOX31;; порядок полей определяет расположение данных. */ + struct MBOX MBOX31; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* eCAN Local Acceptance Mask (LAM) bit definitions */ +/* Описывает структуру CANLAM_BITS; порядок полей определяет расположение данных. */ +struct CANLAM_BITS { // bits description + /* Битовое поле LAM_L, ширина 16 бит; данные LAM_L. */ + Uint16 LAM_L:16; // 0:15 + /* Битовое поле LAM_H, ширина 13 бит; данные LAM_H. */ + Uint16 LAM_H:13; // 16:28 + /* Битовое поле rsvd1, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:2; // 29:30 reserved + /* Битовое поле LAMI, ширина 1 бит; данные LAMI. */ + Uint16 LAMI:1; // 31 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CANLAM_REG в одной области памяти. */ +union CANLAM_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CANLAM_BITS bit;; порядок полей определяет расположение данных. */ + struct CANLAM_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/**************************************/ +/* eCAN Local Acceptance Masks */ +/**************************************/ + +/* eCAN LAM File */ +/* Описывает структуру LAM_REGS; порядок полей определяет расположение данных. */ +struct LAM_REGS { + /* Объединяет несколько представлений CANLAM_REG LAM0; в одной области памяти. */ + union CANLAM_REG LAM0; + /* Объединяет несколько представлений CANLAM_REG LAM1; в одной области памяти. */ + union CANLAM_REG LAM1; + /* Объединяет несколько представлений CANLAM_REG LAM2; в одной области памяти. */ + union CANLAM_REG LAM2; + /* Объединяет несколько представлений CANLAM_REG LAM3; в одной области памяти. */ + union CANLAM_REG LAM3; + /* Объединяет несколько представлений CANLAM_REG LAM4; в одной области памяти. */ + union CANLAM_REG LAM4; + /* Объединяет несколько представлений CANLAM_REG LAM5; в одной области памяти. */ + union CANLAM_REG LAM5; + /* Объединяет несколько представлений CANLAM_REG LAM6; в одной области памяти. */ + union CANLAM_REG LAM6; + /* Объединяет несколько представлений CANLAM_REG LAM7; в одной области памяти. */ + union CANLAM_REG LAM7; + /* Объединяет несколько представлений CANLAM_REG LAM8; в одной области памяти. */ + union CANLAM_REG LAM8; + /* Объединяет несколько представлений CANLAM_REG LAM9; в одной области памяти. */ + union CANLAM_REG LAM9; + /* Объединяет несколько представлений CANLAM_REG LAM10; в одной области памяти. */ + union CANLAM_REG LAM10; + /* Объединяет несколько представлений CANLAM_REG LAM11; в одной области памяти. */ + union CANLAM_REG LAM11; + /* Объединяет несколько представлений CANLAM_REG LAM12; в одной области памяти. */ + union CANLAM_REG LAM12; + /* Объединяет несколько представлений CANLAM_REG LAM13; в одной области памяти. */ + union CANLAM_REG LAM13; + /* Объединяет несколько представлений CANLAM_REG LAM14; в одной области памяти. */ + union CANLAM_REG LAM14; + /* Объединяет несколько представлений CANLAM_REG LAM15; в одной области памяти. */ + union CANLAM_REG LAM15; + /* Объединяет несколько представлений CANLAM_REG LAM16; в одной области памяти. */ + union CANLAM_REG LAM16; + /* Объединяет несколько представлений CANLAM_REG LAM17; в одной области памяти. */ + union CANLAM_REG LAM17; + /* Объединяет несколько представлений CANLAM_REG LAM18; в одной области памяти. */ + union CANLAM_REG LAM18; + /* Объединяет несколько представлений CANLAM_REG LAM19; в одной области памяти. */ + union CANLAM_REG LAM19; + /* Объединяет несколько представлений CANLAM_REG LAM20; в одной области памяти. */ + union CANLAM_REG LAM20; + /* Объединяет несколько представлений CANLAM_REG LAM21; в одной области памяти. */ + union CANLAM_REG LAM21; + /* Объединяет несколько представлений CANLAM_REG LAM22; в одной области памяти. */ + union CANLAM_REG LAM22; + /* Объединяет несколько представлений CANLAM_REG LAM23; в одной области памяти. */ + union CANLAM_REG LAM23; + /* Объединяет несколько представлений CANLAM_REG LAM24; в одной области памяти. */ + union CANLAM_REG LAM24; + /* Объединяет несколько представлений CANLAM_REG LAM25; в одной области памяти. */ + union CANLAM_REG LAM25; + /* Объединяет несколько представлений CANLAM_REG LAM26; в одной области памяти. */ + union CANLAM_REG LAM26; + /* Объединяет несколько представлений CANLAM_REG LAM27; в одной области памяти. */ + union CANLAM_REG LAM27; + /* Объединяет несколько представлений CANLAM_REG LAM28; в одной области памяти. */ + union CANLAM_REG LAM28; + /* Объединяет несколько представлений CANLAM_REG LAM29; в одной области памяти. */ + union CANLAM_REG LAM29; + /* Объединяет несколько представлений CANLAM_REG LAM30; в одной области памяти. */ + union CANLAM_REG LAM30; + /* Объединяет несколько представлений CANLAM_REG LAM31; в одной области памяти. */ + union CANLAM_REG LAM31; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Mailbox MOTS File */ + +/* Описывает структуру MOTS_REGS; порядок полей определяет расположение данных. */ +struct MOTS_REGS { + /* Объявляет MOTS0 — данные MOTS0. */ + Uint32 MOTS0; + /* Объявляет MOTS1 — данные MOTS1. */ + Uint32 MOTS1; + /* Объявляет MOTS2 — данные MOTS2. */ + Uint32 MOTS2; + /* Объявляет MOTS3 — данные MOTS3. */ + Uint32 MOTS3; + /* Объявляет MOTS4 — данные MOTS4. */ + Uint32 MOTS4; + /* Объявляет MOTS5 — данные MOTS5. */ + Uint32 MOTS5; + /* Объявляет MOTS6 — данные MOTS6. */ + Uint32 MOTS6; + /* Объявляет MOTS7 — данные MOTS7. */ + Uint32 MOTS7; + /* Объявляет MOTS8 — данные MOTS8. */ + Uint32 MOTS8; + /* Объявляет MOTS9 — данные MOTS9. */ + Uint32 MOTS9; + /* Объявляет MOTS10 — данные MOTS10. */ + Uint32 MOTS10; + /* Объявляет MOTS11 — данные MOTS11. */ + Uint32 MOTS11; + /* Объявляет MOTS12 — данные MOTS12. */ + Uint32 MOTS12; + /* Объявляет MOTS13 — данные MOTS13. */ + Uint32 MOTS13; + /* Объявляет MOTS14 — данные MOTS14. */ + Uint32 MOTS14; + /* Объявляет MOTS15 — данные MOTS15. */ + Uint32 MOTS15; + /* Объявляет MOTS16 — данные MOTS16. */ + Uint32 MOTS16; + /* Объявляет MOTS17 — данные MOTS17. */ + Uint32 MOTS17; + /* Объявляет MOTS18 — данные MOTS18. */ + Uint32 MOTS18; + /* Объявляет MOTS19 — данные MOTS19. */ + Uint32 MOTS19; + /* Объявляет MOTS20 — данные MOTS20. */ + Uint32 MOTS20; + /* Объявляет MOTS21 — данные MOTS21. */ + Uint32 MOTS21; + /* Объявляет MOTS22 — данные MOTS22. */ + Uint32 MOTS22; + /* Объявляет MOTS23 — данные MOTS23. */ + Uint32 MOTS23; + /* Объявляет MOTS24 — данные MOTS24. */ + Uint32 MOTS24; + /* Объявляет MOTS25 — данные MOTS25. */ + Uint32 MOTS25; + /* Объявляет MOTS26 — данные MOTS26. */ + Uint32 MOTS26; + /* Объявляет MOTS27 — данные MOTS27. */ + Uint32 MOTS27; + /* Объявляет MOTS28 — данные MOTS28. */ + Uint32 MOTS28; + /* Объявляет MOTS29 — данные MOTS29. */ + Uint32 MOTS29; + /* Объявляет MOTS30 — данные MOTS30. */ + Uint32 MOTS30; + /* Объявляет MOTS31 — данные MOTS31. */ + Uint32 MOTS31; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Mailbox MOTO File */ + +/* Описывает структуру MOTO_REGS; порядок полей определяет расположение данных. */ +struct MOTO_REGS { + /* Объявляет MOTO0 — данные MOTO0. */ + Uint32 MOTO0; + /* Объявляет MOTO1 — данные MOTO1. */ + Uint32 MOTO1; + /* Объявляет MOTO2 — данные MOTO2. */ + Uint32 MOTO2; + /* Объявляет MOTO3 — данные MOTO3. */ + Uint32 MOTO3; + /* Объявляет MOTO4 — данные MOTO4. */ + Uint32 MOTO4; + /* Объявляет MOTO5 — данные MOTO5. */ + Uint32 MOTO5; + /* Объявляет MOTO6 — данные MOTO6. */ + Uint32 MOTO6; + /* Объявляет MOTO7 — данные MOTO7. */ + Uint32 MOTO7; + /* Объявляет MOTO8 — данные MOTO8. */ + Uint32 MOTO8; + /* Объявляет MOTO9 — данные MOTO9. */ + Uint32 MOTO9; + /* Объявляет MOTO10 — данные MOTO10. */ + Uint32 MOTO10; + /* Объявляет MOTO11 — данные MOTO11. */ + Uint32 MOTO11; + /* Объявляет MOTO12 — данные MOTO12. */ + Uint32 MOTO12; + /* Объявляет MOTO13 — данные MOTO13. */ + Uint32 MOTO13; + /* Объявляет MOTO14 — данные MOTO14. */ + Uint32 MOTO14; + /* Объявляет MOTO15 — данные MOTO15. */ + Uint32 MOTO15; + /* Объявляет MOTO16 — данные MOTO16. */ + Uint32 MOTO16; + /* Объявляет MOTO17 — данные MOTO17. */ + Uint32 MOTO17; + /* Объявляет MOTO18 — данные MOTO18. */ + Uint32 MOTO18; + /* Объявляет MOTO19 — данные MOTO19. */ + Uint32 MOTO19; + /* Объявляет MOTO20 — данные MOTO20. */ + Uint32 MOTO20; + /* Объявляет MOTO21 — данные MOTO21. */ + Uint32 MOTO21; + /* Объявляет MOTO22 — данные MOTO22. */ + Uint32 MOTO22; + /* Объявляет MOTO23 — данные MOTO23. */ + Uint32 MOTO23; + /* Объявляет MOTO24 — данные MOTO24. */ + Uint32 MOTO24; + /* Объявляет MOTO25 — данные MOTO25. */ + Uint32 MOTO25; + /* Объявляет MOTO26 — данные MOTO26. */ + Uint32 MOTO26; + /* Объявляет MOTO27 — данные MOTO27. */ + Uint32 MOTO27; + /* Объявляет MOTO28 — данные MOTO28. */ + Uint32 MOTO28; + /* Объявляет MOTO29 — данные MOTO29. */ + Uint32 MOTO29; + /* Объявляет MOTO30 — данные MOTO30. */ + Uint32 MOTO30; + /* Объявляет MOTO31 — данные MOTO31. */ + Uint32 MOTO31; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//--------------------------------------------------------------------------- +// eCAN External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct ECAN_REGS ECanaRegs;; порядок элементов сохраняется. */ +extern volatile struct ECAN_REGS ECanaRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct ECAN_MBOXES ECanaMboxes;; порядок элементов сохраняется. */ +extern volatile struct ECAN_MBOXES ECanaMboxes; +/* Продолжает список аргументов, полей или выражение extern volatile struct LAM_REGS ECanaLAMRegs;; порядок элементов сохраняется. */ +extern volatile struct LAM_REGS ECanaLAMRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct MOTO_REGS ECanaMOTORegs;; порядок элементов сохраняется. */ +extern volatile struct MOTO_REGS ECanaMOTORegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct MOTS_REGS ECanaMOTSRegs;; порядок элементов сохраняется. */ +extern volatile struct MOTS_REGS ECanaMOTSRegs; + +/* Продолжает список аргументов, полей или выражение extern volatile struct ECAN_REGS ECanbRegs;; порядок элементов сохраняется. */ +extern volatile struct ECAN_REGS ECanbRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct ECAN_MBOXES ECanbMboxes;; порядок элементов сохраняется. */ +extern volatile struct ECAN_MBOXES ECanbMboxes; +/* Продолжает список аргументов, полей или выражение extern volatile struct LAM_REGS ECanbLAMRegs;; порядок элементов сохраняется. */ +extern volatile struct LAM_REGS ECanbLAMRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct MOTO_REGS ECanbMOTORegs;; порядок элементов сохраняется. */ +extern volatile struct MOTO_REGS ECanbMOTORegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct MOTS_REGS ECanbMOTSRegs;; порядок элементов сохраняется. */ +extern volatile struct MOTS_REGS ECanbMOTSRegs; + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_ECAN.H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_ECap.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_ECap.h new file mode 100644 index 0000000..6ff4cea --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_ECap.h @@ -0,0 +1,245 @@ +/* Поставляемое TI описание ECap для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/1 $ +// Checkin $Date: August 18, 2006 13:52:07 $ +//########################################################################### +// +// FILE: DSP2833x_ECap.h +// +// TITLE: DSP2833x Enhanced Capture Module Register Bit Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_ECAP_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_ECAP_H +/* Определяет защитный символ или переключатель DSP2833x_ECAP_H для последующей компиляции. */ +#define DSP2833x_ECAP_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +//---------------------------------------------------- +// Capture control register 1 bit definitions */ +/* Описывает структуру ECCTL1_BITS; порядок полей определяет расположение данных. */ +struct ECCTL1_BITS { // bits description + /* Битовое поле CAP1POL, ширина 1 бит; данные CAP1POL. */ + Uint16 CAP1POL:1; // 0 Capture Event 1 Polarity select + /* Битовое поле CTRRST1, ширина 1 бит; данные CTRRST1. */ + Uint16 CTRRST1:1; // 1 Counter Reset on Capture Event 1 + /* Битовое поле CAP2POL, ширина 1 бит; данные CAP2POL. */ + Uint16 CAP2POL:1; // 2 Capture Event 2 Polarity select + /* Битовое поле CTRRST2, ширина 1 бит; данные CTRRST2. */ + Uint16 CTRRST2:1; // 3 Counter Reset on Capture Event 2 + /* Битовое поле CAP3POL, ширина 1 бит; данные CAP3POL. */ + Uint16 CAP3POL:1; // 4 Capture Event 3 Polarity select + /* Битовое поле CTRRST3, ширина 1 бит; данные CTRRST3. */ + Uint16 CTRRST3:1; // 5 Counter Reset on Capture Event 3 + /* Битовое поле CAP4POL, ширина 1 бит; данные CAP4POL. */ + Uint16 CAP4POL:1; // 6 Capture Event 4 Polarity select + /* Битовое поле CTRRST4, ширина 1 бит; данные CTRRST4. */ + Uint16 CTRRST4:1; // 7 Counter Reset on Capture Event 4 + /* Битовое поле CAPLDEN, ширина 1 бит; данные CAPLDEN. */ + Uint16 CAPLDEN:1; // 8 Enable Loading CAP1-4 regs on a Cap Event + /* Битовое поле PRESCALE, ширина 5 бит; предделитель. */ + Uint16 PRESCALE:5; // 13:9 Event Filter prescale select + /* Битовое поле FREE_SOFT, ширина 2 бит; данные FREE_SOFT. */ + Uint16 FREE_SOFT:2; // 15:14 Emulation mode +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ECCTL1_REG в одной области памяти. */ +union ECCTL1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ECCTL1_BITS bit;; порядок полей определяет расположение данных. */ + struct ECCTL1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +// In V1.1 the STOPVALUE bit field was changed to +// STOP_WRAP. This correlated to a silicon change from +// F2833x Rev 0 to Rev A. +//---------------------------------------------------- +// Capture control register 2 bit definitions */ +/* Описывает структуру ECCTL2_BITS; порядок полей определяет расположение данных. */ +struct ECCTL2_BITS { // bits description + /* Битовое поле CONT_ONESHT, ширина 1 бит; данные CONT_ONESHT. */ + Uint16 CONT_ONESHT:1; // 0 Continuous or one-shot + /* Битовое поле STOP_WRAP, ширина 2 бит; данные STOP_WRAP. */ + Uint16 STOP_WRAP:2; // 2:1 Stop value for one-shot, Wrap for continuous + /* Битовое поле REARM, ширина 1 бит; данные REARM. */ + Uint16 REARM:1; // 3 One-shot re-arm + /* Битовое поле TSCTRSTOP, ширина 1 бит; данные TSCTRSTOP. */ + Uint16 TSCTRSTOP:1; // 4 TSCNT counter stop + /* Битовое поле SYNCI_EN, ширина 1 бит; данные SYNCI_EN. */ + Uint16 SYNCI_EN:1; // 5 Counter sync-in select + /* Битовое поле SYNCO_SEL, ширина 2 бит; данные SYNCO_SEL. */ + Uint16 SYNCO_SEL:2; // 7:6 Sync-out mode + /* Битовое поле SWSYNC, ширина 1 бит; данные SWSYNC. */ + Uint16 SWSYNC:1; // 8 SW forced counter sync + /* Битовое поле CAP_APWM, ширина 1 бит; данные CAP_APWM. */ + Uint16 CAP_APWM:1; // 9 CAP/APWM operating mode select + /* Битовое поле APWMPOL, ширина 1 бит; данные APWMPOL. */ + Uint16 APWMPOL:1; // 10 APWM output polarity select + /* Битовое поле rsvd1, ширина 5 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:5; // 15:11 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений ECCTL2_REG в одной области памяти. */ +union ECCTL2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ECCTL2_BITS bit;; порядок полей определяет расположение данных. */ + struct ECCTL2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// ECAP interrupt enable register bit definitions */ +/* Описывает структуру ECEINT_BITS; порядок полей определяет расположение данных. */ +struct ECEINT_BITS { // bits description + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 0 reserved + /* Битовое поле CEVT1, ширина 1 бит; данные CEVT1. */ + Uint16 CEVT1:1; // 1 Capture Event 1 Interrupt Enable + /* Битовое поле CEVT2, ширина 1 бит; данные CEVT2. */ + Uint16 CEVT2:1; // 2 Capture Event 2 Interrupt Enable + /* Битовое поле CEVT3, ширина 1 бит; данные CEVT3. */ + Uint16 CEVT3:1; // 3 Capture Event 3 Interrupt Enable + /* Битовое поле CEVT4, ширина 1 бит; данные CEVT4. */ + Uint16 CEVT4:1; // 4 Capture Event 4 Interrupt Enable + /* Битовое поле CTROVF, ширина 1 бит; данные CTROVF. */ + Uint16 CTROVF:1; // 5 Counter Overflow Interrupt Enable + /* Битовое поле CTR_EQ_PRD, ширина 1 бит; данные CTR_EQ_PRD. */ + Uint16 CTR_EQ_PRD:1; // 6 Period Equal Interrupt Enable + /* Битовое поле CTR_EQ_CMP, ширина 1 бит; данные CTR_EQ_CMP. */ + Uint16 CTR_EQ_CMP:1; // 7 Compare Equal Interrupt Enable + /* Битовое поле rsvd2, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений ECEINT_REG в одной области памяти. */ +union ECEINT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ECEINT_BITS bit;; порядок полей определяет расположение данных. */ + struct ECEINT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// ECAP interrupt flag register bit definitions */ +/* Описывает структуру ECFLG_BITS; порядок полей определяет расположение данных. */ +struct ECFLG_BITS { // bits description + /* Битовое поле INT, ширина 1 бит; данные INT. */ + Uint16 INT:1; // 0 Global Flag + /* Битовое поле CEVT1, ширина 1 бит; данные CEVT1. */ + Uint16 CEVT1:1; // 1 Capture Event 1 Interrupt Flag + /* Битовое поле CEVT2, ширина 1 бит; данные CEVT2. */ + Uint16 CEVT2:1; // 2 Capture Event 2 Interrupt Flag + /* Битовое поле CEVT3, ширина 1 бит; данные CEVT3. */ + Uint16 CEVT3:1; // 3 Capture Event 3 Interrupt Flag + /* Битовое поле CEVT4, ширина 1 бит; данные CEVT4. */ + Uint16 CEVT4:1; // 4 Capture Event 4 Interrupt Flag + /* Битовое поле CTROVF, ширина 1 бит; данные CTROVF. */ + Uint16 CTROVF:1; // 5 Counter Overflow Interrupt Flag + /* Битовое поле CTR_EQ_PRD, ширина 1 бит; данные CTR_EQ_PRD. */ + Uint16 CTR_EQ_PRD:1; // 6 Period Equal Interrupt Flag + /* Битовое поле CTR_EQ_CMP, ширина 1 бит; данные CTR_EQ_CMP. */ + Uint16 CTR_EQ_CMP:1; // 7 Compare Equal Interrupt Flag + /* Битовое поле rsvd2, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений ECFLG_REG в одной области памяти. */ +union ECFLG_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ECFLG_BITS bit;; порядок полей определяет расположение данных. */ + struct ECFLG_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- + +/* Описывает структуру ECAP_REGS; порядок полей определяет расположение данных. */ +struct ECAP_REGS { + /* Объявляет TSCTR — данные TSCTR. */ + Uint32 TSCTR; // Time stamp counter + /* Объявляет CTRPHS — данные CTRPHS. */ + Uint32 CTRPHS; // Counter phase + /* Объявляет CAP1 — данные CAP1. */ + Uint32 CAP1; // Capture 1 + /* Объявляет CAP2 — данные CAP2. */ + Uint32 CAP2; // Capture 2 + /* Объявляет CAP3 — данные CAP3. */ + Uint32 CAP3; // Capture 3 + /* Объявляет CAP4 — данные CAP4. */ + Uint32 CAP4; // Capture 4 + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1[8]; // reserved + /* Объединяет несколько представлений ECCTL1_REG ECCTL1; в одной области памяти. */ + union ECCTL1_REG ECCTL1; // Capture Control Reg 1 + /* Объединяет несколько представлений ECCTL2_REG ECCTL2; в одной области памяти. */ + union ECCTL2_REG ECCTL2; // Capture Control Reg 2 + /* Объединяет несколько представлений ECEINT_REG ECEINT; в одной области памяти. */ + union ECEINT_REG ECEINT; // ECAP interrupt enable + /* Объединяет несколько представлений ECFLG_REG ECFLG; в одной области памяти. */ + union ECFLG_REG ECFLG; // ECAP interrupt flags + /* Объединяет несколько представлений ECFLG_REG ECCLR; в одной области памяти. */ + union ECFLG_REG ECCLR; // ECAP interrupt clear + /* Объединяет несколько представлений ECEINT_REG ECFRC; в одной области памяти. */ + union ECEINT_REG ECFRC; // ECAP interrupt force + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2[6]; // reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + + +//--------------------------------------------------------------------------- +// GPI/O External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct ECAP_REGS ECap1Regs;; порядок элементов сохраняется. */ +extern volatile struct ECAP_REGS ECap1Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct ECAP_REGS ECap2Regs;; порядок элементов сохраняется. */ +extern volatile struct ECAP_REGS ECap2Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct ECAP_REGS ECap3Regs;; порядок элементов сохраняется. */ +extern volatile struct ECAP_REGS ECap3Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct ECAP_REGS ECap4Regs;; порядок элементов сохраняется. */ +extern volatile struct ECAP_REGS ECap4Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct ECAP_REGS ECap5Regs;; порядок элементов сохраняется. */ +extern volatile struct ECAP_REGS ECap5Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct ECAP_REGS ECap6Regs;; порядок элементов сохраняется. */ +extern volatile struct ECAP_REGS ECap6Regs; + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_ECAP_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_EPwm.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_EPwm.h new file mode 100644 index 0000000..b6ed86c --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_EPwm.h @@ -0,0 +1,720 @@ +/* Поставляемое TI описание EPwm для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/1 $ +// Checkin $Date: August 18, 2006 13:52:10 $ +//########################################################################### +// +// FILE: DSP2833x_EPwm.h +// +// TITLE: DSP2833x Enhanced PWM Module Register Bit Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_EPWM_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_EPWM_H +/* Определяет защитный символ или переключатель DSP2833x_EPWM_H для последующей компиляции. */ +#define DSP2833x_EPWM_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +//---------------------------------------------------- +// Time base control register bit definitions */ +/* Описывает структуру TBCTL_BITS; порядок полей определяет расположение данных. */ +struct TBCTL_BITS { // bits description + /* Битовое поле CTRMODE, ширина 2 бит; данные CTRMODE. */ + Uint16 CTRMODE:2; // 1:0 Counter Mode + /* Битовое поле PHSEN, ширина 1 бит; данные PHSEN. */ + Uint16 PHSEN:1; // 2 Phase load enable + /* Битовое поле PRDLD, ширина 1 бит; данные PRDLD. */ + Uint16 PRDLD:1; // 3 Active period load + /* Битовое поле SYNCOSEL, ширина 2 бит; данные SYNCOSEL. */ + Uint16 SYNCOSEL:2; // 5:4 Sync output select + /* Битовое поле SWFSYNC, ширина 1 бит; данные SWFSYNC. */ + Uint16 SWFSYNC:1; // 6 Software force sync pulse + /* Битовое поле HSPCLKDIV, ширина 3 бит; данные HSPCLKDIV. */ + Uint16 HSPCLKDIV:3; // 9:7 High speed time pre-scale + /* Битовое поле CLKDIV, ширина 3 бит; данные CLKDIV. */ + Uint16 CLKDIV:3; // 12:10 Timebase clock pre-scale + /* Битовое поле PHSDIR, ширина 1 бит; данные PHSDIR. */ + Uint16 PHSDIR:1; // 13 Phase Direction + /* Битовое поле FREE_SOFT, ширина 2 бит; данные FREE_SOFT. */ + Uint16 FREE_SOFT:2; // 15:14 Emulation mode +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TBCTL_REG в одной области памяти. */ +union TBCTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TBCTL_BITS bit;; порядок полей определяет расположение данных. */ + struct TBCTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Time base status register bit definitions */ +/* Описывает структуру TBSTS_BITS; порядок полей определяет расположение данных. */ +struct TBSTS_BITS { // bits description + /* Битовое поле CTRDIR, ширина 1 бит; данные CTRDIR. */ + Uint16 CTRDIR:1; // 0 Counter direction status + /* Битовое поле SYNCI, ширина 1 бит; данные SYNCI. */ + Uint16 SYNCI:1; // 1 External input sync status + /* Битовое поле CTRMAX, ширина 1 бит; данные CTRMAX. */ + Uint16 CTRMAX:1; // 2 Counter max latched status + /* Битовое поле rsvd1, ширина 13 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:13; // 15:3 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TBSTS_REG в одной области памяти. */ +union TBSTS_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TBSTS_BITS bit;; порядок полей определяет расположение данных. */ + struct TBSTS_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Compare control register bit definitions */ +/* Описывает структуру CMPCTL_BITS; порядок полей определяет расположение данных. */ +struct CMPCTL_BITS { // bits description + /* Битовое поле LOADAMODE, ширина 2 бит; данные LOADAMODE. */ + Uint16 LOADAMODE:2; // 0:1 Active compare A + /* Битовое поле LOADBMODE, ширина 2 бит; данные LOADBMODE. */ + Uint16 LOADBMODE:2; // 3:2 Active compare B + /* Битовое поле SHDWAMODE, ширина 1 бит; данные SHDWAMODE. */ + Uint16 SHDWAMODE:1; // 4 Compare A block operating mode + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 5 reserved + /* Битовое поле SHDWBMODE, ширина 1 бит; данные SHDWBMODE. */ + Uint16 SHDWBMODE:1; // 6 Compare B block operating mode + /* Битовое поле rsvd2, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:1; // 7 reserved + /* Битовое поле SHDWAFULL, ширина 1 бит; данные SHDWAFULL. */ + Uint16 SHDWAFULL:1; // 8 Compare A Shadow registers full Status + /* Битовое поле SHDWBFULL, ширина 1 бит; данные SHDWBFULL. */ + Uint16 SHDWBFULL:1; // 9 Compare B Shadow registers full Status + /* Битовое поле rsvd3, ширина 6 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:6; // 15:10 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений CMPCTL_REG в одной области памяти. */ +union CMPCTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру CMPCTL_BITS bit;; порядок полей определяет расположение данных. */ + struct CMPCTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Action qualifier register bit definitions */ +/* Описывает структуру AQCTL_BITS; порядок полей определяет расположение данных. */ +struct AQCTL_BITS { // bits description + /* Битовое поле ZRO, ширина 2 бит; данные ZRO. */ + Uint16 ZRO:2; // 1:0 Action Counter = Zero + /* Битовое поле PRD, ширина 2 бит; данные PRD. */ + Uint16 PRD:2; // 3:2 Action Counter = Period + /* Битовое поле CAU, ширина 2 бит; данные CAU. */ + Uint16 CAU:2; // 5:4 Action Counter = Compare A up + /* Битовое поле CAD, ширина 2 бит; данные CAD. */ + Uint16 CAD:2; // 7:6 Action Counter = Compare A down + /* Битовое поле CBU, ширина 2 бит; данные CBU. */ + Uint16 CBU:2; // 9:8 Action Counter = Compare B up + /* Битовое поле CBD, ширина 2 бит; данные CBD. */ + Uint16 CBD:2; // 11:10 Action Counter = Compare B down + /* Битовое поле rsvd, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:4; // 15:12 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений AQCTL_REG в одной области памяти. */ +union AQCTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру AQCTL_BITS bit;; порядок полей определяет расположение данных. */ + struct AQCTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Action qualifier SW force register bit definitions */ +/* Описывает структуру AQSFRC_BITS; порядок полей определяет расположение данных. */ +struct AQSFRC_BITS { // bits description + /* Битовое поле ACTSFA, ширина 2 бит; данные ACTSFA. */ + Uint16 ACTSFA:2; // 1:0 Action when One-time SW Force A invoked + /* Битовое поле OTSFA, ширина 1 бит; данные OTSFA. */ + Uint16 OTSFA:1; // 2 One-time SW Force A output + /* Битовое поле ACTSFB, ширина 2 бит; данные ACTSFB. */ + Uint16 ACTSFB:2; // 4:3 Action when One-time SW Force B invoked + /* Битовое поле OTSFB, ширина 1 бит; данные OTSFB. */ + Uint16 OTSFB:1; // 5 One-time SW Force A output + /* Битовое поле RLDCSF, ширина 2 бит; данные RLDCSF. */ + Uint16 RLDCSF:2; // 7:6 Reload from Shadow options + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений AQSFRC_REG в одной области памяти. */ +union AQSFRC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру AQSFRC_BITS bit;; порядок полей определяет расположение данных. */ + struct AQSFRC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Action qualifier continuous SW force register bit definitions */ +/* Описывает структуру AQCSFRC_BITS; порядок полей определяет расположение данных. */ +struct AQCSFRC_BITS { // bits description + /* Битовое поле CSFA, ширина 2 бит; данные CSFA. */ + Uint16 CSFA:2; // 1:0 Continuous Software Force on output A + /* Битовое поле CSFB, ширина 2 бит; данные CSFB. */ + Uint16 CSFB:2; // 3:2 Continuous Software Force on output B + /* Битовое поле rsvd1, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:12; // 15:4 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений AQCSFRC_REG в одной области памяти. */ +union AQCSFRC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру AQCSFRC_BITS bit;; порядок полей определяет расположение данных. */ + struct AQCSFRC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +// As of version 1.1 +// Changed the MODE bit-field to OUT_MODE +// Added the bit-field IN_MODE +// This corresponds to changes in silicon as of F2833x devices +// Rev A silicon. +//---------------------------------------------------- +// Dead-band generator control register bit definitions +/* Описывает структуру DBCTL_BITS; порядок полей определяет расположение данных. */ +struct DBCTL_BITS { // bits description + /* Битовое поле OUT_MODE, ширина 2 бит; OUT режим. */ + Uint16 OUT_MODE:2; // 1:0 Dead Band Output Mode Control + /* Битовое поле POLSEL, ширина 2 бит; данные POLSEL. */ + Uint16 POLSEL:2; // 3:2 Polarity Select Control + /* Битовое поле IN_MODE, ширина 2 бит; IN режим. */ + Uint16 IN_MODE:2; // 5:4 Dead Band Input Select Mode Control + /* Битовое поле rsvd1, ширина 10 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:10; // 15:4 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений DBCTL_REG в одной области памяти. */ +union DBCTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру DBCTL_BITS bit;; порядок полей определяет расположение данных. */ + struct DBCTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// Trip zone select register bit definitions +/* Описывает структуру TZSEL_BITS; порядок полей определяет расположение данных. */ +struct TZSEL_BITS { // bits description + /* Битовое поле CBC1, ширина 1 бит; данные CBC1. */ + Uint16 CBC1:1; // 0 TZ1 CBC select + /* Битовое поле CBC2, ширина 1 бит; данные CBC2. */ + Uint16 CBC2:1; // 1 TZ2 CBC select + /* Битовое поле CBC3, ширина 1 бит; данные CBC3. */ + Uint16 CBC3:1; // 2 TZ3 CBC select + /* Битовое поле CBC4, ширина 1 бит; данные CBC4. */ + Uint16 CBC4:1; // 3 TZ4 CBC select + /* Битовое поле CBC5, ширина 1 бит; данные CBC5. */ + Uint16 CBC5:1; // 4 TZ5 CBC select + /* Битовое поле CBC6, ширина 1 бит; данные CBC6. */ + Uint16 CBC6:1; // 5 TZ6 CBC select + /* Битовое поле rsvd1, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:2; // 7:6 reserved + /* Битовое поле OSHT1, ширина 1 бит; данные OSHT1. */ + Uint16 OSHT1:1; // 8 One-shot TZ1 select + /* Битовое поле OSHT2, ширина 1 бит; данные OSHT2. */ + Uint16 OSHT2:1; // 9 One-shot TZ2 select + /* Битовое поле OSHT3, ширина 1 бит; данные OSHT3. */ + Uint16 OSHT3:1; // 10 One-shot TZ3 select + /* Битовое поле OSHT4, ширина 1 бит; данные OSHT4. */ + Uint16 OSHT4:1; // 11 One-shot TZ4 select + /* Битовое поле OSHT5, ширина 1 бит; данные OSHT5. */ + Uint16 OSHT5:1; // 12 One-shot TZ5 select + /* Битовое поле OSHT6, ширина 1 бит; данные OSHT6. */ + Uint16 OSHT6:1; // 13 One-shot TZ6 select + /* Битовое поле rsvd2, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:2; // 15:14 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TZSEL_REG в одной области памяти. */ +union TZSEL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TZSEL_BITS bit;; порядок полей определяет расположение данных. */ + struct TZSEL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// Trip zone control register bit definitions */ +/* Описывает структуру TZCTL_BITS; порядок полей определяет расположение данных. */ +struct TZCTL_BITS { // bits description + /* Битовое поле TZA, ширина 2 бит; данные TZA. */ + Uint16 TZA:2; // 1:0 TZ1 to TZ6 Trip Action On EPWMxA + /* Битовое поле TZB, ширина 2 бит; данные TZB. */ + Uint16 TZB:2; // 3:2 TZ1 to TZ6 Trip Action On EPWMxB + /* Битовое поле rsvd, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:12; // 15:4 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TZCTL_REG в одной области памяти. */ +union TZCTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TZCTL_BITS bit;; порядок полей определяет расположение данных. */ + struct TZCTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// Trip zone control register bit definitions */ +/* Описывает структуру TZEINT_BITS; порядок полей определяет расположение данных. */ +struct TZEINT_BITS { // bits description + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 0 reserved + /* Битовое поле CBC, ширина 1 бит; данные CBC. */ + Uint16 CBC:1; // 1 Trip Zones Cycle By Cycle Int Enable + /* Битовое поле OST, ширина 1 бит; данные OST. */ + Uint16 OST:1; // 2 Trip Zones One Shot Int Enable + /* Битовое поле rsvd2, ширина 13 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:13; // 15:3 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений TZEINT_REG в одной области памяти. */ +union TZEINT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TZEINT_BITS bit;; порядок полей определяет расположение данных. */ + struct TZEINT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// Trip zone flag register bit definitions */ +/* Описывает структуру TZFLG_BITS; порядок полей определяет расположение данных. */ +struct TZFLG_BITS { // bits description + /* Битовое поле INT, ширина 1 бит; данные INT. */ + Uint16 INT:1; // 0 Global status + /* Битовое поле CBC, ширина 1 бит; данные CBC. */ + Uint16 CBC:1; // 1 Trip Zones Cycle By Cycle Int + /* Битовое поле OST, ширина 1 бит; данные OST. */ + Uint16 OST:1; // 2 Trip Zones One Shot Int + /* Битовое поле rsvd2, ширина 13 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:13; // 15:3 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TZFLG_REG в одной области памяти. */ +union TZFLG_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TZFLG_BITS bit;; порядок полей определяет расположение данных. */ + struct TZFLG_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Trip zone flag clear register bit definitions */ +/* Описывает структуру TZCLR_BITS; порядок полей определяет расположение данных. */ +struct TZCLR_BITS { // bits description + /* Битовое поле INT, ширина 1 бит; данные INT. */ + Uint16 INT:1; // 0 Global status + /* Битовое поле CBC, ширина 1 бит; данные CBC. */ + Uint16 CBC:1; // 1 Trip Zones Cycle By Cycle Int + /* Битовое поле OST, ширина 1 бит; данные OST. */ + Uint16 OST:1; // 2 Trip Zones One Shot Int + /* Битовое поле rsvd2, ширина 13 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:13; // 15:3 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TZCLR_REG в одной области памяти. */ +union TZCLR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TZCLR_BITS bit;; порядок полей определяет расположение данных. */ + struct TZCLR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Trip zone flag force register bit definitions */ +/* Описывает структуру TZFRC_BITS; порядок полей определяет расположение данных. */ +struct TZFRC_BITS { // bits description + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 0 reserved + /* Битовое поле CBC, ширина 1 бит; данные CBC. */ + Uint16 CBC:1; // 1 Trip Zones Cycle By Cycle Int + /* Битовое поле OST, ширина 1 бит; данные OST. */ + Uint16 OST:1; // 2 Trip Zones One Shot Int + /* Битовое поле rsvd2, ширина 13 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:13; // 15:3 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TZFRC_REG в одной области памяти. */ +union TZFRC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру TZFRC_BITS bit;; порядок полей определяет расположение данных. */ + struct TZFRC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Event trigger select register bit definitions */ +/* Описывает структуру ETSEL_BITS; порядок полей определяет расположение данных. */ +struct ETSEL_BITS { // bits description + /* Битовое поле INTSEL, ширина 3 бит; данные INTSEL. */ + Uint16 INTSEL:3; // 2:0 EPWMxINTn Select + /* Битовое поле INTEN, ширина 1 бит; данные INTEN. */ + Uint16 INTEN:1; // 3 EPWMxINTn Enable + /* Битовое поле rsvd1, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:4; // 7:4 reserved + /* Битовое поле SOCASEL, ширина 3 бит; данные SOCASEL. */ + Uint16 SOCASEL:3; // 10:8 Start of conversion A Select + /* Битовое поле SOCAEN, ширина 1 бит; данные SOCAEN. */ + Uint16 SOCAEN:1; // 11 Start of conversion A Enable + /* Битовое поле SOCBSEL, ширина 3 бит; данные SOCBSEL. */ + Uint16 SOCBSEL:3; // 14:12 Start of conversion B Select + /* Битовое поле SOCBEN, ширина 1 бит; данные SOCBEN. */ + Uint16 SOCBEN:1; // 15 Start of conversion B Enable +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ETSEL_REG в одной области памяти. */ +union ETSEL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ETSEL_BITS bit;; порядок полей определяет расположение данных. */ + struct ETSEL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// Event trigger pre-scale register bit definitions */ +/* Описывает структуру ETPS_BITS; порядок полей определяет расположение данных. */ +struct ETPS_BITS { // bits description + /* Битовое поле INTPRD, ширина 2 бит; данные INTPRD. */ + Uint16 INTPRD:2; // 1:0 EPWMxINTn Period Select + /* Битовое поле INTCNT, ширина 2 бит; данные INTCNT. */ + Uint16 INTCNT:2; // 3:2 EPWMxINTn Counter Register + /* Битовое поле rsvd1, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:4; // 7:4 reserved + /* Битовое поле SOCAPRD, ширина 2 бит; данные SOCAPRD. */ + Uint16 SOCAPRD:2; // 9:8 EPWMxSOCA Period Select + /* Битовое поле SOCACNT, ширина 2 бит; данные SOCACNT. */ + Uint16 SOCACNT:2; // 11:10 EPWMxSOCA Counter Register + /* Битовое поле SOCBPRD, ширина 2 бит; данные SOCBPRD. */ + Uint16 SOCBPRD:2; // 13:12 EPWMxSOCB Period Select + /* Битовое поле SOCBCNT, ширина 2 бит; данные SOCBCNT. */ + Uint16 SOCBCNT:2; // 15:14 EPWMxSOCB Counter Register +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ETPS_REG в одной области памяти. */ +union ETPS_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ETPS_BITS bit;; порядок полей определяет расположение данных. */ + struct ETPS_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Event trigger Flag register bit definitions */ +/* Описывает структуру ETFLG_BITS; порядок полей определяет расположение данных. */ +struct ETFLG_BITS { // bits description + /* Битовое поле INT, ширина 1 бит; данные INT. */ + Uint16 INT:1; // 0 EPWMxINTn Flag + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 1 reserved + /* Битовое поле SOCA, ширина 1 бит; данные SOCA. */ + Uint16 SOCA:1; // 2 EPWMxSOCA Flag + /* Битовое поле SOCB, ширина 1 бит; данные SOCB. */ + Uint16 SOCB:1; // 3 EPWMxSOCB Flag + /* Битовое поле rsvd2, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:12; // 15:4 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ETFLG_REG в одной области памяти. */ +union ETFLG_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ETFLG_BITS bit;; порядок полей определяет расположение данных. */ + struct ETFLG_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// Event trigger Clear register bit definitions */ +/* Описывает структуру ETCLR_BITS; порядок полей определяет расположение данных. */ +struct ETCLR_BITS { // bits description + /* Битовое поле INT, ширина 1 бит; данные INT. */ + Uint16 INT:1; // 0 EPWMxINTn Clear + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 1 reserved + /* Битовое поле SOCA, ширина 1 бит; данные SOCA. */ + Uint16 SOCA:1; // 2 EPWMxSOCA Clear + /* Битовое поле SOCB, ширина 1 бит; данные SOCB. */ + Uint16 SOCB:1; // 3 EPWMxSOCB Clear + /* Битовое поле rsvd2, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:12; // 15:4 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ETCLR_REG в одной области памяти. */ +union ETCLR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ETCLR_BITS bit;; порядок полей определяет расположение данных. */ + struct ETCLR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// Event trigger Force register bit definitions */ +/* Описывает структуру ETFRC_BITS; порядок полей определяет расположение данных. */ +struct ETFRC_BITS { // bits description + /* Битовое поле INT, ширина 1 бит; данные INT. */ + Uint16 INT:1; // 0 EPWMxINTn Force + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 1 reserved + /* Битовое поле SOCA, ширина 1 бит; данные SOCA. */ + Uint16 SOCA:1; // 2 EPWMxSOCA Force + /* Битовое поле SOCB, ширина 1 бит; данные SOCB. */ + Uint16 SOCB:1; // 3 EPWMxSOCB Force + /* Битовое поле rsvd2, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:12; // 15:4 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений ETFRC_REG в одной области памяти. */ +union ETFRC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру ETFRC_BITS bit;; порядок полей определяет расположение данных. */ + struct ETFRC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; +//---------------------------------------------------- +// PWM chopper control register bit definitions */ +/* Описывает структуру PCCTL_BITS; порядок полей определяет расположение данных. */ +struct PCCTL_BITS { // bits description + /* Битовое поле CHPEN, ширина 1 бит; данные CHPEN. */ + Uint16 CHPEN:1; // 0 PWM chopping enable + /* Битовое поле OSHTWTH, ширина 4 бит; данные OSHTWTH. */ + Uint16 OSHTWTH:4; // 4:1 One-shot pulse width + /* Битовое поле CHPFREQ, ширина 3 бит; данные CHPFREQ. */ + Uint16 CHPFREQ:3; // 7:5 Chopping clock frequency + /* Битовое поле CHPDUTY, ширина 3 бит; данные CHPDUTY. */ + Uint16 CHPDUTY:3; // 10:8 Chopping clock Duty cycle + /* Битовое поле rsvd1, ширина 5 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:5; // 15:11 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений PCCTL_REG в одной области памяти. */ +union PCCTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PCCTL_BITS bit;; порядок полей определяет расположение данных. */ + struct PCCTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру HRCNFG_BITS; порядок полей определяет расположение данных. */ +struct HRCNFG_BITS { // bits description + /* Битовое поле EDGMODE, ширина 2 бит; данные EDGMODE. */ + Uint16 EDGMODE:2; // 1:0 Edge Mode select Bits + /* Битовое поле CTLMODE, ширина 1 бит; данные CTLMODE. */ + Uint16 CTLMODE:1; // 2 Control mode Select Bit + /* Битовое поле HRLOAD, ширина 1 бит; данные HRLOAD. */ + Uint16 HRLOAD:1; // 3 Shadow mode Select Bit + /* Битовое поле rsvd1, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:12; // 15:4 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений HRCNFG_REG в одной области памяти. */ +union HRCNFG_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру HRCNFG_BITS bit;; порядок полей определяет расположение данных. */ + struct HRCNFG_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру TBPHS_HRPWM_REG; порядок полей определяет расположение данных. */ +struct TBPHS_HRPWM_REG { // bits description + /* Объявляет TBPHSHR — данные TBPHSHR. */ + Uint16 TBPHSHR; // 15:0 Extension register for HRPWM Phase (8 bits) + /* Объявляет TBPHS — данные TBPHS. */ + Uint16 TBPHS; // 31:16 Phase offset register +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений TBPHS_HRPWM_GROUP в одной области памяти. */ +union TBPHS_HRPWM_GROUP { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру TBPHS_HRPWM_REG half;; порядок полей определяет расположение данных. */ + struct TBPHS_HRPWM_REG half; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру CMPA_HRPWM_REG; порядок полей определяет расположение данных. */ +struct CMPA_HRPWM_REG { // bits description + /* Объявляет CMPAHR — данные CMPAHR. */ + Uint16 CMPAHR; // 15:0 Extension register for HRPWM compare (8 bits) + /* Объявляет CMPA — данные CMPA. */ + Uint16 CMPA; // 31:16 Compare A reg +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений CMPA_HRPWM_GROUP в одной области памяти. */ +union CMPA_HRPWM_GROUP { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру CMPA_HRPWM_REG half;; порядок полей определяет расположение данных. */ + struct CMPA_HRPWM_REG half; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру EPWM_REGS; порядок полей определяет расположение данных. */ +struct EPWM_REGS { + /* Объединяет несколько представлений TBCTL_REG TBCTL; в одной области памяти. */ + union TBCTL_REG TBCTL; // + /* Объединяет несколько представлений TBSTS_REG TBSTS; в одной области памяти. */ + union TBSTS_REG TBSTS; // + /* Объединяет несколько представлений TBPHS_HRPWM_GROUP TBPHS; в одной области памяти. */ + union TBPHS_HRPWM_GROUP TBPHS; // Union of TBPHS:TBPHSHR + /* Объявляет TBCTR — данные TBCTR. */ + Uint16 TBCTR; // Counter + /* Объявляет TBPRD — данные TBPRD. */ + Uint16 TBPRD; // Period register set + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1; // + /* Объединяет несколько представлений CMPCTL_REG CMPCTL; в одной области памяти. */ + union CMPCTL_REG CMPCTL; // Compare control + /* Объединяет несколько представлений CMPA_HRPWM_GROUP CMPA; в одной области памяти. */ + union CMPA_HRPWM_GROUP CMPA; // Union of CMPA:CMPAHR + /* Объявляет CMPB — данные CMPB. */ + Uint16 CMPB; // Compare B reg + /* Объединяет несколько представлений AQCTL_REG AQCTLA; в одной области памяти. */ + union AQCTL_REG AQCTLA; // Action qual output A + /* Объединяет несколько представлений AQCTL_REG AQCTLB; в одной области памяти. */ + union AQCTL_REG AQCTLB; // Action qual output B + /* Объединяет несколько представлений AQSFRC_REG AQSFRC; в одной области памяти. */ + union AQSFRC_REG AQSFRC; // Action qual SW force + /* Объединяет несколько представлений AQCSFRC_REG AQCSFRC; в одной области памяти. */ + union AQCSFRC_REG AQCSFRC; // Action qualifier continuous SW force + /* Объединяет несколько представлений DBCTL_REG DBCTL; в одной области памяти. */ + union DBCTL_REG DBCTL; // Dead-band control + /* Объявляет DBRED — данные DBRED. */ + Uint16 DBRED; // Dead-band rising edge delay + /* Объявляет DBFED — данные DBFED. */ + Uint16 DBFED; // Dead-band falling edge delay + /* Объединяет несколько представлений TZSEL_REG TZSEL; в одной области памяти. */ + union TZSEL_REG TZSEL; // Trip zone select + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2; + /* Объединяет несколько представлений TZCTL_REG TZCTL; в одной области памяти. */ + union TZCTL_REG TZCTL; // Trip zone control + /* Объединяет несколько представлений TZEINT_REG TZEINT; в одной области памяти. */ + union TZEINT_REG TZEINT; // Trip zone interrupt enable + /* Объединяет несколько представлений TZFLG_REG TZFLG; в одной области памяти. */ + union TZFLG_REG TZFLG; // Trip zone interrupt flags + /* Объединяет несколько представлений TZCLR_REG TZCLR; в одной области памяти. */ + union TZCLR_REG TZCLR; // Trip zone clear + /* Объединяет несколько представлений TZFRC_REG TZFRC; в одной области памяти. */ + union TZFRC_REG TZFRC; // Trip zone force interrupt + /* Объединяет несколько представлений ETSEL_REG ETSEL; в одной области памяти. */ + union ETSEL_REG ETSEL; // Event trigger selection + /* Объединяет несколько представлений ETPS_REG ETPS; в одной области памяти. */ + union ETPS_REG ETPS; // Event trigger pre-scaler + /* Объединяет несколько представлений ETFLG_REG ETFLG; в одной области памяти. */ + union ETFLG_REG ETFLG; // Event trigger flags + /* Объединяет несколько представлений ETCLR_REG ETCLR; в одной области памяти. */ + union ETCLR_REG ETCLR; // Event trigger clear + /* Объединяет несколько представлений ETFRC_REG ETFRC; в одной области памяти. */ + union ETFRC_REG ETFRC; // Event trigger force + /* Объединяет несколько представлений PCCTL_REG PCCTL; в одной области памяти. */ + union PCCTL_REG PCCTL; // PWM chopper control + /* Объявляет rsvd3 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3; // + /* Объединяет несколько представлений HRCNFG_REG HRCNFG; в одной области памяти. */ + union HRCNFG_REG HRCNFG; // HRPWM Config Reg +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + +//--------------------------------------------------------------------------- +// External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct EPWM_REGS EPwm1Regs;; порядок элементов сохраняется. */ +extern volatile struct EPWM_REGS EPwm1Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct EPWM_REGS EPwm2Regs;; порядок элементов сохраняется. */ +extern volatile struct EPWM_REGS EPwm2Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct EPWM_REGS EPwm3Regs;; порядок элементов сохраняется. */ +extern volatile struct EPWM_REGS EPwm3Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct EPWM_REGS EPwm4Regs;; порядок элементов сохраняется. */ +extern volatile struct EPWM_REGS EPwm4Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct EPWM_REGS EPwm5Regs;; порядок элементов сохраняется. */ +extern volatile struct EPWM_REGS EPwm5Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct EPWM_REGS EPwm6Regs;; порядок элементов сохраняется. */ +extern volatile struct EPWM_REGS EPwm6Regs; + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_EPWM_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_EQep.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_EQep.h new file mode 100644 index 0000000..455839e --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_EQep.h @@ -0,0 +1,407 @@ +/* Поставляемое TI описание EQep для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/1 $ +// Checkin $Date: August 18, 2006 13:52:13 $ +//########################################################################### +// +// FILE: DSP2833x_EQep.h +// +// TITLE: DSP2833x Enhanced Quadrature Encoder Pulse Module +// Register Bit Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_EQEP_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_EQEP_H +/* Определяет защитный символ или переключатель DSP2833x_EQEP_H для последующей компиляции. */ +#define DSP2833x_EQEP_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +//---------------------------------------------------- +// Capture decoder control register bit definitions */ +/* Описывает структуру QDECCTL_BITS; порядок полей определяет расположение данных. */ +struct QDECCTL_BITS { // bits description + /* Битовое поле rsvd1, ширина 5 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:5; // 4:0 reserved + /* Битовое поле QSP, ширина 1 бит; данные QSP. */ + Uint16 QSP:1; // 5 QEPS input polarity + /* Битовое поле QIP, ширина 1 бит; данные QIP. */ + Uint16 QIP:1; // 6 QEPI input polarity + /* Битовое поле QBP, ширина 1 бит; данные QBP. */ + Uint16 QBP:1; // 7 QEPB input polarity + /* Битовое поле QAP, ширина 1 бит; данные QAP. */ + Uint16 QAP:1; // 8 QEPA input polarity + /* Битовое поле IGATE, ширина 1 бит; данные IGATE. */ + Uint16 IGATE:1; // 9 Index pulse gating option + /* Битовое поле SWAP, ширина 1 бит; данные SWAP. */ + Uint16 SWAP:1; // 10 CLK/DIR signal source for Position Counter + /* Битовое поле XCR, ширина 1 бит; данные XCR. */ + Uint16 XCR:1; // 11 External clock rate + /* Битовое поле SPSEL, ширина 1 бит; данные SPSEL. */ + Uint16 SPSEL:1; // 12 Sync output pin select + /* Битовое поле SOEN, ширина 1 бит; данные SOEN. */ + Uint16 SOEN:1; // 13 Enable position compare sync + /* Битовое поле QSRC, ширина 2 бит; данные QSRC. */ + Uint16 QSRC:2; // 15:14 Position counter source +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений QDECCTL_REG в одной области памяти. */ +union QDECCTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру QDECCTL_BITS bit;; порядок полей определяет расположение данных. */ + struct QDECCTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// QEP control register bit definitions */ +/* Описывает структуру QEPCTL_BITS; порядок полей определяет расположение данных. */ +struct QEPCTL_BITS { // bits description + /* Битовое поле WDE, ширина 1 бит; данные WDE. */ + Uint16 WDE:1; // 0 QEP watchdog enable + /* Битовое поле UTE, ширина 1 бит; данные UTE. */ + Uint16 UTE:1; // 1 QEP unit timer enable + /* Битовое поле QCLM, ширина 1 бит; данные QCLM. */ + Uint16 QCLM:1; // 2 QEP capture latch mode + /* Битовое поле QPEN, ширина 1 бит; данные QPEN. */ + Uint16 QPEN:1; // 3 Quadrature position counter enable + /* Битовое поле IEL, ширина 2 бит; данные IEL. */ + Uint16 IEL:2; // 5:4 Index event latch + /* Битовое поле SEL, ширина 1 бит; данные SEL. */ + Uint16 SEL:1; // 6 Strobe event latch + /* Битовое поле SWI, ширина 1 бит; данные SWI. */ + Uint16 SWI:1; // 7 Software init position counter + /* Битовое поле IEI, ширина 2 бит; данные IEI. */ + Uint16 IEI:2; // 9:8 Index event init of position count + /* Битовое поле SEI, ширина 2 бит; данные SEI. */ + Uint16 SEI:2; // 11:10 Strobe event init + /* Битовое поле PCRM, ширина 2 бит; данные PCRM. */ + Uint16 PCRM:2; // 13:12 Position counter reset + /* Битовое поле FREE_SOFT, ширина 2 бит; данные FREE_SOFT. */ + Uint16 FREE_SOFT:2; // 15:14 Emulation mode +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений QEPCTL_REG в одной области памяти. */ +union QEPCTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру QEPCTL_BITS bit;; порядок полей определяет расположение данных. */ + struct QEPCTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// Quadrature capture control register bit definitions */ +/* Описывает структуру QCAPCTL_BITS; порядок полей определяет расположение данных. */ +struct QCAPCTL_BITS { // bits description + /* Битовое поле UPPS, ширина 4 бит; данные UPPS. */ + Uint16 UPPS:4; // 3:0 Unit position pre-scale + /* Битовое поле CCPS, ширина 3 бит; данные CCPS. */ + Uint16 CCPS:3; // 6:4 QEP capture timer pre-scale + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 14:7 reserved + /* Битовое поле CEN, ширина 1 бит; данные CEN. */ + Uint16 CEN:1; // 15 Enable QEP capture +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений QCAPCTL_REG в одной области памяти. */ +union QCAPCTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру QCAPCTL_BITS bit;; порядок полей определяет расположение данных. */ + struct QCAPCTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + +//---------------------------------------------------- +// Position compare control register bit definitions */ +/* Описывает структуру QPOSCTL_BITS; порядок полей определяет расположение данных. */ +struct QPOSCTL_BITS { // bits description + /* Битовое поле PCSPW, ширина 12 бит; данные PCSPW. */ + Uint16 PCSPW:12; // 11:0 Position compare sync pulse width + /* Битовое поле PCE, ширина 1 бит; данные PCE. */ + Uint16 PCE:1; // 12 Position compare enable/disable + /* Битовое поле PCPOL, ширина 1 бит; данные PCPOL. */ + Uint16 PCPOL:1; // 13 Polarity of sync output + /* Битовое поле PCLOAD, ширина 1 бит; данные PCLOAD. */ + Uint16 PCLOAD:1; // 14 Position compare of shadow load + /* Битовое поле PCSHDW, ширина 1 бит; данные PCSHDW. */ + Uint16 PCSHDW:1; // 15 Position compare shadow enable +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений QPOSCTL_REG в одной области памяти. */ +union QPOSCTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру QPOSCTL_BITS bit;; порядок полей определяет расположение данных. */ + struct QPOSCTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// QEP interrupt control register bit definitions */ +/* Описывает структуру QEINT_BITS; порядок полей определяет расположение данных. */ +struct QEINT_BITS { // bits description + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 0 reserved + /* Битовое поле PCE, ширина 1 бит; данные PCE. */ + Uint16 PCE:1; // 1 Position counter error + /* Битовое поле QPE, ширина 1 бит; данные QPE. */ + Uint16 QPE:1; // 2 Quadrature phase error + /* Битовое поле QDC, ширина 1 бит; данные QDC. */ + Uint16 QDC:1; // 3 Quadrature dir change + /* Битовое поле WTO, ширина 1 бит; данные WTO. */ + Uint16 WTO:1; // 4 Watchdog timeout + /* Битовое поле PCU, ширина 1 бит; данные PCU. */ + Uint16 PCU:1; // 5 Position counter underflow + /* Битовое поле PCO, ширина 1 бит; данные PCO. */ + Uint16 PCO:1; // 6 Position counter overflow + /* Битовое поле PCR, ширина 1 бит; данные PCR. */ + Uint16 PCR:1; // 7 Position compare ready + /* Битовое поле PCM, ширина 1 бит; данные PCM. */ + Uint16 PCM:1; // 8 Position compare match + /* Битовое поле SEL, ширина 1 бит; данные SEL. */ + Uint16 SEL:1; // 9 Strobe event latch + /* Битовое поле IEL, ширина 1 бит; данные IEL. */ + Uint16 IEL:1; // 10 Event latch + /* Битовое поле UTO, ширина 1 бит; данные UTO. */ + Uint16 UTO:1; // 11 Unit timeout + /* Битовое поле rsvd2, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:4; // 15:12 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений QEINT_REG в одной области памяти. */ +union QEINT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру QEINT_BITS bit;; порядок полей определяет расположение данных. */ + struct QEINT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// QEP interrupt status register bit definitions */ +/* Описывает структуру QFLG_BITS; порядок полей определяет расположение данных. */ +struct QFLG_BITS { // bits description + /* Битовое поле INT, ширина 1 бит; данные INT. */ + Uint16 INT:1; // 0 Global interrupt + /* Битовое поле PCE, ширина 1 бит; данные PCE. */ + Uint16 PCE:1; // 1 Position counter error + /* Битовое поле PHE, ширина 1 бит; данные PHE. */ + Uint16 PHE:1; // 2 Quadrature phase error + /* Битовое поле QDC, ширина 1 бит; данные QDC. */ + Uint16 QDC:1; // 3 Quadrature dir change + /* Битовое поле WTO, ширина 1 бит; данные WTO. */ + Uint16 WTO:1; // 4 Watchdog timeout + /* Битовое поле PCU, ширина 1 бит; данные PCU. */ + Uint16 PCU:1; // 5 Position counter underflow + /* Битовое поле PCO, ширина 1 бит; данные PCO. */ + Uint16 PCO:1; // 6 Position counter overflow + /* Битовое поле PCR, ширина 1 бит; данные PCR. */ + Uint16 PCR:1; // 7 Position compare ready + /* Битовое поле PCM, ширина 1 бит; данные PCM. */ + Uint16 PCM:1; // 8 Position compare match + /* Битовое поле SEL, ширина 1 бит; данные SEL. */ + Uint16 SEL:1; // 9 Strobe event latch + /* Битовое поле IEL, ширина 1 бит; данные IEL. */ + Uint16 IEL:1; // 10 Event latch + /* Битовое поле UTO, ширина 1 бит; данные UTO. */ + Uint16 UTO:1; // 11 Unit timeout + /* Битовое поле rsvd2, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:4; // 15:12 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений QFLG_REG в одной области памяти. */ +union QFLG_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру QFLG_BITS bit;; порядок полей определяет расположение данных. */ + struct QFLG_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// QEP interrupt force register bit definitions */ +/* Описывает структуру QFRC_BITS; порядок полей определяет расположение данных. */ +struct QFRC_BITS { // bits description + /* Битовое поле reserved, ширина 1 бит; Зарезервировано; сохраняет положение следующих полей в аппаратном регистре. */ + Uint16 reserved:1; // 0 Reserved + /* Битовое поле PCE, ширина 1 бит; данные PCE. */ + Uint16 PCE:1; // 1 Position counter error + /* Битовое поле PHE, ширина 1 бит; данные PHE. */ + Uint16 PHE:1; // 2 Quadrature phase error + /* Битовое поле QDC, ширина 1 бит; данные QDC. */ + Uint16 QDC:1; // 3 Quadrature dir change + /* Битовое поле WTO, ширина 1 бит; данные WTO. */ + Uint16 WTO:1; // 4 Watchdog timeout + /* Битовое поле PCU, ширина 1 бит; данные PCU. */ + Uint16 PCU:1; // 5 Position counter underflow + /* Битовое поле PCO, ширина 1 бит; данные PCO. */ + Uint16 PCO:1; // 6 Position counter overflow + /* Битовое поле PCR, ширина 1 бит; данные PCR. */ + Uint16 PCR:1; // 7 Position compare ready + /* Битовое поле PCM, ширина 1 бит; данные PCM. */ + Uint16 PCM:1; // 8 Position compare match + /* Битовое поле SEL, ширина 1 бит; данные SEL. */ + Uint16 SEL:1; // 9 Strobe event latch + /* Битовое поле IEL, ширина 1 бит; данные IEL. */ + Uint16 IEL:1; // 10 Event latch + /* Битовое поле UTO, ширина 1 бит; данные UTO. */ + Uint16 UTO:1; // 11 Unit timeout + /* Битовое поле rsvd2, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:4; // 15:12 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений QFRC_REG в одной области памяти. */ +union QFRC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру QFRC_BITS bit;; порядок полей определяет расположение данных. */ + struct QFRC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// V1.1 Added UPEVNT (bit 7) This reflects changes +// made as of F2833x Rev A devices +//---------------------------------------------------- +// QEP status register bit definitions */ +/* Описывает структуру QEPSTS_BITS; порядок полей определяет расположение данных. */ +struct QEPSTS_BITS { // bits description + /* Битовое поле PCEF, ширина 1 бит; данные PCEF. */ + Uint16 PCEF:1; // 0 Position counter error + /* Битовое поле FIMF, ширина 1 бит; данные FIMF. */ + Uint16 FIMF:1; // 1 First index marker + /* Битовое поле CDEF, ширина 1 бит; данные CDEF. */ + Uint16 CDEF:1; // 2 Capture direction error + /* Битовое поле COEF, ширина 1 бит; данные COEF. */ + Uint16 COEF:1; // 3 Capture overflow error + /* Битовое поле QDLF, ширина 1 бит; данные QDLF. */ + Uint16 QDLF:1; // 4 QEP direction latch + /* Битовое поле QDF, ширина 1 бит; данные QDF. */ + Uint16 QDF:1; // 5 Quadrature direction + /* Битовое поле FIDF, ширина 1 бит; данные FIDF. */ + Uint16 FIDF:1; // 6 Direction on first index marker + /* Битовое поле UPEVNT, ширина 1 бит; данные UPEVNT. */ + Uint16 UPEVNT:1; // 7 Unit position event flag + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений QEPSTS_REG в одной области памяти. */ +union QEPSTS_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру QEPSTS_BITS bit;; порядок полей определяет расположение данных. */ + struct QEPSTS_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- + +/* Описывает структуру EQEP_REGS; порядок полей определяет расположение данных. */ +struct EQEP_REGS { + /* Объявляет QPOSCNT — данные QPOSCNT. */ + Uint32 QPOSCNT; // Position counter + /* Объявляет QPOSINIT — данные QPOSINIT. */ + Uint32 QPOSINIT; // Position counter init + /* Объявляет QPOSMAX — данные QPOSMAX. */ + Uint32 QPOSMAX; // Maximum position count + /* Объявляет QPOSCMP — данные QPOSCMP. */ + Uint32 QPOSCMP; // Position compare + /* Объявляет QPOSILAT — данные QPOSILAT. */ + Uint32 QPOSILAT; // Index position latch + /* Объявляет QPOSSLAT — данные QPOSSLAT. */ + Uint32 QPOSSLAT; // Strobe position latch + /* Объявляет QPOSLAT — данные QPOSLAT. */ + Uint32 QPOSLAT; // Position latch + /* Объявляет QUTMR — данные QUTMR. */ + Uint32 QUTMR; // Unit timer + /* Объявляет QUPRD — данные QUPRD. */ + Uint32 QUPRD; // Unit period + /* Объявляет QWDTMR — данные QWDTMR. */ + Uint16 QWDTMR; // QEP watchdog timer + /* Объявляет QWDPRD — данные QWDPRD. */ + Uint16 QWDPRD; // QEP watchdog period + /* Объединяет несколько представлений QDECCTL_REG QDECCTL; в одной области памяти. */ + union QDECCTL_REG QDECCTL; // Quadrature decoder control + /* Объединяет несколько представлений QEPCTL_REG QEPCTL; в одной области памяти. */ + union QEPCTL_REG QEPCTL; // QEP control + /* Объединяет несколько представлений QCAPCTL_REG QCAPCTL; в одной области памяти. */ + union QCAPCTL_REG QCAPCTL; // Quadrature capture control + /* Объединяет несколько представлений QPOSCTL_REG QPOSCTL; в одной области памяти. */ + union QPOSCTL_REG QPOSCTL; // Position compare control + /* Объединяет несколько представлений QEINT_REG QEINT; в одной области памяти. */ + union QEINT_REG QEINT; // QEP interrupt control + /* Объединяет несколько представлений QFLG_REG QFLG; в одной области памяти. */ + union QFLG_REG QFLG; // QEP interrupt flag + /* Объединяет несколько представлений QFLG_REG QCLR; в одной области памяти. */ + union QFLG_REG QCLR; // QEP interrupt clear + /* Объединяет несколько представлений QFRC_REG QFRC; в одной области памяти. */ + union QFRC_REG QFRC; // QEP interrupt force + /* Объединяет несколько представлений QEPSTS_REG QEPSTS; в одной области памяти. */ + union QEPSTS_REG QEPSTS; // QEP status + /* Объявляет QCTMR — данные QCTMR. */ + Uint16 QCTMR; // QEP capture timer + /* Объявляет QCPRD — данные QCPRD. */ + Uint16 QCPRD; // QEP capture period + /* Объявляет QCTMRLAT — данные QCTMRLAT. */ + Uint16 QCTMRLAT; // QEP capture latch + /* Объявляет QCPRDLAT — данные QCPRDLAT. */ + Uint16 QCPRDLAT; // QEP capture period latch + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1[30]; // reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + + +//--------------------------------------------------------------------------- +// GPI/O External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct EQEP_REGS EQep1Regs;; порядок элементов сохраняется. */ +extern volatile struct EQEP_REGS EQep1Regs; +/* Продолжает список аргументов, полей или выражение extern volatile struct EQEP_REGS EQep2Regs;; порядок элементов сохраняется. */ +extern volatile struct EQEP_REGS EQep2Regs; + + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_EQEP_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Gpio.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Gpio.h new file mode 100644 index 0000000..772b340 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Gpio.h @@ -0,0 +1,711 @@ +/* Поставляемое TI описание Gpio для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/4 $ +// Checkin $Date: November 15, 2007 09:58:53 $ +//########################################################################### +// +// FILE: DSP2833x_Gpio.h +// +// TITLE: DSP2833x General Purpose I/O Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_GPIO_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_GPIO_H +/* Определяет защитный символ или переключатель DSP2833x_GPIO_H для последующей компиляции. */ +#define DSP2833x_GPIO_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +//---------------------------------------------------- +// GPIO A control register bit definitions */ +/* Описывает структуру GPACTRL_BITS; порядок полей определяет расположение данных. */ +struct GPACTRL_BITS { // bits description + /* Битовое поле QUALPRD0, ширина 8 бит; данные QUALPRD0. */ + Uint16 QUALPRD0:8; // 7:0 Qual period + /* Битовое поле QUALPRD1, ширина 8 бит; данные QUALPRD1. */ + Uint16 QUALPRD1:8; // 15:8 Qual period + /* Битовое поле QUALPRD2, ширина 8 бит; данные QUALPRD2. */ + Uint16 QUALPRD2:8; // 23:16 Qual period + /* Битовое поле QUALPRD3, ширина 8 бит; данные QUALPRD3. */ + Uint16 QUALPRD3:8; // 31:24 Qual period +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений GPACTRL_REG в одной области памяти. */ +union GPACTRL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPACTRL_BITS bit;; порядок полей определяет расположение данных. */ + struct GPACTRL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// GPIO B control register bit definitions */ +/* Описывает структуру GPBCTRL_BITS; порядок полей определяет расположение данных. */ +struct GPBCTRL_BITS { // bits description + /* Битовое поле QUALPRD0, ширина 8 бит; данные QUALPRD0. */ + Uint16 QUALPRD0:8; // 7:0 Qual period + /* Битовое поле QUALPRD1, ширина 8 бит; данные QUALPRD1. */ + Uint16 QUALPRD1:8; // 15:8 Qual period + /* Битовое поле QUALPRD2, ширина 8 бит; данные QUALPRD2. */ + Uint16 QUALPRD2:8; // 23:16 Qual period + /* Битовое поле QUALPRD3, ширина 8 бит; данные QUALPRD3. */ + Uint16 QUALPRD3:8; // 31:24 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений GPBCTRL_REG в одной области памяти. */ +union GPBCTRL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPBCTRL_BITS bit;; порядок полей определяет расположение данных. */ + struct GPBCTRL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// GPIO A Qual/MUX select register bit definitions */ +/* Описывает структуру GPA1_BITS; порядок полей определяет расположение данных. */ +struct GPA1_BITS { // bits description + /* Битовое поле GPIO0, ширина 2 бит; аппаратная линия ввода/вывода GPIO0. */ + Uint16 GPIO0:2; // 1:0 GPIO0 + /* Битовое поле GPIO1, ширина 2 бит; аппаратная линия ввода/вывода GPIO1. */ + Uint16 GPIO1:2; // 3:2 GPIO1 + /* Битовое поле GPIO2, ширина 2 бит; аппаратная линия ввода/вывода GPIO2. */ + Uint16 GPIO2:2; // 5:4 GPIO2 + /* Битовое поле GPIO3, ширина 2 бит; аппаратная линия ввода/вывода GPIO3. */ + Uint16 GPIO3:2; // 7:6 GPIO3 + /* Битовое поле GPIO4, ширина 2 бит; аппаратная линия ввода/вывода GPIO4. */ + Uint16 GPIO4:2; // 9:8 GPIO4 + /* Битовое поле GPIO5, ширина 2 бит; аппаратная линия ввода/вывода GPIO5. */ + Uint16 GPIO5:2; // 11:10 GPIO5 + /* Битовое поле GPIO6, ширина 2 бит; аппаратная линия ввода/вывода GPIO6. */ + Uint16 GPIO6:2; // 13:12 GPIO6 + /* Битовое поле GPIO7, ширина 2 бит; аппаратная линия ввода/вывода GPIO7. */ + Uint16 GPIO7:2; // 15:14 GPIO7 + /* Битовое поле GPIO8, ширина 2 бит; аппаратная линия ввода/вывода GPIO8. */ + Uint16 GPIO8:2; // 17:16 GPIO8 + /* Битовое поле GPIO9, ширина 2 бит; аппаратная линия ввода/вывода GPIO9. */ + Uint16 GPIO9:2; // 19:18 GPIO9 + /* Битовое поле GPIO10, ширина 2 бит; аппаратная линия ввода/вывода GPIO10. */ + Uint16 GPIO10:2; // 21:20 GPIO10 + /* Битовое поле GPIO11, ширина 2 бит; аппаратная линия ввода/вывода GPIO11. */ + Uint16 GPIO11:2; // 23:22 GPIO11 + /* Битовое поле GPIO12, ширина 2 бит; аппаратная линия ввода/вывода GPIO12. */ + Uint16 GPIO12:2; // 25:24 GPIO12 + /* Битовое поле GPIO13, ширина 2 бит; аппаратная линия ввода/вывода GPIO13. */ + Uint16 GPIO13:2; // 27:26 GPIO13 + /* Битовое поле GPIO14, ширина 2 бит; аппаратная линия ввода/вывода GPIO14. */ + Uint16 GPIO14:2; // 29:28 GPIO14 + /* Битовое поле GPIO15, ширина 2 бит; аппаратная линия ввода/вывода GPIO15. */ + Uint16 GPIO15:2; // 31:30 GPIO15 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру GPA2_BITS; порядок полей определяет расположение данных. */ +struct GPA2_BITS { // bits description + /* Битовое поле GPIO16, ширина 2 бит; аппаратная линия ввода/вывода GPIO16. */ + Uint16 GPIO16:2; // 1:0 GPIO16 + /* Битовое поле GPIO17, ширина 2 бит; аппаратная линия ввода/вывода GPIO17. */ + Uint16 GPIO17:2; // 3:2 GPIO17 + /* Битовое поле GPIO18, ширина 2 бит; аппаратная линия ввода/вывода GPIO18. */ + Uint16 GPIO18:2; // 5:4 GPIO18 + /* Битовое поле GPIO19, ширина 2 бит; аппаратная линия ввода/вывода GPIO19. */ + Uint16 GPIO19:2; // 7:6 GPIO19 + /* Битовое поле GPIO20, ширина 2 бит; аппаратная линия ввода/вывода GPIO20. */ + Uint16 GPIO20:2; // 9:8 GPIO20 + /* Битовое поле GPIO21, ширина 2 бит; аппаратная линия ввода/вывода GPIO21. */ + Uint16 GPIO21:2; // 11:10 GPIO21 + /* Битовое поле GPIO22, ширина 2 бит; аппаратная линия ввода/вывода GPIO22. */ + Uint16 GPIO22:2; // 13:12 GPIO22 + /* Битовое поле GPIO23, ширина 2 бит; аппаратная линия ввода/вывода GPIO23. */ + Uint16 GPIO23:2; // 15:14 GPIO23 + /* Битовое поле GPIO24, ширина 2 бит; аппаратная линия ввода/вывода GPIO24. */ + Uint16 GPIO24:2; // 17:16 GPIO24 + /* Битовое поле GPIO25, ширина 2 бит; аппаратная линия ввода/вывода GPIO25. */ + Uint16 GPIO25:2; // 19:18 GPIO25 + /* Битовое поле GPIO26, ширина 2 бит; аппаратная линия ввода/вывода GPIO26. */ + Uint16 GPIO26:2; // 21:20 GPIO26 + /* Битовое поле GPIO27, ширина 2 бит; аппаратная линия ввода/вывода GPIO27. */ + Uint16 GPIO27:2; // 23:22 GPIO27 + /* Битовое поле GPIO28, ширина 2 бит; аппаратная линия ввода/вывода GPIO28. */ + Uint16 GPIO28:2; // 25:24 GPIO28 + /* Битовое поле GPIO29, ширина 2 бит; аппаратная линия ввода/вывода GPIO29. */ + Uint16 GPIO29:2; // 27:26 GPIO29 + /* Битовое поле GPIO30, ширина 2 бит; аппаратная линия ввода/вывода GPIO30. */ + Uint16 GPIO30:2; // 29:28 GPIO30 + /* Битовое поле GPIO31, ширина 2 бит; аппаратная линия ввода/вывода GPIO31. */ + Uint16 GPIO31:2; // 31:30 GPIO31 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру GPB1_BITS; порядок полей определяет расположение данных. */ +struct GPB1_BITS { // bits description + /* Битовое поле GPIO32, ширина 2 бит; аппаратная линия ввода/вывода GPIO32. */ + Uint16 GPIO32:2; // 1:0 GPIO32 + /* Битовое поле GPIO33, ширина 2 бит; аппаратная линия ввода/вывода GPIO33. */ + Uint16 GPIO33:2; // 3:2 GPIO33 + /* Битовое поле GPIO34, ширина 2 бит; аппаратная линия ввода/вывода GPIO34. */ + Uint16 GPIO34:2; // 5:4 GPIO34 + /* Битовое поле GPIO35, ширина 2 бит; аппаратная линия ввода/вывода GPIO35. */ + Uint16 GPIO35:2; // 7:6 GPIO35 + /* Битовое поле GPIO36, ширина 2 бит; аппаратная линия ввода/вывода GPIO36. */ + Uint16 GPIO36:2; // 9:8 GPIO36 + /* Битовое поле GPIO37, ширина 2 бит; аппаратная линия ввода/вывода GPIO37. */ + Uint16 GPIO37:2; // 11:10 GPIO37 + /* Битовое поле GPIO38, ширина 2 бит; аппаратная линия ввода/вывода GPIO38. */ + Uint16 GPIO38:2; // 13:12 GPIO38 + /* Битовое поле GPIO39, ширина 2 бит; аппаратная линия ввода/вывода GPIO39. */ + Uint16 GPIO39:2; // 15:14 GPIO39 + /* Битовое поле GPIO40, ширина 2 бит; аппаратная линия ввода/вывода GPIO40. */ + Uint16 GPIO40:2; // 17:16 GPIO40 + /* Битовое поле GPIO41, ширина 2 бит; аппаратная линия ввода/вывода GPIO41. */ + Uint16 GPIO41:2; // 19:16 GPIO41 + /* Битовое поле GPIO42, ширина 2 бит; аппаратная линия ввода/вывода GPIO42. */ + Uint16 GPIO42:2; // 21:20 GPIO42 + /* Битовое поле GPIO43, ширина 2 бит; аппаратная линия ввода/вывода GPIO43. */ + Uint16 GPIO43:2; // 23:22 GPIO43 + /* Битовое поле GPIO44, ширина 2 бит; аппаратная линия ввода/вывода GPIO44. */ + Uint16 GPIO44:2; // 25:24 GPIO44 + /* Битовое поле GPIO45, ширина 2 бит; аппаратная линия ввода/вывода GPIO45. */ + Uint16 GPIO45:2; // 27:26 GPIO45 + /* Битовое поле GPIO46, ширина 2 бит; аппаратная линия ввода/вывода GPIO46. */ + Uint16 GPIO46:2; // 29:28 GPIO46 + /* Битовое поле GPIO47, ширина 2 бит; аппаратная линия ввода/вывода GPIO47. */ + Uint16 GPIO47:2; // 31:30 GPIO47 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру GPB2_BITS; порядок полей определяет расположение данных. */ +struct GPB2_BITS { // bits description + /* Битовое поле GPIO48, ширина 2 бит; аппаратная линия ввода/вывода GPIO48. */ + Uint16 GPIO48:2; // 1:0 GPIO48 + /* Битовое поле GPIO49, ширина 2 бит; аппаратная линия ввода/вывода GPIO49. */ + Uint16 GPIO49:2; // 3:2 GPIO49 + /* Битовое поле GPIO50, ширина 2 бит; аппаратная линия ввода/вывода GPIO50. */ + Uint16 GPIO50:2; // 5:4 GPIO50 + /* Битовое поле GPIO51, ширина 2 бит; аппаратная линия ввода/вывода GPIO51. */ + Uint16 GPIO51:2; // 7:6 GPIO51 + /* Битовое поле GPIO52, ширина 2 бит; аппаратная линия ввода/вывода GPIO52. */ + Uint16 GPIO52:2; // 9:8 GPIO52 + /* Битовое поле GPIO53, ширина 2 бит; аппаратная линия ввода/вывода GPIO53. */ + Uint16 GPIO53:2; // 11:10 GPIO53 + /* Битовое поле GPIO54, ширина 2 бит; аппаратная линия ввода/вывода GPIO54. */ + Uint16 GPIO54:2; // 13:12 GPIO54 + /* Битовое поле GPIO55, ширина 2 бит; аппаратная линия ввода/вывода GPIO55. */ + Uint16 GPIO55:2; // 15:14 GPIO55 + /* Битовое поле GPIO56, ширина 2 бит; аппаратная линия ввода/вывода GPIO56. */ + Uint16 GPIO56:2; // 17:16 GPIO56 + /* Битовое поле GPIO57, ширина 2 бит; аппаратная линия ввода/вывода GPIO57. */ + Uint16 GPIO57:2; // 19:18 GPIO57 + /* Битовое поле GPIO58, ширина 2 бит; аппаратная линия ввода/вывода GPIO58. */ + Uint16 GPIO58:2; // 21:20 GPIO58 + /* Битовое поле GPIO59, ширина 2 бит; аппаратная линия ввода/вывода GPIO59. */ + Uint16 GPIO59:2; // 23:22 GPIO59 + /* Битовое поле GPIO60, ширина 2 бит; аппаратная линия ввода/вывода GPIO60. */ + Uint16 GPIO60:2; // 25:24 GPIO60 + /* Битовое поле GPIO61, ширина 2 бит; аппаратная линия ввода/вывода GPIO61. */ + Uint16 GPIO61:2; // 27:26 GPIO61 + /* Битовое поле GPIO62, ширина 2 бит; аппаратная линия ввода/вывода GPIO62. */ + Uint16 GPIO62:2; // 29:28 GPIO62 + /* Битовое поле GPIO63, ширина 2 бит; аппаратная линия ввода/вывода GPIO63. */ + Uint16 GPIO63:2; // 31:30 GPIO63 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру GPC1_BITS; порядок полей определяет расположение данных. */ +struct GPC1_BITS { // bits description + /* Битовое поле GPIO64, ширина 2 бит; аппаратная линия ввода/вывода GPIO64. */ + Uint16 GPIO64:2; // 1:0 GPIO64 + /* Битовое поле GPIO65, ширина 2 бит; аппаратная линия ввода/вывода GPIO65. */ + Uint16 GPIO65:2; // 3:2 GPIO65 + /* Битовое поле GPIO66, ширина 2 бит; аппаратная линия ввода/вывода GPIO66. */ + Uint16 GPIO66:2; // 5:4 GPIO66 + /* Битовое поле GPIO67, ширина 2 бит; аппаратная линия ввода/вывода GPIO67. */ + Uint16 GPIO67:2; // 7:6 GPIO67 + /* Битовое поле GPIO68, ширина 2 бит; аппаратная линия ввода/вывода GPIO68. */ + Uint16 GPIO68:2; // 9:8 GPIO68 + /* Битовое поле GPIO69, ширина 2 бит; аппаратная линия ввода/вывода GPIO69. */ + Uint16 GPIO69:2; // 11:10 GPIO69 + /* Битовое поле GPIO70, ширина 2 бит; аппаратная линия ввода/вывода GPIO70. */ + Uint16 GPIO70:2; // 13:12 GPIO70 + /* Битовое поле GPIO71, ширина 2 бит; аппаратная линия ввода/вывода GPIO71. */ + Uint16 GPIO71:2; // 15:14 GPIO71 + /* Битовое поле GPIO72, ширина 2 бит; аппаратная линия ввода/вывода GPIO72. */ + Uint16 GPIO72:2; // 17:16 GPIO72 + /* Битовое поле GPIO73, ширина 2 бит; аппаратная линия ввода/вывода GPIO73. */ + Uint16 GPIO73:2; // 19:18 GPIO73 + /* Битовое поле GPIO74, ширина 2 бит; аппаратная линия ввода/вывода GPIO74. */ + Uint16 GPIO74:2; // 21:20 GPIO74 + /* Битовое поле GPIO75, ширина 2 бит; аппаратная линия ввода/вывода GPIO75. */ + Uint16 GPIO75:2; // 23:22 GPIO75 + /* Битовое поле GPIO76, ширина 2 бит; аппаратная линия ввода/вывода GPIO76. */ + Uint16 GPIO76:2; // 25:24 GPIO76 + /* Битовое поле GPIO77, ширина 2 бит; аппаратная линия ввода/вывода GPIO77. */ + Uint16 GPIO77:2; // 27:26 GPIO77 + /* Битовое поле GPIO78, ширина 2 бит; аппаратная линия ввода/вывода GPIO78. */ + Uint16 GPIO78:2; // 29:28 GPIO78 + /* Битовое поле GPIO79, ширина 2 бит; аппаратная линия ввода/вывода GPIO79. */ + Uint16 GPIO79:2; // 31:30 GPIO79 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру GPC2_BITS; порядок полей определяет расположение данных. */ +struct GPC2_BITS { // bits description + /* Битовое поле GPIO80, ширина 2 бит; аппаратная линия ввода/вывода GPIO80. */ + Uint16 GPIO80:2; // 1:0 GPIO80 + /* Битовое поле GPIO81, ширина 2 бит; аппаратная линия ввода/вывода GPIO81. */ + Uint16 GPIO81:2; // 3:2 GPIO81 + /* Битовое поле GPIO82, ширина 2 бит; аппаратная линия ввода/вывода GPIO82. */ + Uint16 GPIO82:2; // 5:4 GPIO82 + /* Битовое поле GPIO83, ширина 2 бит; аппаратная линия ввода/вывода GPIO83. */ + Uint16 GPIO83:2; // 7:6 GPIO83 + /* Битовое поле GPIO84, ширина 2 бит; аппаратная линия ввода/вывода GPIO84. */ + Uint16 GPIO84:2; // 9:8 GPIO84 + /* Битовое поле GPIO85, ширина 2 бит; аппаратная линия ввода/вывода GPIO85. */ + Uint16 GPIO85:2; // 11:10 GPIO85 + /* Битовое поле GPIO86, ширина 2 бит; аппаратная линия ввода/вывода GPIO86. */ + Uint16 GPIO86:2; // 13:12 GPIO86 + /* Битовое поле GPIO87, ширина 2 бит; аппаратная линия ввода/вывода GPIO87. */ + Uint16 GPIO87:2; // 15:14 GPIO87 + /* Битовое поле rsvd, ширина 16 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:16; // 31:16 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений GPA1_REG в одной области памяти. */ +union GPA1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPA1_BITS bit;; порядок полей определяет расположение данных. */ + struct GPA1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений GPA2_REG в одной области памяти. */ +union GPA2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPA2_BITS bit;; порядок полей определяет расположение данных. */ + struct GPA2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений GPB1_REG в одной области памяти. */ +union GPB1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPB1_BITS bit;; порядок полей определяет расположение данных. */ + struct GPB1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений GPB2_REG в одной области памяти. */ +union GPB2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPB2_BITS bit;; порядок полей определяет расположение данных. */ + struct GPB2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений GPC1_REG в одной области памяти. */ +union GPC1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPC1_BITS bit;; порядок полей определяет расположение данных. */ + struct GPC1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений GPC2_REG в одной области памяти. */ +union GPC2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPC2_BITS bit;; порядок полей определяет расположение данных. */ + struct GPC2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// GPIO A DIR/TOGGLE/SET/CLEAR register bit definitions */ +/* Описывает структуру GPADAT_BITS; порядок полей определяет расположение данных. */ +struct GPADAT_BITS { // bits description + /* Битовое поле GPIO0, ширина 1 бит; аппаратная линия ввода/вывода GPIO0. */ + Uint16 GPIO0:1; // 0 GPIO0 + /* Битовое поле GPIO1, ширина 1 бит; аппаратная линия ввода/вывода GPIO1. */ + Uint16 GPIO1:1; // 1 GPIO1 + /* Битовое поле GPIO2, ширина 1 бит; аппаратная линия ввода/вывода GPIO2. */ + Uint16 GPIO2:1; // 2 GPIO2 + /* Битовое поле GPIO3, ширина 1 бит; аппаратная линия ввода/вывода GPIO3. */ + Uint16 GPIO3:1; // 3 GPIO3 + /* Битовое поле GPIO4, ширина 1 бит; аппаратная линия ввода/вывода GPIO4. */ + Uint16 GPIO4:1; // 4 GPIO4 + /* Битовое поле GPIO5, ширина 1 бит; аппаратная линия ввода/вывода GPIO5. */ + Uint16 GPIO5:1; // 5 GPIO5 + /* Битовое поле GPIO6, ширина 1 бит; аппаратная линия ввода/вывода GPIO6. */ + Uint16 GPIO6:1; // 6 GPIO6 + /* Битовое поле GPIO7, ширина 1 бит; аппаратная линия ввода/вывода GPIO7. */ + Uint16 GPIO7:1; // 7 GPIO7 + /* Битовое поле GPIO8, ширина 1 бит; аппаратная линия ввода/вывода GPIO8. */ + Uint16 GPIO8:1; // 8 GPIO8 + /* Битовое поле GPIO9, ширина 1 бит; аппаратная линия ввода/вывода GPIO9. */ + Uint16 GPIO9:1; // 9 GPIO9 + /* Битовое поле GPIO10, ширина 1 бит; аппаратная линия ввода/вывода GPIO10. */ + Uint16 GPIO10:1; // 10 GPIO10 + /* Битовое поле GPIO11, ширина 1 бит; аппаратная линия ввода/вывода GPIO11. */ + Uint16 GPIO11:1; // 11 GPIO11 + /* Битовое поле GPIO12, ширина 1 бит; аппаратная линия ввода/вывода GPIO12. */ + Uint16 GPIO12:1; // 12 GPIO12 + /* Битовое поле GPIO13, ширина 1 бит; аппаратная линия ввода/вывода GPIO13. */ + Uint16 GPIO13:1; // 13 GPIO13 + /* Битовое поле GPIO14, ширина 1 бит; аппаратная линия ввода/вывода GPIO14. */ + Uint16 GPIO14:1; // 14 GPIO14 + /* Битовое поле GPIO15, ширина 1 бит; аппаратная линия ввода/вывода GPIO15. */ + Uint16 GPIO15:1; // 15 GPIO15 + /* Битовое поле GPIO16, ширина 1 бит; аппаратная линия ввода/вывода GPIO16. */ + Uint16 GPIO16:1; // 16 GPIO16 + /* Битовое поле GPIO17, ширина 1 бит; аппаратная линия ввода/вывода GPIO17. */ + Uint16 GPIO17:1; // 17 GPIO17 + /* Битовое поле GPIO18, ширина 1 бит; аппаратная линия ввода/вывода GPIO18. */ + Uint16 GPIO18:1; // 18 GPIO18 + /* Битовое поле GPIO19, ширина 1 бит; аппаратная линия ввода/вывода GPIO19. */ + Uint16 GPIO19:1; // 19 GPIO19 + /* Битовое поле GPIO20, ширина 1 бит; аппаратная линия ввода/вывода GPIO20. */ + Uint16 GPIO20:1; // 20 GPIO20 + /* Битовое поле GPIO21, ширина 1 бит; аппаратная линия ввода/вывода GPIO21. */ + Uint16 GPIO21:1; // 21 GPIO21 + /* Битовое поле GPIO22, ширина 1 бит; аппаратная линия ввода/вывода GPIO22. */ + Uint16 GPIO22:1; // 22 GPIO22 + /* Битовое поле GPIO23, ширина 1 бит; аппаратная линия ввода/вывода GPIO23. */ + Uint16 GPIO23:1; // 23 GPIO23 + /* Битовое поле GPIO24, ширина 1 бит; аппаратная линия ввода/вывода GPIO24. */ + Uint16 GPIO24:1; // 24 GPIO24 + /* Битовое поле GPIO25, ширина 1 бит; аппаратная линия ввода/вывода GPIO25. */ + Uint16 GPIO25:1; // 25 GPIO25 + /* Битовое поле GPIO26, ширина 1 бит; аппаратная линия ввода/вывода GPIO26. */ + Uint16 GPIO26:1; // 26 GPIO26 + /* Битовое поле GPIO27, ширина 1 бит; аппаратная линия ввода/вывода GPIO27. */ + Uint16 GPIO27:1; // 27 GPIO27 + /* Битовое поле GPIO28, ширина 1 бит; аппаратная линия ввода/вывода GPIO28. */ + Uint16 GPIO28:1; // 28 GPIO28 + /* Битовое поле GPIO29, ширина 1 бит; аппаратная линия ввода/вывода GPIO29. */ + Uint16 GPIO29:1; // 29 GPIO29 + /* Битовое поле GPIO30, ширина 1 бит; аппаратная линия ввода/вывода GPIO30. */ + Uint16 GPIO30:1; // 30 GPIO30 + /* Битовое поле GPIO31, ширина 1 бит; аппаратная линия ввода/вывода GPIO31. */ + Uint16 GPIO31:1; // 31 GPIO31 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру GPBDAT_BITS; порядок полей определяет расположение данных. */ +struct GPBDAT_BITS { // bits description + /* Битовое поле GPIO32, ширина 1 бит; аппаратная линия ввода/вывода GPIO32. */ + Uint16 GPIO32:1; // 0 GPIO32 + /* Битовое поле GPIO33, ширина 1 бит; аппаратная линия ввода/вывода GPIO33. */ + Uint16 GPIO33:1; // 1 GPIO33 + /* Битовое поле GPIO34, ширина 1 бит; аппаратная линия ввода/вывода GPIO34. */ + Uint16 GPIO34:1; // 2 GPIO34 + /* Битовое поле GPIO35, ширина 1 бит; аппаратная линия ввода/вывода GPIO35. */ + Uint16 GPIO35:1; // 3 GPIO35 + /* Битовое поле GPIO36, ширина 1 бит; аппаратная линия ввода/вывода GPIO36. */ + Uint16 GPIO36:1; // 4 GPIO36 + /* Битовое поле GPIO37, ширина 1 бит; аппаратная линия ввода/вывода GPIO37. */ + Uint16 GPIO37:1; // 5 GPIO37 + /* Битовое поле GPIO38, ширина 1 бит; аппаратная линия ввода/вывода GPIO38. */ + Uint16 GPIO38:1; // 6 GPIO38 + /* Битовое поле GPIO39, ширина 1 бит; аппаратная линия ввода/вывода GPIO39. */ + Uint16 GPIO39:1; // 7 GPIO39 + /* Битовое поле GPIO40, ширина 1 бит; аппаратная линия ввода/вывода GPIO40. */ + Uint16 GPIO40:1; // 8 GPIO40 + /* Битовое поле GPIO41, ширина 1 бит; аппаратная линия ввода/вывода GPIO41. */ + Uint16 GPIO41:1; // 9 GPIO41 + /* Битовое поле GPIO42, ширина 1 бит; аппаратная линия ввода/вывода GPIO42. */ + Uint16 GPIO42:1; // 10 GPIO42 + /* Битовое поле GPIO43, ширина 1 бит; аппаратная линия ввода/вывода GPIO43. */ + Uint16 GPIO43:1; // 11 GPIO43 + /* Битовое поле GPIO44, ширина 1 бит; аппаратная линия ввода/вывода GPIO44. */ + Uint16 GPIO44:1; // 12 GPIO44 + /* Битовое поле GPIO45, ширина 1 бит; аппаратная линия ввода/вывода GPIO45. */ + Uint16 GPIO45:1; // 13 GPIO45 + /* Битовое поле GPIO46, ширина 1 бит; аппаратная линия ввода/вывода GPIO46. */ + Uint16 GPIO46:1; // 14 GPIO46 + /* Битовое поле GPIO47, ширина 1 бит; аппаратная линия ввода/вывода GPIO47. */ + Uint16 GPIO47:1; // 15 GPIO47 + /* Битовое поле GPIO48, ширина 1 бит; аппаратная линия ввода/вывода GPIO48. */ + Uint16 GPIO48:1; // 16 GPIO48 + /* Битовое поле GPIO49, ширина 1 бит; аппаратная линия ввода/вывода GPIO49. */ + Uint16 GPIO49:1; // 17 GPIO49 + /* Битовое поле GPIO50, ширина 1 бит; аппаратная линия ввода/вывода GPIO50. */ + Uint16 GPIO50:1; // 18 GPIO50 + /* Битовое поле GPIO51, ширина 1 бит; аппаратная линия ввода/вывода GPIO51. */ + Uint16 GPIO51:1; // 19 GPIO51 + /* Битовое поле GPIO52, ширина 1 бит; аппаратная линия ввода/вывода GPIO52. */ + Uint16 GPIO52:1; // 20 GPIO52 + /* Битовое поле GPIO53, ширина 1 бит; аппаратная линия ввода/вывода GPIO53. */ + Uint16 GPIO53:1; // 21 GPIO53 + /* Битовое поле GPIO54, ширина 1 бит; аппаратная линия ввода/вывода GPIO54. */ + Uint16 GPIO54:1; // 22 GPIO54 + /* Битовое поле GPIO55, ширина 1 бит; аппаратная линия ввода/вывода GPIO55. */ + Uint16 GPIO55:1; // 23 GPIO55 + /* Битовое поле GPIO56, ширина 1 бит; аппаратная линия ввода/вывода GPIO56. */ + Uint16 GPIO56:1; // 24 GPIO56 + /* Битовое поле GPIO57, ширина 1 бит; аппаратная линия ввода/вывода GPIO57. */ + Uint16 GPIO57:1; // 25 GPIO57 + /* Битовое поле GPIO58, ширина 1 бит; аппаратная линия ввода/вывода GPIO58. */ + Uint16 GPIO58:1; // 26 GPIO58 + /* Битовое поле GPIO59, ширина 1 бит; аппаратная линия ввода/вывода GPIO59. */ + Uint16 GPIO59:1; // 27 GPIO59 + /* Битовое поле GPIO60, ширина 1 бит; аппаратная линия ввода/вывода GPIO60. */ + Uint16 GPIO60:1; // 28 GPIO60 + /* Битовое поле GPIO61, ширина 1 бит; аппаратная линия ввода/вывода GPIO61. */ + Uint16 GPIO61:1; // 29 GPIO61 + /* Битовое поле GPIO62, ширина 1 бит; аппаратная линия ввода/вывода GPIO62. */ + Uint16 GPIO62:1; // 30 GPIO62 + /* Битовое поле GPIO63, ширина 1 бит; аппаратная линия ввода/вывода GPIO63. */ + Uint16 GPIO63:1; // 31 GPIO63 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру GPCDAT_BITS; порядок полей определяет расположение данных. */ +struct GPCDAT_BITS { // bits description + /* Битовое поле GPIO64, ширина 1 бит; аппаратная линия ввода/вывода GPIO64. */ + Uint16 GPIO64:1; // 0 GPIO64 + /* Битовое поле GPIO65, ширина 1 бит; аппаратная линия ввода/вывода GPIO65. */ + Uint16 GPIO65:1; // 1 GPIO65 + /* Битовое поле GPIO66, ширина 1 бит; аппаратная линия ввода/вывода GPIO66. */ + Uint16 GPIO66:1; // 2 GPIO66 + /* Битовое поле GPIO67, ширина 1 бит; аппаратная линия ввода/вывода GPIO67. */ + Uint16 GPIO67:1; // 3 GPIO67 + /* Битовое поле GPIO68, ширина 1 бит; аппаратная линия ввода/вывода GPIO68. */ + Uint16 GPIO68:1; // 4 GPIO68 + /* Битовое поле GPIO69, ширина 1 бит; аппаратная линия ввода/вывода GPIO69. */ + Uint16 GPIO69:1; // 5 GPIO69 + /* Битовое поле GPIO70, ширина 1 бит; аппаратная линия ввода/вывода GPIO70. */ + Uint16 GPIO70:1; // 6 GPIO70 + /* Битовое поле GPIO71, ширина 1 бит; аппаратная линия ввода/вывода GPIO71. */ + Uint16 GPIO71:1; // 7 GPIO71 + /* Битовое поле GPIO72, ширина 1 бит; аппаратная линия ввода/вывода GPIO72. */ + Uint16 GPIO72:1; // 8 GPIO72 + /* Битовое поле GPIO73, ширина 1 бит; аппаратная линия ввода/вывода GPIO73. */ + Uint16 GPIO73:1; // 9 GPIO73 + /* Битовое поле GPIO74, ширина 1 бит; аппаратная линия ввода/вывода GPIO74. */ + Uint16 GPIO74:1; // 10 GPIO74 + /* Битовое поле GPIO75, ширина 1 бит; аппаратная линия ввода/вывода GPIO75. */ + Uint16 GPIO75:1; // 11 GPIO75 + /* Битовое поле GPIO76, ширина 1 бит; аппаратная линия ввода/вывода GPIO76. */ + Uint16 GPIO76:1; // 12 GPIO76 + /* Битовое поле GPIO77, ширина 1 бит; аппаратная линия ввода/вывода GPIO77. */ + Uint16 GPIO77:1; // 13 GPIO77 + /* Битовое поле GPIO78, ширина 1 бит; аппаратная линия ввода/вывода GPIO78. */ + Uint16 GPIO78:1; // 14 GPIO78 + /* Битовое поле GPIO79, ширина 1 бит; аппаратная линия ввода/вывода GPIO79. */ + Uint16 GPIO79:1; // 15 GPIO79 + /* Битовое поле GPIO80, ширина 1 бит; аппаратная линия ввода/вывода GPIO80. */ + Uint16 GPIO80:1; // 16 GPIO80 + /* Битовое поле GPIO81, ширина 1 бит; аппаратная линия ввода/вывода GPIO81. */ + Uint16 GPIO81:1; // 17 GPIO81 + /* Битовое поле GPIO82, ширина 1 бит; аппаратная линия ввода/вывода GPIO82. */ + Uint16 GPIO82:1; // 18 GPIO82 + /* Битовое поле GPIO83, ширина 1 бит; аппаратная линия ввода/вывода GPIO83. */ + Uint16 GPIO83:1; // 19 GPIO83 + /* Битовое поле GPIO84, ширина 1 бит; аппаратная линия ввода/вывода GPIO84. */ + Uint16 GPIO84:1; // 20 GPIO84 + /* Битовое поле GPIO85, ширина 1 бит; аппаратная линия ввода/вывода GPIO85. */ + Uint16 GPIO85:1; // 21 GPIO85 + /* Битовое поле GPIO86, ширина 1 бит; аппаратная линия ввода/вывода GPIO86. */ + Uint16 GPIO86:1; // 22 GPIO86 + /* Битовое поле GPIO87, ширина 1 бит; аппаратная линия ввода/вывода GPIO87. */ + Uint16 GPIO87:1; // 23 GPIO87 + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 31:24 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений GPADAT_REG в одной области памяти. */ +union GPADAT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPADAT_BITS bit;; порядок полей определяет расположение данных. */ + struct GPADAT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений GPBDAT_REG в одной области памяти. */ +union GPBDAT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPBDAT_BITS bit;; порядок полей определяет расположение данных. */ + struct GPBDAT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений GPCDAT_REG в одной области памяти. */ +union GPCDAT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру GPCDAT_BITS bit;; порядок полей определяет расположение данных. */ + struct GPCDAT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + + +//---------------------------------------------------- +// GPIO Xint1/XINT2/XNMI select register bit definitions */ +/* Описывает структуру GPIOXINT_BITS; порядок полей определяет расположение данных. */ +struct GPIOXINT_BITS { // bits description + /* Битовое поле GPIOSEL, ширина 5 бит; аппаратная линия ввода/вывода GPIOSEL. */ + Uint16 GPIOSEL:5; // 4:0 Select GPIO interrupt input source + /* Битовое поле rsvd1, ширина 11 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:11; // 15:5 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений GPIOXINT_REG в одной области памяти. */ +union GPIOXINT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру GPIOXINT_BITS bit;; порядок полей определяет расположение данных. */ + struct GPIOXINT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру GPIO_CTRL_REGS; порядок полей определяет расположение данных. */ +struct GPIO_CTRL_REGS { + /* Объединяет несколько представлений GPACTRL_REG GPACTRL; в одной области памяти. */ + union GPACTRL_REG GPACTRL; // GPIO A Control Register (GPIO0 to 31) + /* Объединяет несколько представлений GPA1_REG GPAQSEL1; в одной области памяти. */ + union GPA1_REG GPAQSEL1; // GPIO A Qualifier Select 1 Register (GPIO0 to 15) + /* Объединяет несколько представлений GPA2_REG GPAQSEL2; в одной области памяти. */ + union GPA2_REG GPAQSEL2; // GPIO A Qualifier Select 2 Register (GPIO16 to 31) + /* Объединяет несколько представлений GPA1_REG GPAMUX1; в одной области памяти. */ + union GPA1_REG GPAMUX1; // GPIO A Mux 1 Register (GPIO0 to 15) + /* Объединяет несколько представлений GPA2_REG GPAMUX2; в одной области памяти. */ + union GPA2_REG GPAMUX2; // GPIO A Mux 2 Register (GPIO16 to 31) + /* Объединяет несколько представлений GPADAT_REG GPADIR; в одной области памяти. */ + union GPADAT_REG GPADIR; // GPIO A Direction Register (GPIO0 to 31) + /* Объединяет несколько представлений GPADAT_REG GPAPUD; в одной области памяти. */ + union GPADAT_REG GPAPUD; // GPIO A Pull Up Disable Register (GPIO0 to 31) + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint32 rsvd1; + /* Объединяет несколько представлений GPBCTRL_REG GPBCTRL; в одной области памяти. */ + union GPBCTRL_REG GPBCTRL; // GPIO B Control Register (GPIO32 to 63) + /* Объединяет несколько представлений GPB1_REG GPBQSEL1; в одной области памяти. */ + union GPB1_REG GPBQSEL1; // GPIO B Qualifier Select 1 Register (GPIO32 to 47) + /* Объединяет несколько представлений GPB2_REG GPBQSEL2; в одной области памяти. */ + union GPB2_REG GPBQSEL2; // GPIO B Qualifier Select 2 Register (GPIO48 to 63) + /* Объединяет несколько представлений GPB1_REG GPBMUX1; в одной области памяти. */ + union GPB1_REG GPBMUX1; // GPIO B Mux 1 Register (GPIO32 to 47) + /* Объединяет несколько представлений GPB2_REG GPBMUX2; в одной области памяти. */ + union GPB2_REG GPBMUX2; // GPIO B Mux 2 Register (GPIO48 to 63) + /* Объединяет несколько представлений GPBDAT_REG GPBDIR; в одной области памяти. */ + union GPBDAT_REG GPBDIR; // GPIO B Direction Register (GPIO32 to 63) + /* Объединяет несколько представлений GPBDAT_REG GPBPUD; в одной области памяти. */ + union GPBDAT_REG GPBPUD; // GPIO B Pull Up Disable Register (GPIO32 to 63) + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2[8]; + /* Объединяет несколько представлений GPC1_REG GPCMUX1; в одной области памяти. */ + union GPC1_REG GPCMUX1; // GPIO C Mux 1 Register (GPIO64 to 79) + /* Объединяет несколько представлений GPC2_REG GPCMUX2; в одной области памяти. */ + union GPC2_REG GPCMUX2; // GPIO C Mux 2 Register (GPIO80 to 95) + /* Объединяет несколько представлений GPCDAT_REG GPCDIR; в одной области памяти. */ + union GPCDAT_REG GPCDIR; // GPIO C Direction Register (GPIO64 to 95) + /* Объединяет несколько представлений GPCDAT_REG GPCPUD; в одной области памяти. */ + union GPCDAT_REG GPCPUD; // GPIO C Pull Up Disable Register (GPIO64 to 95) +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру GPIO_DATA_REGS; порядок полей определяет расположение данных. */ +struct GPIO_DATA_REGS { + /* Объединяет несколько представлений GPADAT_REG GPADAT; в одной области памяти. */ + union GPADAT_REG GPADAT; // GPIO Data Register (GPIO0 to 31) + /* Объединяет несколько представлений GPADAT_REG GPASET; в одной области памяти. */ + union GPADAT_REG GPASET; // GPIO Data Set Register (GPIO0 to 31) + /* Объединяет несколько представлений GPADAT_REG GPACLEAR; в одной области памяти. */ + union GPADAT_REG GPACLEAR; // GPIO Data Clear Register (GPIO0 to 31) + /* Объединяет несколько представлений GPADAT_REG GPATOGGLE; в одной области памяти. */ + union GPADAT_REG GPATOGGLE; // GPIO Data Toggle Register (GPIO0 to 31) + /* Объединяет несколько представлений GPBDAT_REG GPBDAT; в одной области памяти. */ + union GPBDAT_REG GPBDAT; // GPIO Data Register (GPIO32 to 63) + /* Объединяет несколько представлений GPBDAT_REG GPBSET; в одной области памяти. */ + union GPBDAT_REG GPBSET; // GPIO Data Set Register (GPIO32 to 63) + /* Объединяет несколько представлений GPBDAT_REG GPBCLEAR; в одной области памяти. */ + union GPBDAT_REG GPBCLEAR; // GPIO Data Clear Register (GPIO32 to 63) + /* Объединяет несколько представлений GPBDAT_REG GPBTOGGLE; в одной области памяти. */ + union GPBDAT_REG GPBTOGGLE; // GPIO Data Toggle Register (GPIO32 to 63) + /* Объединяет несколько представлений GPCDAT_REG GPCDAT; в одной области памяти. */ + union GPCDAT_REG GPCDAT; // GPIO Data Register (GPIO64 to 95) + /* Объединяет несколько представлений GPCDAT_REG GPCSET; в одной области памяти. */ + union GPCDAT_REG GPCSET; // GPIO Data Set Register (GPIO64 to 95) + /* Объединяет несколько представлений GPCDAT_REG GPCCLEAR; в одной области памяти. */ + union GPCDAT_REG GPCCLEAR; // GPIO Data Clear Register (GPIO64 to 95) + /* Объединяет несколько представлений GPCDAT_REG GPCTOGGLE; в одной области памяти. */ + union GPCDAT_REG GPCTOGGLE; // GPIO Data Toggle Register (GPIO64 to 95) + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1[8]; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру GPIO_INT_REGS; порядок полей определяет расположение данных. */ +struct GPIO_INT_REGS { + /* Объединяет несколько представлений GPIOXINT_REG GPIOXINT1SEL; в одной области памяти. */ + union GPIOXINT_REG GPIOXINT1SEL; // XINT1 GPIO Input Selection + /* Объединяет несколько представлений GPIOXINT_REG GPIOXINT2SEL; в одной области памяти. */ + union GPIOXINT_REG GPIOXINT2SEL; // XINT2 GPIO Input Selection + /* Объединяет несколько представлений GPIOXINT_REG GPIOXNMISEL; в одной области памяти. */ + union GPIOXINT_REG GPIOXNMISEL; // XNMI_Xint13 GPIO Input Selection + /* Объединяет несколько представлений GPIOXINT_REG GPIOXINT3SEL; в одной области памяти. */ + union GPIOXINT_REG GPIOXINT3SEL; // XINT3 GPIO Input Selection + /* Объединяет несколько представлений GPIOXINT_REG GPIOXINT4SEL; в одной области памяти. */ + union GPIOXINT_REG GPIOXINT4SEL; // XINT4 GPIO Input Selection + /* Объединяет несколько представлений GPIOXINT_REG GPIOXINT5SEL; в одной области памяти. */ + union GPIOXINT_REG GPIOXINT5SEL; // XINT5 GPIO Input Selection + /* Объединяет несколько представлений GPIOXINT_REG GPIOXINT6SEL; в одной области памяти. */ + union GPIOXINT_REG GPIOXINT6SEL; // XINT6 GPIO Input Selection + /* Объединяет несколько представлений GPIOXINT_REG GPIOXINT7SEL; в одной области памяти. */ + union GPIOXINT_REG GPIOXINT7SEL; // XINT7 GPIO Input Selection + /* Объединяет несколько представлений GPADAT_REG GPIOLPMSEL; в одной области памяти. */ + union GPADAT_REG GPIOLPMSEL; // Low power modes GP I/O input select +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//--------------------------------------------------------------------------- +// GPI/O External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct GPIO_CTRL_REGS GpioCtrlRegs;; порядок элементов сохраняется. */ +extern volatile struct GPIO_CTRL_REGS GpioCtrlRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct GPIO_DATA_REGS GpioDataRegs;; порядок элементов сохраняется. */ +extern volatile struct GPIO_DATA_REGS GpioDataRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct GPIO_INT_REGS GpioIntRegs;; порядок элементов сохраняется. */ +extern volatile struct GPIO_INT_REGS GpioIntRegs; + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_GPIO_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_I2c.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_I2c.h new file mode 100644 index 0000000..da548ce --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_I2c.h @@ -0,0 +1,319 @@ +/* Поставляемое TI описание I2c для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/2 $ +// Checkin $Date: March 22, 2007 10:40:22 $ +//########################################################################### +// +// FILE: DSP2833x_I2c.h +// +// TITLE: DSP2833x Enhanced Quadrature Encoder Pulse Module +// Register Bit Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_I2C_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_I2C_H +/* Определяет защитный символ или переключатель DSP2833x_I2C_H для последующей компиляции. */ +#define DSP2833x_I2C_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +//---------------------------------------------------- +// I2C interrupt vector register bit definitions */ +/* Описывает структуру I2CISRC_BITS; порядок полей определяет расположение данных. */ +struct I2CISRC_BITS { // bits description + /* Битовое поле INTCODE, ширина 3 бит; данные INTCODE. */ + Uint16 INTCODE:3; // 2:0 Interrupt code + /* Битовое поле rsvd1, ширина 13 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:13; // 15:3 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений I2CISRC_REG в одной области памяти. */ +union I2CISRC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру I2CISRC_BITS bit;; порядок полей определяет расположение данных. */ + struct I2CISRC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// I2C interrupt mask register bit definitions */ +/* Описывает структуру I2CIER_BITS; порядок полей определяет расположение данных. */ +struct I2CIER_BITS { // bits description + /* Битовое поле ARBL, ширина 1 бит; данные ARBL. */ + Uint16 ARBL:1; // 0 Arbitration lost interrupt + /* Битовое поле NACK, ширина 1 бит; данные NACK. */ + Uint16 NACK:1; // 1 No ack interrupt + /* Битовое поле ARDY, ширина 1 бит; данные ARDY. */ + Uint16 ARDY:1; // 2 Register access ready interrupt + /* Битовое поле RRDY, ширина 1 бит; данные RRDY. */ + Uint16 RRDY:1; // 3 Recieve data ready interrupt + /* Битовое поле XRDY, ширина 1 бит; данные XRDY. */ + Uint16 XRDY:1; // 4 Transmit data ready interrupt + /* Битовое поле SCD, ширина 1 бит; данные SCD. */ + Uint16 SCD:1; // 5 Stop condition detection + /* Битовое поле AAS, ширина 1 бит; данные AAS. */ + Uint16 AAS:1; // 6 Address as slave + /* Битовое поле rsvd, ширина 9 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:9; // 15:7 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений I2CIER_REG в одной области памяти. */ +union I2CIER_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру I2CIER_BITS bit;; порядок полей определяет расположение данных. */ + struct I2CIER_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// I2C status register bit definitions */ +/* Описывает структуру I2CSTR_BITS; порядок полей определяет расположение данных. */ +struct I2CSTR_BITS { // bits description + /* Битовое поле ARBL, ширина 1 бит; данные ARBL. */ + Uint16 ARBL:1; // 0 Arbitration lost interrupt + /* Битовое поле NACK, ширина 1 бит; данные NACK. */ + Uint16 NACK:1; // 1 No ack interrupt + /* Битовое поле ARDY, ширина 1 бит; данные ARDY. */ + Uint16 ARDY:1; // 2 Register access ready interrupt + /* Битовое поле RRDY, ширина 1 бит; данные RRDY. */ + Uint16 RRDY:1; // 3 Recieve data ready interrupt + /* Битовое поле XRDY, ширина 1 бит; данные XRDY. */ + Uint16 XRDY:1; // 4 Transmit data ready interrupt + /* Битовое поле SCD, ширина 1 бит; данные SCD. */ + Uint16 SCD:1; // 5 Stop condition detection + /* Битовое поле rsvd1, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:2; // 7:6 reserved + /* Битовое поле AD0, ширина 1 бит; данные AD0. */ + Uint16 AD0:1; // 8 Address Zero + /* Битовое поле AAS, ширина 1 бит; данные AAS. */ + Uint16 AAS:1; // 9 Address as slave + /* Битовое поле XSMT, ширина 1 бит; данные XSMT. */ + Uint16 XSMT:1; // 10 XMIT shift empty + /* Битовое поле RSFULL, ширина 1 бит; данные RSFULL. */ + Uint16 RSFULL:1; // 11 Recieve shift full + /* Битовое поле BB, ширина 1 бит; данные BB. */ + Uint16 BB:1; // 12 Bus busy + /* Битовое поле NACKSNT, ширина 1 бит; данные NACKSNT. */ + Uint16 NACKSNT:1; // 13 A no ack sent + /* Битовое поле SDIR, ширина 1 бит; данные SDIR. */ + Uint16 SDIR:1; // 14 Slave direction + /* Битовое поле rsvd2, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:1; // 15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений I2CSTR_REG в одной области памяти. */ +union I2CSTR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру I2CSTR_BITS bit;; порядок полей определяет расположение данных. */ + struct I2CSTR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// I2C mode control register bit definitions */ +/* Описывает структуру I2CMDR_BITS; порядок полей определяет расположение данных. */ +struct I2CMDR_BITS { // bits description + /* Битовое поле BC, ширина 3 бит; данные BC. */ + Uint16 BC:3; // 2:0 Bit count + /* Битовое поле FDF, ширина 1 бит; данные FDF. */ + Uint16 FDF:1; // 3 Free data format + /* Битовое поле STB, ширина 1 бит; данные STB. */ + Uint16 STB:1; // 4 Start byte + /* Битовое поле IRS, ширина 1 бит; данные IRS. */ + Uint16 IRS:1; // 5 I2C Reset not + /* Битовое поле DLB, ширина 1 бит; данные DLB. */ + Uint16 DLB:1; // 6 Digital loopback + /* Битовое поле RM, ширина 1 бит; данные RM. */ + Uint16 RM:1; // 7 Repeat mode + /* Битовое поле XA, ширина 1 бит; данные XA. */ + Uint16 XA:1; // 8 Expand address + /* Битовое поле TRX, ширина 1 бит; данные TRX. */ + Uint16 TRX:1; // 9 Transmitter/reciever + /* Битовое поле MST, ширина 1 бит; данные MST. */ + Uint16 MST:1; // 10 Master/slave + /* Битовое поле STP, ширина 1 бит; данные STP. */ + Uint16 STP:1; // 11 Stop condition + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 12 reserved + /* Битовое поле STT, ширина 1 бит; данные STT. */ + Uint16 STT:1; // 13 Start condition + /* Битовое поле FREE, ширина 1 бит; данные FREE. */ + Uint16 FREE:1; // 14 Emulation mode + /* Битовое поле NACKMOD, ширина 1 бит; данные NACKMOD. */ + Uint16 NACKMOD:1; // 15 No Ack mode +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений I2CMDR_REG в одной области памяти. */ +union I2CMDR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру I2CMDR_BITS bit;; порядок полей определяет расположение данных. */ + struct I2CMDR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// I2C pre-scaler register bit definitions */ +/* Описывает структуру I2CPSC_BITS; порядок полей определяет расположение данных. */ +struct I2CPSC_BITS { // bits description + /* Битовое поле IPSC, ширина 8 бит; данные IPSC. */ + Uint16 IPSC:8; // 7:0 pre-scaler + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений I2CPSC_REG в одной области памяти. */ +union I2CPSC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру I2CPSC_BITS bit;; порядок полей определяет расположение данных. */ + struct I2CPSC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- +// TX FIFO control register bit definitions */ +/* Описывает структуру I2CFFTX_BITS; порядок полей определяет расположение данных. */ +struct I2CFFTX_BITS { // bits description + /* Битовое поле TXFFIL, ширина 5 бит; данные TXFFIL. */ + Uint16 TXFFIL:5; // 4:0 FIFO interrupt level + /* Битовое поле TXFFIENA, ширина 1 бит; данные TXFFIENA. */ + Uint16 TXFFIENA:1; // 5 FIFO interrupt enable/disable + /* Битовое поле TXFFINTCLR, ширина 1 бит; данные TXFFINTCLR. */ + Uint16 TXFFINTCLR:1; // 6 FIFO clear + /* Битовое поле TXFFINT, ширина 1 бит; данные TXFFINT. */ + Uint16 TXFFINT:1; // 7 FIFO interrupt flag + /* Битовое поле TXFFST, ширина 5 бит; данные TXFFST. */ + Uint16 TXFFST:5; // 12:8 FIFO level status + /* Битовое поле TXFFRST, ширина 1 бит; данные TXFFRST. */ + Uint16 TXFFRST:1; // 13 FIFO reset + /* Битовое поле I2CFFEN, ширина 1 бит; данные I2CFFEN. */ + Uint16 I2CFFEN:1; // 14 enable/disable TX & RX FIFOs + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 15 reserved + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений I2CFFTX_REG в одной области памяти. */ +union I2CFFTX_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру I2CFFTX_BITS bit;; порядок полей определяет расположение данных. */ + struct I2CFFTX_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// RX FIFO control register bit definitions */ +/* Описывает структуру I2CFFRX_BITS; порядок полей определяет расположение данных. */ +struct I2CFFRX_BITS { // bits description + /* Битовое поле RXFFIL, ширина 5 бит; данные RXFFIL. */ + Uint16 RXFFIL:5; // 4:0 FIFO interrupt level + /* Битовое поле RXFFIENA, ширина 1 бит; данные RXFFIENA. */ + Uint16 RXFFIENA:1; // 5 FIFO interrupt enable/disable + /* Битовое поле RXFFINTCLR, ширина 1 бит; данные RXFFINTCLR. */ + Uint16 RXFFINTCLR:1; // 6 FIFO clear + /* Битовое поле RXFFINT, ширина 1 бит; данные RXFFINT. */ + Uint16 RXFFINT:1; // 7 FIFO interrupt flag + /* Битовое поле RXFFST, ширина 5 бит; данные RXFFST. */ + Uint16 RXFFST:5; // 12:8 FIFO level + /* Битовое поле RXFFRST, ширина 1 бит; данные RXFFRST. */ + Uint16 RXFFRST:1; // 13 FIFO reset + /* Битовое поле rsvd1, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:2; // 15:14 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений I2CFFRX_REG в одной области памяти. */ +union I2CFFRX_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру I2CFFRX_BITS bit;; порядок полей определяет расположение данных. */ + struct I2CFFRX_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//---------------------------------------------------- + +/* Описывает структуру I2C_REGS; порядок полей определяет расположение данных. */ +struct I2C_REGS { + /* Объявляет I2COAR — данные I2COAR. */ + Uint16 I2COAR; // Own address register + /* Объединяет несколько представлений I2CIER_REG I2CIER; в одной области памяти. */ + union I2CIER_REG I2CIER; // Interrupt enable + /* Объединяет несколько представлений I2CSTR_REG I2CSTR; в одной области памяти. */ + union I2CSTR_REG I2CSTR; // Interrupt status + /* Объявляет I2CCLKL — данные I2CCLKL. */ + Uint16 I2CCLKL; // Clock divider low + /* Объявляет I2CCLKH — данные I2CCLKH. */ + Uint16 I2CCLKH; // Clock divider high + /* Объявляет I2CCNT — данные I2CCNT. */ + Uint16 I2CCNT; // Data count + /* Объявляет I2CDRR — данные I2CDRR. */ + Uint16 I2CDRR; // Data recieve + /* Объявляет I2CSAR — данные I2CSAR. */ + Uint16 I2CSAR; // Slave address + /* Объявляет I2CDXR — данные I2CDXR. */ + Uint16 I2CDXR; // Data transmit + /* Объединяет несколько представлений I2CMDR_REG I2CMDR; в одной области памяти. */ + union I2CMDR_REG I2CMDR; // Mode + /* Объединяет несколько представлений I2CISRC_REG I2CISRC; в одной области памяти. */ + union I2CISRC_REG I2CISRC; // Interrupt source + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1; // reserved + /* Объединяет несколько представлений I2CPSC_REG I2CPSC; в одной области памяти. */ + union I2CPSC_REG I2CPSC; // Pre-scaler + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2[19]; // reserved + /* Объединяет несколько представлений I2CFFTX_REG I2CFFTX; в одной области памяти. */ + union I2CFFTX_REG I2CFFTX; // Transmit FIFO + /* Объединяет несколько представлений I2CFFRX_REG I2CFFRX; в одной области памяти. */ + union I2CFFRX_REG I2CFFRX; // Recieve FIFO +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + + +//--------------------------------------------------------------------------- +// External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct I2C_REGS I2caRegs;; порядок элементов сохраняется. */ +extern volatile struct I2C_REGS I2caRegs; + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_I2C_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Mcbsp.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Mcbsp.h new file mode 100644 index 0000000..b70e765 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Mcbsp.h @@ -0,0 +1,1299 @@ +/* Поставляемое TI описание Mcbsp для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/5 $ +// Checkin $Date: May 14, 2008 16:30:31 $ +//########################################################################### +// +// FILE: DSP2833x_Mcbsp.h +// +// TITLE: DSP2833x Device McBSP Register Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_MCBSP_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_MCBSP_H +/* Определяет защитный символ или переключатель DSP2833x_MCBSP_H для последующей компиляции. */ +#define DSP2833x_MCBSP_H + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +//--------------------------------------------------------------------------- +// McBSP Individual Register Bit Definitions: +// +// McBSP DRR2 register bit definitions: +/* Описывает структуру DRR2_BITS; порядок полей определяет расположение данных. */ +struct DRR2_BITS { // bit description + /* Битовое поле HWLB, ширина 8 бит; данные HWLB. */ + Uint16 HWLB:8; // 16:23 High word low byte + /* Битовое поле HWHB, ширина 8 бит; данные HWHB. */ + Uint16 HWHB:8; // 24:31 High word high byte +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений DRR2_REG в одной области памяти. */ +union DRR2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру DRR2_BITS bit;; порядок полей определяет расположение данных. */ + struct DRR2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// McBSP DRR1 register bit definitions: +/* Описывает структуру DRR1_BITS; порядок полей определяет расположение данных. */ +struct DRR1_BITS { // bit description + /* Битовое поле LWLB, ширина 8 бит; данные LWLB. */ + Uint16 LWLB:8; // 16:23 Low word low byte + /* Битовое поле LWHB, ширина 8 бит; данные LWHB. */ + Uint16 LWHB:8; // 24:31 low word high byte +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений DRR1_REG в одной области памяти. */ +union DRR1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру DRR1_BITS bit;; порядок полей определяет расположение данных. */ + struct DRR1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// McBSP DXR2 register bit definitions: +/* Описывает структуру DXR2_BITS; порядок полей определяет расположение данных. */ +struct DXR2_BITS { // bit description + /* Битовое поле HWLB, ширина 8 бит; данные HWLB. */ + Uint16 HWLB:8; // 16:23 High word low byte + /* Битовое поле HWHB, ширина 8 бит; данные HWHB. */ + Uint16 HWHB:8; // 24:31 High word high byte +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений DXR2_REG в одной области памяти. */ +union DXR2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру DXR2_BITS bit;; порядок полей определяет расположение данных. */ + struct DXR2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// McBSP DXR1 register bit definitions: +/* Описывает структуру DXR1_BITS; порядок полей определяет расположение данных. */ +struct DXR1_BITS { // bit description + /* Битовое поле LWLB, ширина 8 бит; данные LWLB. */ + Uint16 LWLB:8; // 16:23 Low word low byte + /* Битовое поле LWHB, ширина 8 бит; данные LWHB. */ + Uint16 LWHB:8; // 24:31 low word high byte +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений DXR1_REG в одной области памяти. */ +union DXR1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру DXR1_BITS bit;; порядок полей определяет расположение данных. */ + struct DXR1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// SPCR2 control register bit definitions: +/* Описывает структуру SPCR2_BITS; порядок полей определяет расположение данных. */ +struct SPCR2_BITS { // bit description + /* Битовое поле XRST, ширина 1 бит; данные XRST. */ + Uint16 XRST:1; // 0 transmit reset + /* Битовое поле XRDY, ширина 1 бит; данные XRDY. */ + Uint16 XRDY:1; // 1 transmit ready + /* Битовое поле XEMPTY, ширина 1 бит; данные XEMPTY. */ + Uint16 XEMPTY:1; // 2 Transmit empty + /* Битовое поле XSYNCERR, ширина 1 бит; данные XSYNCERR. */ + Uint16 XSYNCERR:1; // 3 Transmit syn errorINT flag + /* Битовое поле XINTM, ширина 2 бит; данные XINTM. */ + Uint16 XINTM:2; // 5:4 Transmit interrupt types + /* Битовое поле GRST, ширина 1 бит; данные GRST. */ + Uint16 GRST:1; // 6 CLKG reset + /* Битовое поле FRST, ширина 1 бит; данные FRST. */ + Uint16 FRST:1; // 7 Frame sync reset + /* Битовое поле SOFT, ширина 1 бит; данные SOFT. */ + Uint16 SOFT:1; // 8 SOFT bit + /* Битовое поле FREE, ширина 1 бит; данные FREE. */ + Uint16 FREE:1; // 9 FREE bit + /* Битовое поле rsvd, ширина 6 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:6; // 15:10 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SPCR2_REG в одной области памяти. */ +union SPCR2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SPCR2_BITS bit;; порядок полей определяет расположение данных. */ + struct SPCR2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// SPCR1 control register bit definitions: +/* Описывает структуру SPCR1_BITS; порядок полей определяет расположение данных. */ +struct SPCR1_BITS { // bit description + /* Битовое поле RRST, ширина 1 бит; данные RRST. */ + Uint16 RRST:1; // 0 Receive reset + /* Битовое поле RRDY, ширина 1 бит; данные RRDY. */ + Uint16 RRDY:1; // 1 Receive ready + /* Битовое поле RFULL, ширина 1 бит; данные RFULL. */ + Uint16 RFULL:1; // 2 Receive full + /* Битовое поле RSYNCERR, ширина 1 бит; данные RSYNCERR. */ + Uint16 RSYNCERR:1; // 7 Receive syn error + /* Битовое поле RINTM, ширина 2 бит; данные RINTM. */ + Uint16 RINTM:2; // 5:4 Receive interrupt types + /* Битовое поле ABIS, ширина 1 бит; данные ABIS. */ + Uint16 ABIS:1; // 6 ABIS mode select + /* Битовое поле DXENA, ширина 1 бит; данные DXENA. */ + Uint16 DXENA:1; // 7 DX hi-z enable + /* Битовое поле rsvd, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:3; // 10:8 reserved + /* Битовое поле CLKSTP, ширина 2 бит; данные CLKSTP. */ + Uint16 CLKSTP:2; // 12:11 CLKSTOP mode bit + /* Битовое поле RJUST, ширина 2 бит; данные RJUST. */ + Uint16 RJUST:2; // 13:14 Right justified + /* Битовое поле DLB, ширина 1 бит; данные DLB. */ + Uint16 DLB:1; // 15 Digital loop back +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SPCR1_REG в одной области памяти. */ +union SPCR1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SPCR1_BITS bit;; порядок полей определяет расположение данных. */ + struct SPCR1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// RCR2 control register bit definitions: +/* Описывает структуру RCR2_BITS; порядок полей определяет расположение данных. */ +struct RCR2_BITS { // bit description + /* Битовое поле RDATDLY, ширина 2 бит; данные RDATDLY. */ + Uint16 RDATDLY:2; // 1:0 Receive data delay + /* Битовое поле RFIG, ширина 1 бит; данные RFIG. */ + Uint16 RFIG:1; // 2 Receive frame sync ignore + /* Битовое поле RCOMPAND, ширина 2 бит; данные RCOMPAND. */ + Uint16 RCOMPAND:2; // 4:3 Receive Companding Mode selects + /* Битовое поле RWDLEN2, ширина 3 бит; данные RWDLEN2. */ + Uint16 RWDLEN2:3; // 7:5 Receive word length + /* Битовое поле RFRLEN2, ширина 7 бит; данные RFRLEN2. */ + Uint16 RFRLEN2:7; // 14:8 Receive Frame sync + /* Битовое поле RPHASE, ширина 1 бит; данные RPHASE. */ + Uint16 RPHASE:1; // 15 Receive Phase +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений RCR2_REG в одной области памяти. */ +union RCR2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру RCR2_BITS bit;; порядок полей определяет расположение данных. */ + struct RCR2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// RCR1 control register bit definitions: +/* Описывает структуру RCR1_BITS; порядок полей определяет расположение данных. */ +struct RCR1_BITS { // bit description + /* Битовое поле rsvd1, ширина 5 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:5; // 4:0 reserved + /* Битовое поле RWDLEN1, ширина 3 бит; данные RWDLEN1. */ + Uint16 RWDLEN1:3; // 7:5 Receive word length + /* Битовое поле RFRLEN1, ширина 7 бит; данные RFRLEN1. */ + Uint16 RFRLEN1:7; // 14:8 Receive frame length + /* Битовое поле rsvd2, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:1; // 15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений RCR1_REG в одной области памяти. */ +union RCR1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру RCR1_BITS bit;; порядок полей определяет расположение данных. */ + struct RCR1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XCR2 control register bit definitions: + +/* Описывает структуру XCR2_BITS; порядок полей определяет расположение данных. */ +struct XCR2_BITS { // bit description + /* Битовое поле XDATDLY, ширина 2 бит; данные XDATDLY. */ + Uint16 XDATDLY:2; // 1:0 Transmit data delay + /* Битовое поле XFIG, ширина 1 бит; данные XFIG. */ + Uint16 XFIG:1; // 2 Transmit frame sync ignore + /* Битовое поле XCOMPAND, ширина 2 бит; данные XCOMPAND. */ + Uint16 XCOMPAND:2; // 4:3 Transmit Companding Mode selects + /* Битовое поле XWDLEN2, ширина 3 бит; данные XWDLEN2. */ + Uint16 XWDLEN2:3; // 7:5 Transmit word length + /* Битовое поле XFRLEN2, ширина 7 бит; данные XFRLEN2. */ + Uint16 XFRLEN2:7; // 14:8 Transmit Frame sync + /* Битовое поле XPHASE, ширина 1 бит; данные XPHASE. */ + Uint16 XPHASE:1; // 15 Transmit Phase +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XCR2_REG в одной области памяти. */ +union XCR2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XCR2_BITS bit;; порядок полей определяет расположение данных. */ + struct XCR2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XCR1 control register bit definitions: +/* Описывает структуру XCR1_BITS; порядок полей определяет расположение данных. */ +struct XCR1_BITS { // bit description + /* Битовое поле rsvd1, ширина 5 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:5; // 4:0 reserved + /* Битовое поле XWDLEN1, ширина 3 бит; данные XWDLEN1. */ + Uint16 XWDLEN1:3; // 7:5 Transmit word length + /* Битовое поле XFRLEN1, ширина 7 бит; данные XFRLEN1. */ + Uint16 XFRLEN1:7; // 14:8 Transmit frame length + /* Битовое поле rsvd2, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:1; // 15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XCR1_REG в одной области памяти. */ +union XCR1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XCR1_BITS bit;; порядок полей определяет расположение данных. */ + struct XCR1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// SRGR2 Sample rate generator control register bit definitions: +/* Описывает структуру SRGR2_BITS; порядок полей определяет расположение данных. */ +struct SRGR2_BITS { // bit description + /* Битовое поле FPER, ширина 12 бит; данные FPER. */ + Uint16 FPER:12; // 11:0 Frame period + /* Битовое поле FSGM, ширина 1 бит; данные FSGM. */ + Uint16 FSGM:1; // 12 Frame sync generator mode + /* Битовое поле CLKSM, ширина 1 бит; данные CLKSM. */ + Uint16 CLKSM:1; // 13 Sample rate generator mode + /* Битовое поле rsvd, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:1; // 14 reserved + /* Битовое поле GSYNC, ширина 1 бит; данные GSYNC. */ + Uint16 GSYNC:1; // 15 CLKG sync +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SRGR2_REG в одной области памяти. */ +union SRGR2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SRGR2_BITS bit;; порядок полей определяет расположение данных. */ + struct SRGR2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// SRGR1 control register bit definitions: +/* Описывает структуру SRGR1_BITS; порядок полей определяет расположение данных. */ +struct SRGR1_BITS { // bit description + /* Битовое поле CLKGDV, ширина 8 бит; данные CLKGDV. */ + Uint16 CLKGDV:8; // 7:0 CLKG divider + /* Битовое поле FWID, ширина 8 бит; данные FWID. */ + Uint16 FWID:8; // 15:8 Frame width +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SRGR1_REG в одной области памяти. */ +union SRGR1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SRGR1_BITS bit;; порядок полей определяет расположение данных. */ + struct SRGR1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// MCR2 Multichannel control register bit definitions: +/* Описывает структуру MCR2_BITS; порядок полей определяет расположение данных. */ +struct MCR2_BITS { // bit description + /* Битовое поле XMCM, ширина 2 бит; данные XMCM. */ + Uint16 XMCM:2; // 1:0 Transmit multichannel mode + /* Битовое поле XCBLK, ширина 3 бит; данные XCBLK. */ + Uint16 XCBLK:3; // 2:4 Transmit current block + /* Битовое поле XPABLK, ширина 2 бит; данные XPABLK. */ + Uint16 XPABLK:2; // 5:6 Transmit partition A Block + /* Битовое поле XPBBLK, ширина 2 бит; данные XPBBLK. */ + Uint16 XPBBLK:2; // 7:8 Transmit partition B Block + /* Битовое поле XMCME, ширина 1 бит; данные XMCME. */ + Uint16 XMCME:1; // 9 Transmit multi-channel enhance mode + /* Битовое поле rsvd, ширина 6 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:6; // 15:10 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений MCR2_REG в одной области памяти. */ +union MCR2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру MCR2_BITS bit;; порядок полей определяет расположение данных. */ + struct MCR2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// MCR1 Multichannel control register bit definitions: +/* Описывает структуру MCR1_BITS; порядок полей определяет расположение данных. */ +struct MCR1_BITS { // bit description + /* Битовое поле RMCM, ширина 1 бит; данные RMCM. */ + Uint16 RMCM:1; // 0 Receive multichannel mode + /* Битовое поле rsvd, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:1; // 1 reserved + /* Битовое поле RCBLK, ширина 3 бит; данные RCBLK. */ + Uint16 RCBLK:3; // 4:2 Receive current block + /* Битовое поле RPABLK, ширина 2 бит; данные RPABLK. */ + Uint16 RPABLK:2; // 6:5 Receive partition A Block + /* Битовое поле RPBBLK, ширина 2 бит; данные RPBBLK. */ + Uint16 RPBBLK:2; // 7:8 Receive partition B Block + /* Битовое поле RMCME, ширина 1 бит; данные RMCME. */ + Uint16 RMCME:1; // 9 Receive multi-channel enhance mode + /* Битовое поле rsvd1, ширина 6 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:6; // 15:10 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений MCR1_REG в одной области памяти. */ +union MCR1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру MCR1_BITS bit;; порядок полей определяет расположение данных. */ + struct MCR1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// RCERA control register bit definitions: +/* Описывает структуру RCERA_BITS; порядок полей определяет расположение данных. */ +struct RCERA_BITS { // bit description + /* Битовое поле RCEA0, ширина 1 бит; данные RCEA0. */ + Uint16 RCEA0:1; // 0 Receive Channel enable bit + /* Битовое поле RCEA1, ширина 1 бит; данные RCEA1. */ + Uint16 RCEA1:1; // 1 Receive Channel enable bit + /* Битовое поле RCEA2, ширина 1 бит; данные RCEA2. */ + Uint16 RCEA2:1; // 2 Receive Channel enable bit + /* Битовое поле RCEA3, ширина 1 бит; данные RCEA3. */ + Uint16 RCEA3:1; // 3 Receive Channel enable bit + /* Битовое поле RCEA4, ширина 1 бит; данные RCEA4. */ + Uint16 RCEA4:1; // 4 Receive Channel enable bit + /* Битовое поле RCEA5, ширина 1 бит; данные RCEA5. */ + Uint16 RCEA5:1; // 5 Receive Channel enable bit + /* Битовое поле RCEA6, ширина 1 бит; данные RCEA6. */ + Uint16 RCEA6:1; // 6 Receive Channel enable bit + /* Битовое поле RCEA7, ширина 1 бит; данные RCEA7. */ + Uint16 RCEA7:1; // 7 Receive Channel enable bit + /* Битовое поле RCEA8, ширина 1 бит; данные RCEA8. */ + Uint16 RCEA8:1; // 8 Receive Channel enable bit + /* Битовое поле RCEA9, ширина 1 бит; данные RCEA9. */ + Uint16 RCEA9:1; // 9 Receive Channel enable bit + /* Битовое поле RCEA10, ширина 1 бит; данные RCEA10. */ + Uint16 RCEA10:1; // 10 Receive Channel enable bit + /* Битовое поле RCEA11, ширина 1 бит; данные RCEA11. */ + Uint16 RCEA11:1; // 11 Receive Channel enable bit + /* Битовое поле RCEA12, ширина 1 бит; данные RCEA12. */ + Uint16 RCEA12:1; // 12 Receive Channel enable bit + /* Битовое поле RCEA13, ширина 1 бит; данные RCEA13. */ + Uint16 RCEA13:1; // 13 Receive Channel enable bit + /* Битовое поле RCEA14, ширина 1 бит; данные RCEA14. */ + Uint16 RCEA14:1; // 14 Receive Channel enable bit + /* Битовое поле RCEA15, ширина 1 бит; данные RCEA15. */ + Uint16 RCEA15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений RCERA_REG в одной области памяти. */ +union RCERA_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру RCERA_BITS bit;; порядок полей определяет расположение данных. */ + struct RCERA_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// RCERB control register bit definitions: +/* Описывает структуру RCERB_BITS; порядок полей определяет расположение данных. */ +struct RCERB_BITS { // bit description + /* Битовое поле RCEB0, ширина 1 бит; данные RCEB0. */ + Uint16 RCEB0:1; // 0 Receive Channel enable bit + /* Битовое поле RCEB1, ширина 1 бит; данные RCEB1. */ + Uint16 RCEB1:1; // 1 Receive Channel enable bit + /* Битовое поле RCEB2, ширина 1 бит; данные RCEB2. */ + Uint16 RCEB2:1; // 2 Receive Channel enable bit + /* Битовое поле RCEB3, ширина 1 бит; данные RCEB3. */ + Uint16 RCEB3:1; // 3 Receive Channel enable bit + /* Битовое поле RCEB4, ширина 1 бит; данные RCEB4. */ + Uint16 RCEB4:1; // 4 Receive Channel enable bit + /* Битовое поле RCEB5, ширина 1 бит; данные RCEB5. */ + Uint16 RCEB5:1; // 5 Receive Channel enable bit + /* Битовое поле RCEB6, ширина 1 бит; данные RCEB6. */ + Uint16 RCEB6:1; // 6 Receive Channel enable bit + /* Битовое поле RCEB7, ширина 1 бит; данные RCEB7. */ + Uint16 RCEB7:1; // 7 Receive Channel enable bit + /* Битовое поле RCEB8, ширина 1 бит; данные RCEB8. */ + Uint16 RCEB8:1; // 8 Receive Channel enable bit + /* Битовое поле RCEB9, ширина 1 бит; данные RCEB9. */ + Uint16 RCEB9:1; // 9 Receive Channel enable bit + /* Битовое поле RCEB10, ширина 1 бит; данные RCEB10. */ + Uint16 RCEB10:1; // 10 Receive Channel enable bit + /* Битовое поле RCEB11, ширина 1 бит; данные RCEB11. */ + Uint16 RCEB11:1; // 11 Receive Channel enable bit + /* Битовое поле RCEB12, ширина 1 бит; данные RCEB12. */ + Uint16 RCEB12:1; // 12 Receive Channel enable bit + /* Битовое поле RCEB13, ширина 1 бит; данные RCEB13. */ + Uint16 RCEB13:1; // 13 Receive Channel enable bit + /* Битовое поле RCEB14, ширина 1 бит; данные RCEB14. */ + Uint16 RCEB14:1; // 14 Receive Channel enable bit + /* Битовое поле RCEB15, ширина 1 бит; данные RCEB15. */ + Uint16 RCEB15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений RCERB_REG в одной области памяти. */ +union RCERB_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру RCERB_BITS bit;; порядок полей определяет расположение данных. */ + struct RCERB_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XCERA control register bit definitions: +/* Описывает структуру XCERA_BITS; порядок полей определяет расположение данных. */ +struct XCERA_BITS { // bit description + /* Битовое поле XCERA0, ширина 1 бит; данные XCERA0. */ + Uint16 XCERA0:1; // 0 Receive Channel enable bit + /* Битовое поле XCERA1, ширина 1 бит; данные XCERA1. */ + Uint16 XCERA1:1; // 1 Receive Channel enable bit + /* Битовое поле XCERA2, ширина 1 бит; данные XCERA2. */ + Uint16 XCERA2:1; // 2 Receive Channel enable bit + /* Битовое поле XCERA3, ширина 1 бит; данные XCERA3. */ + Uint16 XCERA3:1; // 3 Receive Channel enable bit + /* Битовое поле XCERA4, ширина 1 бит; данные XCERA4. */ + Uint16 XCERA4:1; // 4 Receive Channel enable bit + /* Битовое поле XCERA5, ширина 1 бит; данные XCERA5. */ + Uint16 XCERA5:1; // 5 Receive Channel enable bit + /* Битовое поле XCERA6, ширина 1 бит; данные XCERA6. */ + Uint16 XCERA6:1; // 6 Receive Channel enable bit + /* Битовое поле XCERA7, ширина 1 бит; данные XCERA7. */ + Uint16 XCERA7:1; // 7 Receive Channel enable bit + /* Битовое поле XCERA8, ширина 1 бит; данные XCERA8. */ + Uint16 XCERA8:1; // 8 Receive Channel enable bit + /* Битовое поле XCERA9, ширина 1 бит; данные XCERA9. */ + Uint16 XCERA9:1; // 9 Receive Channel enable bit + /* Битовое поле XCERA10, ширина 1 бит; данные XCERA10. */ + Uint16 XCERA10:1; // 10 Receive Channel enable bit + /* Битовое поле XCERA11, ширина 1 бит; данные XCERA11. */ + Uint16 XCERA11:1; // 11 Receive Channel enable bit + /* Битовое поле XCERA12, ширина 1 бит; данные XCERA12. */ + Uint16 XCERA12:1; // 12 Receive Channel enable bit + /* Битовое поле XCERA13, ширина 1 бит; данные XCERA13. */ + Uint16 XCERA13:1; // 13 Receive Channel enable bit + /* Битовое поле XCERA14, ширина 1 бит; данные XCERA14. */ + Uint16 XCERA14:1; // 14 Receive Channel enable bit + /* Битовое поле XCERA15, ширина 1 бит; данные XCERA15. */ + Uint16 XCERA15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XCERA_REG в одной области памяти. */ +union XCERA_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XCERA_BITS bit;; порядок полей определяет расположение данных. */ + struct XCERA_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XCERB control register bit definitions: +/* Описывает структуру XCERB_BITS; порядок полей определяет расположение данных. */ +struct XCERB_BITS { // bit description + /* Битовое поле XCERB0, ширина 1 бит; данные XCERB0. */ + Uint16 XCERB0:1; // 0 Receive Channel enable bit + /* Битовое поле XCERB1, ширина 1 бит; данные XCERB1. */ + Uint16 XCERB1:1; // 1 Receive Channel enable bit + /* Битовое поле XCERB2, ширина 1 бит; данные XCERB2. */ + Uint16 XCERB2:1; // 2 Receive Channel enable bit + /* Битовое поле XCERB3, ширина 1 бит; данные XCERB3. */ + Uint16 XCERB3:1; // 3 Receive Channel enable bit + /* Битовое поле XCERB4, ширина 1 бит; данные XCERB4. */ + Uint16 XCERB4:1; // 4 Receive Channel enable bit + /* Битовое поле XCERB5, ширина 1 бит; данные XCERB5. */ + Uint16 XCERB5:1; // 5 Receive Channel enable bit + /* Битовое поле XCERB6, ширина 1 бит; данные XCERB6. */ + Uint16 XCERB6:1; // 6 Receive Channel enable bit + /* Битовое поле XCERB7, ширина 1 бит; данные XCERB7. */ + Uint16 XCERB7:1; // 7 Receive Channel enable bit + /* Битовое поле XCERB8, ширина 1 бит; данные XCERB8. */ + Uint16 XCERB8:1; // 8 Receive Channel enable bit + /* Битовое поле XCERB9, ширина 1 бит; данные XCERB9. */ + Uint16 XCERB9:1; // 9 Receive Channel enable bit + /* Битовое поле XCERB10, ширина 1 бит; данные XCERB10. */ + Uint16 XCERB10:1; // 10 Receive Channel enable bit + /* Битовое поле XCERB11, ширина 1 бит; данные XCERB11. */ + Uint16 XCERB11:1; // 11 Receive Channel enable bit + /* Битовое поле XCERB12, ширина 1 бит; данные XCERB12. */ + Uint16 XCERB12:1; // 12 Receive Channel enable bit + /* Битовое поле XCERB13, ширина 1 бит; данные XCERB13. */ + Uint16 XCERB13:1; // 13 Receive Channel enable bit + /* Битовое поле XCERB14, ширина 1 бит; данные XCERB14. */ + Uint16 XCERB14:1; // 14 Receive Channel enable bit + /* Битовое поле XCERB15, ширина 1 бит; данные XCERB15. */ + Uint16 XCERB15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XCERB_REG в одной области памяти. */ +union XCERB_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XCERB_BITS bit;; порядок полей определяет расположение данных. */ + struct XCERB_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// PCR control register bit definitions: +/* Описывает структуру PCR_BITS; порядок полей определяет расположение данных. */ +struct PCR_BITS { // bit description + /* Битовое поле CLKRP, ширина 1 бит; данные CLKRP. */ + Uint16 CLKRP:1; // 0 Receive Clock polarity + /* Битовое поле CLKXP, ширина 1 бит; данные CLKXP. */ + Uint16 CLKXP:1; // 1 Transmit clock polarity + /* Битовое поле FSRP, ширина 1 бит; данные FSRP. */ + Uint16 FSRP:1; // 2 Receive Frame synchronization polarity + /* Битовое поле FSXP, ширина 1 бит; данные FSXP. */ + Uint16 FSXP:1; // 3 Transmit Frame synchronization polarity + /* Битовое поле DR_STAT, ширина 1 бит; данные DR_STAT. */ + Uint16 DR_STAT:1; // 4 DR pin status - reserved for this McBSP + /* Битовое поле DX_STAT, ширина 1 бит; данные DX_STAT. */ + Uint16 DX_STAT:1; // 5 DX pin status - reserved for this McBSP + /* Битовое поле CLKS_STAT, ширина 1 бит; данные CLKS_STAT. */ + Uint16 CLKS_STAT:1; // 6 CLKS pin status - reserved for 28x -McBSP + /* Битовое поле SCLKME, ширина 1 бит; данные SCLKME. */ + Uint16 SCLKME:1; // 7 Enhanced sample clock mode selection bit. + /* Битовое поле CLKRM, ширина 1 бит; данные CLKRM. */ + Uint16 CLKRM:1; // 8 Receiver Clock Mode + /* Битовое поле CLKXM, ширина 1 бит; данные CLKXM. */ + Uint16 CLKXM:1; // 9 Transmitter Clock Mode. + /* Битовое поле FSRM, ширина 1 бит; данные FSRM. */ + Uint16 FSRM:1; // 10 Receive Frame Synchronization Mode + /* Битовое поле FSXM, ширина 1 бит; данные FSXM. */ + Uint16 FSXM:1; // 11 Transmit Frame Synchronization Mode + /* Битовое поле RIOEN, ширина 1 бит; данные RIOEN. */ + Uint16 RIOEN:1; // 12 General Purpose I/O Mode - reserved in this 28x-McBSP + /* Битовое поле XIOEN, ширина 1 бит; данные XIOEN. */ + Uint16 XIOEN:1; // 13 General Purpose I/O Mode - reserved in this 28x-McBSP + /* Битовое поле IDEL_EN, ширина 1 бит; данные IDEL_EN. */ + Uint16 IDEL_EN:1; // 14 reserved in this 28x-McBSP + /* Битовое поле rsvd, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:1 ; // 15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PCR_REG в одной области памяти. */ +union PCR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PCR_BITS bit;; порядок полей определяет расположение данных. */ + struct PCR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// RCERC control register bit definitions: +/* Описывает структуру RCERC_BITS; порядок полей определяет расположение данных. */ +struct RCERC_BITS { // bit description + /* Битовое поле RCEC0, ширина 1 бит; данные RCEC0. */ + Uint16 RCEC0:1; // 0 Receive Channel enable bit + /* Битовое поле RCEC1, ширина 1 бит; данные RCEC1. */ + Uint16 RCEC1:1; // 1 Receive Channel enable bit + /* Битовое поле RCEC2, ширина 1 бит; данные RCEC2. */ + Uint16 RCEC2:1; // 2 Receive Channel enable bit + /* Битовое поле RCEC3, ширина 1 бит; данные RCEC3. */ + Uint16 RCEC3:1; // 3 Receive Channel enable bit + /* Битовое поле RCEC4, ширина 1 бит; данные RCEC4. */ + Uint16 RCEC4:1; // 4 Receive Channel enable bit + /* Битовое поле RCEC5, ширина 1 бит; данные RCEC5. */ + Uint16 RCEC5:1; // 5 Receive Channel enable bit + /* Битовое поле RCEC6, ширина 1 бит; данные RCEC6. */ + Uint16 RCEC6:1; // 6 Receive Channel enable bit + /* Битовое поле RCEC7, ширина 1 бит; данные RCEC7. */ + Uint16 RCEC7:1; // 7 Receive Channel enable bit + /* Битовое поле RCEC8, ширина 1 бит; данные RCEC8. */ + Uint16 RCEC8:1; // 8 Receive Channel enable bit + /* Битовое поле RCEC9, ширина 1 бит; данные RCEC9. */ + Uint16 RCEC9:1; // 9 Receive Channel enable bit + /* Битовое поле RCEC10, ширина 1 бит; данные RCEC10. */ + Uint16 RCEC10:1; // 10 Receive Channel enable bit + /* Битовое поле RCEC11, ширина 1 бит; данные RCEC11. */ + Uint16 RCEC11:1; // 11 Receive Channel enable bit + /* Битовое поле RCEC12, ширина 1 бит; данные RCEC12. */ + Uint16 RCEC12:1; // 12 Receive Channel enable bit + /* Битовое поле RCEC13, ширина 1 бит; данные RCEC13. */ + Uint16 RCEC13:1; // 13 Receive Channel enable bit + /* Битовое поле RCEC14, ширина 1 бит; данные RCEC14. */ + Uint16 RCEC14:1; // 14 Receive Channel enable bit + /* Битовое поле RCEC15, ширина 1 бит; данные RCEC15. */ + Uint16 RCEC15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений RCERC_REG в одной области памяти. */ +union RCERC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру RCERC_BITS bit;; порядок полей определяет расположение данных. */ + struct RCERC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// RCERD control register bit definitions: +/* Описывает структуру RCERD_BITS; порядок полей определяет расположение данных. */ +struct RCERD_BITS { // bit description + /* Битовое поле RCED0, ширина 1 бит; данные RCED0. */ + Uint16 RCED0:1; // 0 Receive Channel enable bit + /* Битовое поле RCED1, ширина 1 бит; данные RCED1. */ + Uint16 RCED1:1; // 1 Receive Channel enable bit + /* Битовое поле RCED2, ширина 1 бит; данные RCED2. */ + Uint16 RCED2:1; // 2 Receive Channel enable bit + /* Битовое поле RCED3, ширина 1 бит; данные RCED3. */ + Uint16 RCED3:1; // 3 Receive Channel enable bit + /* Битовое поле RCED4, ширина 1 бит; данные RCED4. */ + Uint16 RCED4:1; // 4 Receive Channel enable bit + /* Битовое поле RCED5, ширина 1 бит; данные RCED5. */ + Uint16 RCED5:1; // 5 Receive Channel enable bit + /* Битовое поле RCED6, ширина 1 бит; данные RCED6. */ + Uint16 RCED6:1; // 6 Receive Channel enable bit + /* Битовое поле RCED7, ширина 1 бит; данные RCED7. */ + Uint16 RCED7:1; // 7 Receive Channel enable bit + /* Битовое поле RCED8, ширина 1 бит; данные RCED8. */ + Uint16 RCED8:1; // 8 Receive Channel enable bit + /* Битовое поле RCED9, ширина 1 бит; данные RCED9. */ + Uint16 RCED9:1; // 9 Receive Channel enable bit + /* Битовое поле RCED10, ширина 1 бит; данные RCED10. */ + Uint16 RCED10:1; // 10 Receive Channel enable bit + /* Битовое поле RCED11, ширина 1 бит; данные RCED11. */ + Uint16 RCED11:1; // 11 Receive Channel enable bit + /* Битовое поле RCED12, ширина 1 бит; данные RCED12. */ + Uint16 RCED12:1; // 12 Receive Channel enable bit + /* Битовое поле RCED13, ширина 1 бит; данные RCED13. */ + Uint16 RCED13:1; // 13 Receive Channel enable bit + /* Битовое поле RCED14, ширина 1 бит; данные RCED14. */ + Uint16 RCED14:1; // 14 Receive Channel enable bit + /* Битовое поле RCED15, ширина 1 бит; данные RCED15. */ + Uint16 RCED15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений RCERD_REG в одной области памяти. */ +union RCERD_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру RCERD_BITS bit;; порядок полей определяет расположение данных. */ + struct RCERD_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XCERC control register bit definitions: +/* Описывает структуру XCERC_BITS; порядок полей определяет расположение данных. */ +struct XCERC_BITS { // bit description + /* Битовое поле XCERC0, ширина 1 бит; данные XCERC0. */ + Uint16 XCERC0:1; // 0 Receive Channel enable bit + /* Битовое поле XCERC1, ширина 1 бит; данные XCERC1. */ + Uint16 XCERC1:1; // 1 Receive Channel enable bit + /* Битовое поле XCERC2, ширина 1 бит; данные XCERC2. */ + Uint16 XCERC2:1; // 2 Receive Channel enable bit + /* Битовое поле XCERC3, ширина 1 бит; данные XCERC3. */ + Uint16 XCERC3:1; // 3 Receive Channel enable bit + /* Битовое поле XCERC4, ширина 1 бит; данные XCERC4. */ + Uint16 XCERC4:1; // 4 Receive Channel enable bit + /* Битовое поле XCERC5, ширина 1 бит; данные XCERC5. */ + Uint16 XCERC5:1; // 5 Receive Channel enable bit + /* Битовое поле XCERC6, ширина 1 бит; данные XCERC6. */ + Uint16 XCERC6:1; // 6 Receive Channel enable bit + /* Битовое поле XCERC7, ширина 1 бит; данные XCERC7. */ + Uint16 XCERC7:1; // 7 Receive Channel enable bit + /* Битовое поле XCERC8, ширина 1 бит; данные XCERC8. */ + Uint16 XCERC8:1; // 8 Receive Channel enable bit + /* Битовое поле XCERC9, ширина 1 бит; данные XCERC9. */ + Uint16 XCERC9:1; // 9 Receive Channel enable bit + /* Битовое поле XCERC10, ширина 1 бит; данные XCERC10. */ + Uint16 XCERC10:1; // 10 Receive Channel enable bit + /* Битовое поле XCERC11, ширина 1 бит; данные XCERC11. */ + Uint16 XCERC11:1; // 11 Receive Channel enable bit + /* Битовое поле XCERC12, ширина 1 бит; данные XCERC12. */ + Uint16 XCERC12:1; // 12 Receive Channel enable bit + /* Битовое поле XCERC13, ширина 1 бит; данные XCERC13. */ + Uint16 XCERC13:1; // 13 Receive Channel enable bit + /* Битовое поле XCERC14, ширина 1 бит; данные XCERC14. */ + Uint16 XCERC14:1; // 14 Receive Channel enable bit + /* Битовое поле XCERC15, ширина 1 бит; данные XCERC15. */ + Uint16 XCERC15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XCERC_REG в одной области памяти. */ +union XCERC_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XCERC_BITS bit;; порядок полей определяет расположение данных. */ + struct XCERC_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XCERD control register bit definitions: +/* Описывает структуру XCERD_BITS; порядок полей определяет расположение данных. */ +struct XCERD_BITS { // bit description + /* Битовое поле XCERD0, ширина 1 бит; данные XCERD0. */ + Uint16 XCERD0:1; // 0 Receive Channel enable bit + /* Битовое поле XCERD1, ширина 1 бит; данные XCERD1. */ + Uint16 XCERD1:1; // 1 Receive Channel enable bit + /* Битовое поле XCERD2, ширина 1 бит; данные XCERD2. */ + Uint16 XCERD2:1; // 2 Receive Channel enable bit + /* Битовое поле XCERD3, ширина 1 бит; данные XCERD3. */ + Uint16 XCERD3:1; // 3 Receive Channel enable bit + /* Битовое поле XCERD4, ширина 1 бит; данные XCERD4. */ + Uint16 XCERD4:1; // 4 Receive Channel enable bit + /* Битовое поле XCERD5, ширина 1 бит; данные XCERD5. */ + Uint16 XCERD5:1; // 5 Receive Channel enable bit + /* Битовое поле XCERD6, ширина 1 бит; данные XCERD6. */ + Uint16 XCERD6:1; // 6 Receive Channel enable bit + /* Битовое поле XCERD7, ширина 1 бит; данные XCERD7. */ + Uint16 XCERD7:1; // 7 Receive Channel enable bit + /* Битовое поле XCERD8, ширина 1 бит; данные XCERD8. */ + Uint16 XCERD8:1; // 8 Receive Channel enable bit + /* Битовое поле XCERD9, ширина 1 бит; данные XCERD9. */ + Uint16 XCERD9:1; // 9 Receive Channel enable bit + /* Битовое поле XCERD10, ширина 1 бит; данные XCERD10. */ + Uint16 XCERD10:1; // 10 Receive Channel enable bit + /* Битовое поле XCERD11, ширина 1 бит; данные XCERD11. */ + Uint16 XCERD11:1; // 11 Receive Channel enable bit + /* Битовое поле XCERD12, ширина 1 бит; данные XCERD12. */ + Uint16 XCERD12:1; // 12 Receive Channel enable bit + /* Битовое поле XCERD13, ширина 1 бит; данные XCERD13. */ + Uint16 XCERD13:1; // 13 Receive Channel enable bit + /* Битовое поле XCERD14, ширина 1 бит; данные XCERD14. */ + Uint16 XCERD14:1; // 14 Receive Channel enable bit + /* Битовое поле XCERD15, ширина 1 бит; данные XCERD15. */ + Uint16 XCERD15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XCERD_REG в одной области памяти. */ +union XCERD_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XCERD_BITS bit;; порядок полей определяет расположение данных. */ + struct XCERD_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// RCERE control register bit definitions: +/* Описывает структуру RCERE_BITS; порядок полей определяет расположение данных. */ +struct RCERE_BITS { // bit description + /* Битовое поле RCEE0, ширина 1 бит; данные RCEE0. */ + Uint16 RCEE0:1; // 0 Receive Channel enable bit + /* Битовое поле RCEE1, ширина 1 бит; данные RCEE1. */ + Uint16 RCEE1:1; // 1 Receive Channel enable bit + /* Битовое поле RCEE2, ширина 1 бит; данные RCEE2. */ + Uint16 RCEE2:1; // 2 Receive Channel enable bit + /* Битовое поле RCEE3, ширина 1 бит; данные RCEE3. */ + Uint16 RCEE3:1; // 3 Receive Channel enable bit + /* Битовое поле RCEE4, ширина 1 бит; данные RCEE4. */ + Uint16 RCEE4:1; // 4 Receive Channel enable bit + /* Битовое поле RCEE5, ширина 1 бит; данные RCEE5. */ + Uint16 RCEE5:1; // 5 Receive Channel enable bit + /* Битовое поле RCEE6, ширина 1 бит; данные RCEE6. */ + Uint16 RCEE6:1; // 6 Receive Channel enable bit + /* Битовое поле RCEE7, ширина 1 бит; данные RCEE7. */ + Uint16 RCEE7:1; // 7 Receive Channel enable bit + /* Битовое поле RCEE8, ширина 1 бит; данные RCEE8. */ + Uint16 RCEE8:1; // 8 Receive Channel enable bit + /* Битовое поле RCEE9, ширина 1 бит; данные RCEE9. */ + Uint16 RCEE9:1; // 9 Receive Channel enable bit + /* Битовое поле RCEE10, ширина 1 бит; данные RCEE10. */ + Uint16 RCEE10:1; // 10 Receive Channel enable bit + /* Битовое поле RCEE11, ширина 1 бит; данные RCEE11. */ + Uint16 RCEE11:1; // 11 Receive Channel enable bit + /* Битовое поле RCEE12, ширина 1 бит; данные RCEE12. */ + Uint16 RCEE12:1; // 12 Receive Channel enable bit + /* Битовое поле RCEE13, ширина 1 бит; данные RCEE13. */ + Uint16 RCEE13:1; // 13 Receive Channel enable bit + /* Битовое поле RCEE14, ширина 1 бит; данные RCEE14. */ + Uint16 RCEE14:1; // 14 Receive Channel enable bit + /* Битовое поле RCEE15, ширина 1 бит; данные RCEE15. */ + Uint16 RCEE15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений RCERE_REG в одной области памяти. */ +union RCERE_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру RCERE_BITS bit;; порядок полей определяет расположение данных. */ + struct RCERE_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// RCERF control register bit definitions: +/* Описывает структуру RCERF_BITS; порядок полей определяет расположение данных. */ +struct RCERF_BITS { // bit description + /* Битовое поле RCEF0, ширина 1 бит; данные RCEF0. */ + Uint16 RCEF0:1; // 0 Receive Channel enable bit + /* Битовое поле RCEF1, ширина 1 бит; данные RCEF1. */ + Uint16 RCEF1:1; // 1 Receive Channel enable bit + /* Битовое поле RCEF2, ширина 1 бит; данные RCEF2. */ + Uint16 RCEF2:1; // 2 Receive Channel enable bit + /* Битовое поле RCEF3, ширина 1 бит; данные RCEF3. */ + Uint16 RCEF3:1; // 3 Receive Channel enable bit + /* Битовое поле RCEF4, ширина 1 бит; данные RCEF4. */ + Uint16 RCEF4:1; // 4 Receive Channel enable bit + /* Битовое поле RCEF5, ширина 1 бит; данные RCEF5. */ + Uint16 RCEF5:1; // 5 Receive Channel enable bit + /* Битовое поле RCEF6, ширина 1 бит; данные RCEF6. */ + Uint16 RCEF6:1; // 6 Receive Channel enable bit + /* Битовое поле RCEF7, ширина 1 бит; данные RCEF7. */ + Uint16 RCEF7:1; // 7 Receive Channel enable bit + /* Битовое поле RCEF8, ширина 1 бит; данные RCEF8. */ + Uint16 RCEF8:1; // 8 Receive Channel enable bit + /* Битовое поле RCEF9, ширина 1 бит; данные RCEF9. */ + Uint16 RCEF9:1; // 9 Receive Channel enable bit + /* Битовое поле RCEF10, ширина 1 бит; данные RCEF10. */ + Uint16 RCEF10:1; // 10 Receive Channel enable bit + /* Битовое поле RCEF11, ширина 1 бит; данные RCEF11. */ + Uint16 RCEF11:1; // 11 Receive Channel enable bit + /* Битовое поле RCEF12, ширина 1 бит; данные RCEF12. */ + Uint16 RCEF12:1; // 12 Receive Channel enable bit + /* Битовое поле RCEF13, ширина 1 бит; данные RCEF13. */ + Uint16 RCEF13:1; // 13 Receive Channel enable bit + /* Битовое поле RCEF14, ширина 1 бит; данные RCEF14. */ + Uint16 RCEF14:1; // 14 Receive Channel enable bit + /* Битовое поле RCEF15, ширина 1 бит; данные RCEF15. */ + Uint16 RCEF15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений RCERF_REG в одной области памяти. */ +union RCERF_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру RCERF_BITS bit;; порядок полей определяет расположение данных. */ + struct RCERF_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XCERE control register bit definitions: +/* Описывает структуру XCERE_BITS; порядок полей определяет расположение данных. */ +struct XCERE_BITS { // bit description + /* Битовое поле XCERE0, ширина 1 бит; данные XCERE0. */ + Uint16 XCERE0:1; // 0 Receive Channel enable bit + /* Битовое поле XCERE1, ширина 1 бит; данные XCERE1. */ + Uint16 XCERE1:1; // 1 Receive Channel enable bit + /* Битовое поле XCERE2, ширина 1 бит; данные XCERE2. */ + Uint16 XCERE2:1; // 2 Receive Channel enable bit + /* Битовое поле XCERE3, ширина 1 бит; данные XCERE3. */ + Uint16 XCERE3:1; // 3 Receive Channel enable bit + /* Битовое поле XCERE4, ширина 1 бит; данные XCERE4. */ + Uint16 XCERE4:1; // 4 Receive Channel enable bit + /* Битовое поле XCERE5, ширина 1 бит; данные XCERE5. */ + Uint16 XCERE5:1; // 5 Receive Channel enable bit + /* Битовое поле XCERE6, ширина 1 бит; данные XCERE6. */ + Uint16 XCERE6:1; // 6 Receive Channel enable bit + /* Битовое поле XCERE7, ширина 1 бит; данные XCERE7. */ + Uint16 XCERE7:1; // 7 Receive Channel enable bit + /* Битовое поле XCERE8, ширина 1 бит; данные XCERE8. */ + Uint16 XCERE8:1; // 8 Receive Channel enable bit + /* Битовое поле XCERE9, ширина 1 бит; данные XCERE9. */ + Uint16 XCERE9:1; // 9 Receive Channel enable bit + /* Битовое поле XCERE10, ширина 1 бит; данные XCERE10. */ + Uint16 XCERE10:1; // 10 Receive Channel enable bit + /* Битовое поле XCERE11, ширина 1 бит; данные XCERE11. */ + Uint16 XCERE11:1; // 11 Receive Channel enable bit + /* Битовое поле XCERE12, ширина 1 бит; данные XCERE12. */ + Uint16 XCERE12:1; // 12 Receive Channel enable bit + /* Битовое поле XCERE13, ширина 1 бит; данные XCERE13. */ + Uint16 XCERE13:1; // 13 Receive Channel enable bit + /* Битовое поле XCERE14, ширина 1 бит; данные XCERE14. */ + Uint16 XCERE14:1; // 14 Receive Channel enable bit + /* Битовое поле XCERE15, ширина 1 бит; данные XCERE15. */ + Uint16 XCERE15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XCERE_REG в одной области памяти. */ +union XCERE_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XCERE_BITS bit;; порядок полей определяет расположение данных. */ + struct XCERE_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XCERF control register bit definitions: +/* Описывает структуру XCERF_BITS; порядок полей определяет расположение данных. */ +struct XCERF_BITS { // bit description + /* Битовое поле XCERF0, ширина 1 бит; данные XCERF0. */ + Uint16 XCERF0:1; // 0 Receive Channel enable bit + /* Битовое поле XCERF1, ширина 1 бит; данные XCERF1. */ + Uint16 XCERF1:1; // 1 Receive Channel enable bit + /* Битовое поле XCERF2, ширина 1 бит; данные XCERF2. */ + Uint16 XCERF2:1; // 2 Receive Channel enable bit + /* Битовое поле XCERF3, ширина 1 бит; данные XCERF3. */ + Uint16 XCERF3:1; // 3 Receive Channel enable bit + /* Битовое поле XCERF4, ширина 1 бит; данные XCERF4. */ + Uint16 XCERF4:1; // 4 Receive Channel enable bit + /* Битовое поле XCERF5, ширина 1 бит; данные XCERF5. */ + Uint16 XCERF5:1; // 5 Receive Channel enable bit + /* Битовое поле XCERF6, ширина 1 бит; данные XCERF6. */ + Uint16 XCERF6:1; // 6 Receive Channel enable bit + /* Битовое поле XCERF7, ширина 1 бит; данные XCERF7. */ + Uint16 XCERF7:1; // 7 Receive Channel enable bit + /* Битовое поле XCERF8, ширина 1 бит; данные XCERF8. */ + Uint16 XCERF8:1; // 8 Receive Channel enable bit + /* Битовое поле XCERF9, ширина 1 бит; данные XCERF9. */ + Uint16 XCERF9:1; // 9 Receive Channel enable bit + /* Битовое поле XCERF10, ширина 1 бит; данные XCERF10. */ + Uint16 XCERF10:1; // 10 Receive Channel enable bit + /* Битовое поле XCERF11, ширина 1 бит; данные XCERF11. */ + Uint16 XCERF11:1; // 11 Receive Channel enable bit + /* Битовое поле XCERF12, ширина 1 бит; данные XCERF12. */ + Uint16 XCERF12:1; // 12 Receive Channel enable bit + /* Битовое поле XCERF13, ширина 1 бит; данные XCERF13. */ + Uint16 XCERF13:1; // 13 Receive Channel enable bit + /* Битовое поле XCERF14, ширина 1 бит; данные XCERF14. */ + Uint16 XCERF14:1; // 14 Receive Channel enable bit + /* Битовое поле XCERF15, ширина 1 бит; данные XCERF15. */ + Uint16 XCERF15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XCERF_REG в одной области памяти. */ +union XCERF_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XCERF_BITS bit;; порядок полей определяет расположение данных. */ + struct XCERF_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// RCERG control register bit definitions: +/* Описывает структуру RCERG_BITS; порядок полей определяет расположение данных. */ +struct RCERG_BITS { // bit description + /* Битовое поле RCEG0, ширина 1 бит; данные RCEG0. */ + Uint16 RCEG0:1; // 0 Receive Channel enable bit + /* Битовое поле RCEG1, ширина 1 бит; данные RCEG1. */ + Uint16 RCEG1:1; // 1 Receive Channel enable bit + /* Битовое поле RCEG2, ширина 1 бит; данные RCEG2. */ + Uint16 RCEG2:1; // 2 Receive Channel enable bit + /* Битовое поле RCEG3, ширина 1 бит; данные RCEG3. */ + Uint16 RCEG3:1; // 3 Receive Channel enable bit + /* Битовое поле RCEG4, ширина 1 бит; данные RCEG4. */ + Uint16 RCEG4:1; // 4 Receive Channel enable bit + /* Битовое поле RCEG5, ширина 1 бит; данные RCEG5. */ + Uint16 RCEG5:1; // 5 Receive Channel enable bit + /* Битовое поле RCEG6, ширина 1 бит; данные RCEG6. */ + Uint16 RCEG6:1; // 6 Receive Channel enable bit + /* Битовое поле RCEG7, ширина 1 бит; данные RCEG7. */ + Uint16 RCEG7:1; // 7 Receive Channel enable bit + /* Битовое поле RCEG8, ширина 1 бит; данные RCEG8. */ + Uint16 RCEG8:1; // 8 Receive Channel enable bit + /* Битовое поле RCEG9, ширина 1 бит; данные RCEG9. */ + Uint16 RCEG9:1; // 9 Receive Channel enable bit + /* Битовое поле RCEG10, ширина 1 бит; данные RCEG10. */ + Uint16 RCEG10:1; // 10 Receive Channel enable bit + /* Битовое поле RCEG11, ширина 1 бит; данные RCEG11. */ + Uint16 RCEG11:1; // 11 Receive Channel enable bit + /* Битовое поле RCEG12, ширина 1 бит; данные RCEG12. */ + Uint16 RCEG12:1; // 12 Receive Channel enable bit + /* Битовое поле RCEG13, ширина 1 бит; данные RCEG13. */ + Uint16 RCEG13:1; // 13 Receive Channel enable bit + /* Битовое поле RCEG14, ширина 1 бит; данные RCEG14. */ + Uint16 RCEG14:1; // 14 Receive Channel enable bit + /* Битовое поле RCEG15, ширина 1 бит; данные RCEG15. */ + Uint16 RCEG15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений RCERG_REG в одной области памяти. */ +union RCERG_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру RCERG_BITS bit;; порядок полей определяет расположение данных. */ + struct RCERG_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// RCERH control register bit definitions: +/* Описывает структуру RCERH_BITS; порядок полей определяет расположение данных. */ +struct RCERH_BITS { // bit description + /* Битовое поле RCEH0, ширина 1 бит; данные RCEH0. */ + Uint16 RCEH0:1; // 0 Receive Channel enable bit + /* Битовое поле RCEH1, ширина 1 бит; данные RCEH1. */ + Uint16 RCEH1:1; // 1 Receive Channel enable bit + /* Битовое поле RCEH2, ширина 1 бит; данные RCEH2. */ + Uint16 RCEH2:1; // 2 Receive Channel enable bit + /* Битовое поле RCEH3, ширина 1 бит; данные RCEH3. */ + Uint16 RCEH3:1; // 3 Receive Channel enable bit + /* Битовое поле RCEH4, ширина 1 бит; данные RCEH4. */ + Uint16 RCEH4:1; // 4 Receive Channel enable bit + /* Битовое поле RCEH5, ширина 1 бит; данные RCEH5. */ + Uint16 RCEH5:1; // 5 Receive Channel enable bit + /* Битовое поле RCEH6, ширина 1 бит; данные RCEH6. */ + Uint16 RCEH6:1; // 6 Receive Channel enable bit + /* Битовое поле RCEH7, ширина 1 бит; данные RCEH7. */ + Uint16 RCEH7:1; // 7 Receive Channel enable bit + /* Битовое поле RCEH8, ширина 1 бит; данные RCEH8. */ + Uint16 RCEH8:1; // 8 Receive Channel enable bit + /* Битовое поле RCEH9, ширина 1 бит; данные RCEH9. */ + Uint16 RCEH9:1; // 9 Receive Channel enable bit + /* Битовое поле RCEH10, ширина 1 бит; данные RCEH10. */ + Uint16 RCEH10:1; // 10 Receive Channel enable bit + /* Битовое поле RCEH11, ширина 1 бит; данные RCEH11. */ + Uint16 RCEH11:1; // 11 Receive Channel enable bit + /* Битовое поле RCEH12, ширина 1 бит; данные RCEH12. */ + Uint16 RCEH12:1; // 12 Receive Channel enable bit + /* Битовое поле RCEH13, ширина 1 бит; данные RCEH13. */ + Uint16 RCEH13:1; // 13 Receive Channel enable bit + /* Битовое поле RCEH14, ширина 1 бит; данные RCEH14. */ + Uint16 RCEH14:1; // 14 Receive Channel enable bit + /* Битовое поле RCEH15, ширина 1 бит; данные RCEH15. */ + Uint16 RCEH15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений RCERH_REG в одной области памяти. */ +union RCERH_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру RCERH_BITS bit;; порядок полей определяет расположение данных. */ + struct RCERH_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XCERG control register bit definitions: +/* Описывает структуру XCERG_BITS; порядок полей определяет расположение данных. */ +struct XCERG_BITS { // bit description + /* Битовое поле XCERG0, ширина 1 бит; данные XCERG0. */ + Uint16 XCERG0:1; // 0 Receive Channel enable bit + /* Битовое поле XCERG1, ширина 1 бит; данные XCERG1. */ + Uint16 XCERG1:1; // 1 Receive Channel enable bit + /* Битовое поле XCERG2, ширина 1 бит; данные XCERG2. */ + Uint16 XCERG2:1; // 2 Receive Channel enable bit + /* Битовое поле XCERG3, ширина 1 бит; данные XCERG3. */ + Uint16 XCERG3:1; // 3 Receive Channel enable bit + /* Битовое поле XCERG4, ширина 1 бит; данные XCERG4. */ + Uint16 XCERG4:1; // 4 Receive Channel enable bit + /* Битовое поле XCERG5, ширина 1 бит; данные XCERG5. */ + Uint16 XCERG5:1; // 5 Receive Channel enable bit + /* Битовое поле XCERG6, ширина 1 бит; данные XCERG6. */ + Uint16 XCERG6:1; // 6 Receive Channel enable bit + /* Битовое поле XCERG7, ширина 1 бит; данные XCERG7. */ + Uint16 XCERG7:1; // 7 Receive Channel enable bit + /* Битовое поле XCERG8, ширина 1 бит; данные XCERG8. */ + Uint16 XCERG8:1; // 8 Receive Channel enable bit + /* Битовое поле XCERG9, ширина 1 бит; данные XCERG9. */ + Uint16 XCERG9:1; // 9 Receive Channel enable bit + /* Битовое поле XCERG10, ширина 1 бит; данные XCERG10. */ + Uint16 XCERG10:1; // 10 Receive Channel enable bit + /* Битовое поле XCERG11, ширина 1 бит; данные XCERG11. */ + Uint16 XCERG11:1; // 11 Receive Channel enable bit + /* Битовое поле XCERG12, ширина 1 бит; данные XCERG12. */ + Uint16 XCERG12:1; // 12 Receive Channel enable bit + /* Битовое поле XCERG13, ширина 1 бит; данные XCERG13. */ + Uint16 XCERG13:1; // 13 Receive Channel enable bit + /* Битовое поле XCERG14, ширина 1 бит; данные XCERG14. */ + Uint16 XCERG14:1; // 14 Receive Channel enable bit + /* Битовое поле XCERG15, ширина 1 бит; данные XCERG15. */ + Uint16 XCERG15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XCERG_REG в одной области памяти. */ +union XCERG_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XCERG_BITS bit;; порядок полей определяет расположение данных. */ + struct XCERG_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XCERH control register bit definitions: +/* Описывает структуру XCERH_BITS; порядок полей определяет расположение данных. */ +struct XCERH_BITS { // bit description + /* Битовое поле XCEH0, ширина 1 бит; данные XCEH0. */ + Uint16 XCEH0:1; // 0 Receive Channel enable bit + /* Битовое поле XCEH1, ширина 1 бит; данные XCEH1. */ + Uint16 XCEH1:1; // 1 Receive Channel enable bit + /* Битовое поле XCEH2, ширина 1 бит; данные XCEH2. */ + Uint16 XCEH2:1; // 2 Receive Channel enable bit + /* Битовое поле XCEH3, ширина 1 бит; данные XCEH3. */ + Uint16 XCEH3:1; // 3 Receive Channel enable bit + /* Битовое поле XCEH4, ширина 1 бит; данные XCEH4. */ + Uint16 XCEH4:1; // 4 Receive Channel enable bit + /* Битовое поле XCEH5, ширина 1 бит; данные XCEH5. */ + Uint16 XCEH5:1; // 5 Receive Channel enable bit + /* Битовое поле XCEH6, ширина 1 бит; данные XCEH6. */ + Uint16 XCEH6:1; // 6 Receive Channel enable bit + /* Битовое поле XCEH7, ширина 1 бит; данные XCEH7. */ + Uint16 XCEH7:1; // 7 Receive Channel enable bit + /* Битовое поле XCEH8, ширина 1 бит; данные XCEH8. */ + Uint16 XCEH8:1; // 8 Receive Channel enable bit + /* Битовое поле XCEH9, ширина 1 бит; данные XCEH9. */ + Uint16 XCEH9:1; // 9 Receive Channel enable bit + /* Битовое поле XCEH10, ширина 1 бит; данные XCEH10. */ + Uint16 XCEH10:1; // 10 Receive Channel enable bit + /* Битовое поле XCEH11, ширина 1 бит; данные XCEH11. */ + Uint16 XCEH11:1; // 11 Receive Channel enable bit + /* Битовое поле XCEH12, ширина 1 бит; данные XCEH12. */ + Uint16 XCEH12:1; // 12 Receive Channel enable bit + /* Битовое поле XCEH13, ширина 1 бит; данные XCEH13. */ + Uint16 XCEH13:1; // 13 Receive Channel enable bit + /* Битовое поле XCEH14, ширина 1 бит; данные XCEH14. */ + Uint16 XCEH14:1; // 14 Receive Channel enable bit + /* Битовое поле XCEH15, ширина 1 бит; данные XCEH15. */ + Uint16 XCEH15:1; // 15 Receive Channel enable bit +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XCERH_REG в одной области памяти. */ +union XCERH_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XCERH_BITS bit;; порядок полей определяет расположение данных. */ + struct XCERH_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +// McBSP Interrupt enable register for RINT/XINT +/* Описывает структуру MFFINT_BITS; порядок полей определяет расположение данных. */ +struct MFFINT_BITS { // bits description + /* Битовое поле XINT, ширина 1 бит; данные XINT. */ + Uint16 XINT:1; // 0 XINT interrupt enable + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 1 reserved + /* Битовое поле RINT, ширина 1 бит; данные RINT. */ + Uint16 RINT:1; // 2 RINT interrupt enable + /* Битовое поле rsvd2, ширина 13 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:13; // 15:3 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений MFFINT_REG в одной области памяти. */ +union MFFINT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру MFFINT_BITS bit;; порядок полей определяет расположение данных. */ + struct MFFINT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//--------------------------------------------------------------------------- +// McBSP Register File: +// +/* Описывает структуру MCBSP_REGS; порядок полей определяет расположение данных. */ +struct MCBSP_REGS { + /* Объединяет несколько представлений DRR2_REG DRR2; в одной области памяти. */ + union DRR2_REG DRR2; // MCBSP Data receive register bits 31-16 + /* Объединяет несколько представлений DRR1_REG DRR1; в одной области памяти. */ + union DRR1_REG DRR1; // MCBSP Data receive register bits 15-0 + /* Объединяет несколько представлений DXR2_REG DXR2; в одной области памяти. */ + union DXR2_REG DXR2; // MCBSP Data transmit register bits 31-16 + /* Объединяет несколько представлений DXR1_REG DXR1; в одной области памяти. */ + union DXR1_REG DXR1; // MCBSP Data transmit register bits 15-0 + /* Объединяет несколько представлений SPCR2_REG SPCR2; в одной области памяти. */ + union SPCR2_REG SPCR2; // MCBSP control register bits 31-16 + /* Объединяет несколько представлений SPCR1_REG SPCR1; в одной области памяти. */ + union SPCR1_REG SPCR1; // MCBSP control register bits 15-0 + /* Объединяет несколько представлений RCR2_REG RCR2; в одной области памяти. */ + union RCR2_REG RCR2; // MCBSP receive control register bits 31-16 + /* Объединяет несколько представлений RCR1_REG RCR1; в одной области памяти. */ + union RCR1_REG RCR1; // MCBSP receive control register bits 15-0 + /* Объединяет несколько представлений XCR2_REG XCR2; в одной области памяти. */ + union XCR2_REG XCR2; // MCBSP transmit control register bits 31-16 + /* Объединяет несколько представлений XCR1_REG XCR1; в одной области памяти. */ + union XCR1_REG XCR1; // MCBSP transmit control register bits 15-0 + /* Объединяет несколько представлений SRGR2_REG SRGR2; в одной области памяти. */ + union SRGR2_REG SRGR2; // MCBSP sample rate gen register bits 31-16 + /* Объединяет несколько представлений SRGR1_REG SRGR1; в одной области памяти. */ + union SRGR1_REG SRGR1; // MCBSP sample rate gen register bits 15-0 + /* Объединяет несколько представлений MCR2_REG MCR2; в одной области памяти. */ + union MCR2_REG MCR2; // MCBSP multichannel register bits 31-16 + /* Объединяет несколько представлений MCR1_REG MCR1; в одной области памяти. */ + union MCR1_REG MCR1; // MCBSP multichannel register bits 15-0 + /* Объединяет несколько представлений RCERA_REG RCERA; в одной области памяти. */ + union RCERA_REG RCERA; // MCBSP Receive channel enable partition A + /* Объединяет несколько представлений RCERB_REG RCERB; в одной области памяти. */ + union RCERB_REG RCERB; // MCBSP Receive channel enable partition B + /* Объединяет несколько представлений XCERA_REG XCERA; в одной области памяти. */ + union XCERA_REG XCERA; // MCBSP Transmit channel enable partition A + /* Объединяет несколько представлений XCERB_REG XCERB; в одной области памяти. */ + union XCERB_REG XCERB; // MCBSP Transmit channel enable partition B + /* Объединяет несколько представлений PCR_REG PCR; в одной области памяти. */ + union PCR_REG PCR; // MCBSP Pin control register bits 15-0 + /* Объединяет несколько представлений RCERC_REG RCERC; в одной области памяти. */ + union RCERC_REG RCERC; // MCBSP Receive channel enable partition C + /* Объединяет несколько представлений RCERD_REG RCERD; в одной области памяти. */ + union RCERD_REG RCERD; // MCBSP Receive channel enable partition D + /* Объединяет несколько представлений XCERC_REG XCERC; в одной области памяти. */ + union XCERC_REG XCERC; // MCBSP Transmit channel enable partition C + /* Объединяет несколько представлений XCERD_REG XCERD; в одной области памяти. */ + union XCERD_REG XCERD; // MCBSP Transmit channel enable partition D + /* Объединяет несколько представлений RCERE_REG RCERE; в одной области памяти. */ + union RCERE_REG RCERE; // MCBSP Receive channel enable partition E + /* Объединяет несколько представлений RCERF_REG RCERF; в одной области памяти. */ + union RCERF_REG RCERF; // MCBSP Receive channel enable partition F + /* Объединяет несколько представлений XCERE_REG XCERE; в одной области памяти. */ + union XCERE_REG XCERE; // MCBSP Transmit channel enable partition E + /* Объединяет несколько представлений XCERF_REG XCERF; в одной области памяти. */ + union XCERF_REG XCERF; // MCBSP Transmit channel enable partition F + /* Объединяет несколько представлений RCERG_REG RCERG; в одной области памяти. */ + union RCERG_REG RCERG; // MCBSP Receive channel enable partition G + /* Объединяет несколько представлений RCERH_REG RCERH; в одной области памяти. */ + union RCERH_REG RCERH; // MCBSP Receive channel enable partition H + /* Объединяет несколько представлений XCERG_REG XCERG; в одной области памяти. */ + union XCERG_REG XCERG; // MCBSP Transmit channel enable partition G + /* Объединяет несколько представлений XCERH_REG XCERH; в одной области памяти. */ + union XCERH_REG XCERH; // MCBSP Transmit channel enable partition H + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1[4]; // reserved + /* Объединяет несколько представлений MFFINT_REG MFFINT; в одной области памяти. */ + union MFFINT_REG MFFINT; // MCBSP Interrupt enable register for RINT/XINT + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2; // reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// McBSP External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct MCBSP_REGS McbspaRegs;; порядок элементов сохраняется. */ +extern volatile struct MCBSP_REGS McbspaRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct MCBSP_REGS McbspbRegs;; порядок элементов сохраняется. */ +extern volatile struct MCBSP_REGS McbspbRegs; + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_MCBSP_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_PieCtrl.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_PieCtrl.h new file mode 100644 index 0000000..b7eece6 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_PieCtrl.h @@ -0,0 +1,260 @@ +/* Поставляемое TI описание PieCtrl для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/1 $ +// Checkin $Date: August 18, 2006 13:52:24 $ +//########################################################################### +// +// FILE: DSP2833x_PieCtrl.h +// +// TITLE: DSP2833x Device PIE Control Register Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + + +/* Начинает условие: DSP2833x_PIE_CTRL_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_PIE_CTRL_H +/* Определяет защитный символ или переключатель DSP2833x_PIE_CTRL_H для последующей компиляции. */ +#define DSP2833x_PIE_CTRL_H + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +//--------------------------------------------------------------------------- +// PIE Control Register Bit Definitions: +// +// PIECTRL: Register bit definitions: +/* Описывает структуру PIECTRL_BITS; порядок полей определяет расположение данных. */ +struct PIECTRL_BITS { // bits description + /* Битовое поле ENPIE, ширина 1 бит; данные ENPIE. */ + Uint16 ENPIE:1; // 0 Enable PIE block + /* Битовое поле PIEVECT, ширина 15 бит; данные PIEVECT. */ + Uint16 PIEVECT:15; // 15:1 Fetched vector address +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PIECTRL_REG в одной области памяти. */ +union PIECTRL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PIECTRL_BITS bit;; порядок полей определяет расположение данных. */ + struct PIECTRL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// PIEIER: Register bit definitions: +/* Описывает структуру PIEIER_BITS; порядок полей определяет расположение данных. */ +struct PIEIER_BITS { // bits description + /* Битовое поле INTx1, ширина 1 бит; данные INTx1. */ + Uint16 INTx1:1; // 0 INTx.1 + /* Битовое поле INTx2, ширина 1 бит; данные INTx2. */ + Uint16 INTx2:1; // 1 INTx.2 + /* Битовое поле INTx3, ширина 1 бит; данные INTx3. */ + Uint16 INTx3:1; // 2 INTx.3 + /* Битовое поле INTx4, ширина 1 бит; данные INTx4. */ + Uint16 INTx4:1; // 3 INTx.4 + /* Битовое поле INTx5, ширина 1 бит; данные INTx5. */ + Uint16 INTx5:1; // 4 INTx.5 + /* Битовое поле INTx6, ширина 1 бит; данные INTx6. */ + Uint16 INTx6:1; // 5 INTx.6 + /* Битовое поле INTx7, ширина 1 бит; данные INTx7. */ + Uint16 INTx7:1; // 6 INTx.7 + /* Битовое поле INTx8, ширина 1 бит; данные INTx8. */ + Uint16 INTx8:1; // 7 INTx.8 + /* Битовое поле rsvd, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PIEIER_REG в одной области памяти. */ +union PIEIER_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PIEIER_BITS bit;; порядок полей определяет расположение данных. */ + struct PIEIER_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// PIEIFR: Register bit definitions: +/* Описывает структуру PIEIFR_BITS; порядок полей определяет расположение данных. */ +struct PIEIFR_BITS { // bits description + /* Битовое поле INTx1, ширина 1 бит; данные INTx1. */ + Uint16 INTx1:1; // 0 INTx.1 + /* Битовое поле INTx2, ширина 1 бит; данные INTx2. */ + Uint16 INTx2:1; // 1 INTx.2 + /* Битовое поле INTx3, ширина 1 бит; данные INTx3. */ + Uint16 INTx3:1; // 2 INTx.3 + /* Битовое поле INTx4, ширина 1 бит; данные INTx4. */ + Uint16 INTx4:1; // 3 INTx.4 + /* Битовое поле INTx5, ширина 1 бит; данные INTx5. */ + Uint16 INTx5:1; // 4 INTx.5 + /* Битовое поле INTx6, ширина 1 бит; данные INTx6. */ + Uint16 INTx6:1; // 5 INTx.6 + /* Битовое поле INTx7, ширина 1 бит; данные INTx7. */ + Uint16 INTx7:1; // 6 INTx.7 + /* Битовое поле INTx8, ширина 1 бит; данные INTx8. */ + Uint16 INTx8:1; // 7 INTx.8 + /* Битовое поле rsvd, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PIEIFR_REG в одной области памяти. */ +union PIEIFR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PIEIFR_BITS bit;; порядок полей определяет расположение данных. */ + struct PIEIFR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// PIEACK: Register bit definitions: +/* Описывает структуру PIEACK_BITS; порядок полей определяет расположение данных. */ +struct PIEACK_BITS { // bits description + /* Битовое поле ACK1, ширина 1 бит; данные ACK1. */ + Uint16 ACK1:1; // 0 Acknowledge PIE interrupt group 1 + /* Битовое поле ACK2, ширина 1 бит; данные ACK2. */ + Uint16 ACK2:1; // 1 Acknowledge PIE interrupt group 2 + /* Битовое поле ACK3, ширина 1 бит; данные ACK3. */ + Uint16 ACK3:1; // 2 Acknowledge PIE interrupt group 3 + /* Битовое поле ACK4, ширина 1 бит; данные ACK4. */ + Uint16 ACK4:1; // 3 Acknowledge PIE interrupt group 4 + /* Битовое поле ACK5, ширина 1 бит; данные ACK5. */ + Uint16 ACK5:1; // 4 Acknowledge PIE interrupt group 5 + /* Битовое поле ACK6, ширина 1 бит; данные ACK6. */ + Uint16 ACK6:1; // 5 Acknowledge PIE interrupt group 6 + /* Битовое поле ACK7, ширина 1 бит; данные ACK7. */ + Uint16 ACK7:1; // 6 Acknowledge PIE interrupt group 7 + /* Битовое поле ACK8, ширина 1 бит; данные ACK8. */ + Uint16 ACK8:1; // 7 Acknowledge PIE interrupt group 8 + /* Битовое поле ACK9, ширина 1 бит; данные ACK9. */ + Uint16 ACK9:1; // 8 Acknowledge PIE interrupt group 9 + /* Битовое поле ACK10, ширина 1 бит; данные ACK10. */ + Uint16 ACK10:1; // 9 Acknowledge PIE interrupt group 10 + /* Битовое поле ACK11, ширина 1 бит; данные ACK11. */ + Uint16 ACK11:1; // 10 Acknowledge PIE interrupt group 11 + /* Битовое поле ACK12, ширина 1 бит; данные ACK12. */ + Uint16 ACK12:1; // 11 Acknowledge PIE interrupt group 12 + /* Битовое поле rsvd, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:4; // 15:12 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PIEACK_REG в одной области памяти. */ +union PIEACK_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PIEACK_BITS bit;; порядок полей определяет расположение данных. */ + struct PIEACK_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// PIE Control Register File: +// +/* Описывает структуру PIE_CTRL_REGS; порядок полей определяет расположение данных. */ +struct PIE_CTRL_REGS { + /* Объединяет несколько представлений PIECTRL_REG PIECTRL; в одной области памяти. */ + union PIECTRL_REG PIECTRL; // PIE control register + /* Объединяет несколько представлений PIEACK_REG PIEACK; в одной области памяти. */ + union PIEACK_REG PIEACK; // PIE acknowledge + /* Объединяет несколько представлений PIEIER_REG PIEIER1; в одной области памяти. */ + union PIEIER_REG PIEIER1; // PIE int1 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR1; в одной области памяти. */ + union PIEIFR_REG PIEIFR1; // PIE int1 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER2; в одной области памяти. */ + union PIEIER_REG PIEIER2; // PIE INT2 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR2; в одной области памяти. */ + union PIEIFR_REG PIEIFR2; // PIE INT2 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER3; в одной области памяти. */ + union PIEIER_REG PIEIER3; // PIE INT3 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR3; в одной области памяти. */ + union PIEIFR_REG PIEIFR3; // PIE INT3 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER4; в одной области памяти. */ + union PIEIER_REG PIEIER4; // PIE INT4 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR4; в одной области памяти. */ + union PIEIFR_REG PIEIFR4; // PIE INT4 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER5; в одной области памяти. */ + union PIEIER_REG PIEIER5; // PIE INT5 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR5; в одной области памяти. */ + union PIEIFR_REG PIEIFR5; // PIE INT5 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER6; в одной области памяти. */ + union PIEIER_REG PIEIER6; // PIE INT6 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR6; в одной области памяти. */ + union PIEIFR_REG PIEIFR6; // PIE INT6 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER7; в одной области памяти. */ + union PIEIER_REG PIEIER7; // PIE INT7 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR7; в одной области памяти. */ + union PIEIFR_REG PIEIFR7; // PIE INT7 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER8; в одной области памяти. */ + union PIEIER_REG PIEIER8; // PIE INT8 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR8; в одной области памяти. */ + union PIEIFR_REG PIEIFR8; // PIE INT8 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER9; в одной области памяти. */ + union PIEIER_REG PIEIER9; // PIE INT9 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR9; в одной области памяти. */ + union PIEIFR_REG PIEIFR9; // PIE INT9 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER10; в одной области памяти. */ + union PIEIER_REG PIEIER10; // PIE int10 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR10; в одной области памяти. */ + union PIEIFR_REG PIEIFR10; // PIE int10 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER11; в одной области памяти. */ + union PIEIER_REG PIEIER11; // PIE int11 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR11; в одной области памяти. */ + union PIEIFR_REG PIEIFR11; // PIE int11 IFR register + /* Объединяет несколько представлений PIEIER_REG PIEIER12; в одной области памяти. */ + union PIEIER_REG PIEIER12; // PIE int12 IER register + /* Объединяет несколько представлений PIEIFR_REG PIEIFR12; в одной области памяти. */ + union PIEIFR_REG PIEIFR12; // PIE int12 IFR register +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Задаёт PIEACK_GROUP1 = 0x0001; данные PIEACK_GROUP1. */ +#define PIEACK_GROUP1 0x0001 +/* Задаёт PIEACK_GROUP2 = 0x0002; данные PIEACK_GROUP2. */ +#define PIEACK_GROUP2 0x0002 +/* Задаёт PIEACK_GROUP3 = 0x0004; данные PIEACK_GROUP3. */ +#define PIEACK_GROUP3 0x0004 +/* Задаёт PIEACK_GROUP4 = 0x0008; данные PIEACK_GROUP4. */ +#define PIEACK_GROUP4 0x0008 +/* Задаёт PIEACK_GROUP5 = 0x0010; данные PIEACK_GROUP5. */ +#define PIEACK_GROUP5 0x0010 +/* Задаёт PIEACK_GROUP6 = 0x0020; данные PIEACK_GROUP6. */ +#define PIEACK_GROUP6 0x0020 +/* Задаёт PIEACK_GROUP7 = 0x0040; данные PIEACK_GROUP7. */ +#define PIEACK_GROUP7 0x0040 +/* Задаёт PIEACK_GROUP8 = 0x0080; данные PIEACK_GROUP8. */ +#define PIEACK_GROUP8 0x0080 +/* Задаёт PIEACK_GROUP9 = 0x0100; данные PIEACK_GROUP9. */ +#define PIEACK_GROUP9 0x0100 +/* Задаёт PIEACK_GROUP10 = 0x0200; данные PIEACK_GROUP10. */ +#define PIEACK_GROUP10 0x0200 +/* Задаёт PIEACK_GROUP11 = 0x0400; данные PIEACK_GROUP11. */ +#define PIEACK_GROUP11 0x0400 +/* Задаёт PIEACK_GROUP12 = 0x0800; данные PIEACK_GROUP12. */ +#define PIEACK_GROUP12 0x0800 + +//--------------------------------------------------------------------------- +// PIE Control Registers External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct PIE_CTRL_REGS PieCtrlRegs;; порядок элементов сохраняется. */ +extern volatile struct PIE_CTRL_REGS PieCtrlRegs; + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_PIE_CTRL_H definition + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_PieVect.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_PieVect.h new file mode 100644 index 0000000..b768be2 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_PieVect.h @@ -0,0 +1,349 @@ +/* Поставляемое TI описание PieVect для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/2 $ +// Checkin $Date: March 16, 2007 09:00:21 $ +//########################################################################### +// +// FILE: DSP2833x_PieVect.h +// +// TITLE: DSP2833x Devices PIE Vector Table Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_PIE_VECT_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_PIE_VECT_H +/* Определяет защитный символ или переключатель DSP2833x_PIE_VECT_H для последующей компиляции. */ +#define DSP2833x_PIE_VECT_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +//--------------------------------------------------------------------------- +// PIE Interrupt Vector Table Definition: +// +// Create a user type called PINT (pointer to interrupt): + +/* Объявляет интерфейс функции void; реализация вызывается через этот прототип. */ +typedef interrupt void(*PINT)(void); + +// Define Vector Table: +/* Описывает структуру PIE_VECT_TABLE; порядок полей определяет расположение данных. */ +struct PIE_VECT_TABLE { + +// Reset is never fetched from this table. +// It will always be fetched from 0x3FFFC0 in +// boot ROM + + /* Продолжает список аргументов, полей или выражение PINT PIE1_RESERVED;; порядок элементов сохраняется. */ + PINT PIE1_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE2_RESERVED;; порядок элементов сохраняется. */ + PINT PIE2_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE3_RESERVED;; порядок элементов сохраняется. */ + PINT PIE3_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE4_RESERVED;; порядок элементов сохраняется. */ + PINT PIE4_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE5_RESERVED;; порядок элементов сохраняется. */ + PINT PIE5_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE6_RESERVED;; порядок элементов сохраняется. */ + PINT PIE6_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE7_RESERVED;; порядок элементов сохраняется. */ + PINT PIE7_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE8_RESERVED;; порядок элементов сохраняется. */ + PINT PIE8_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE9_RESERVED;; порядок элементов сохраняется. */ + PINT PIE9_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE10_RESERVED;; порядок элементов сохраняется. */ + PINT PIE10_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE11_RESERVED;; порядок элементов сохраняется. */ + PINT PIE11_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE12_RESERVED;; порядок элементов сохраняется. */ + PINT PIE12_RESERVED; + /* Продолжает список аргументов, полей или выражение PINT PIE13_RESERVED;; порядок элементов сохраняется. */ + PINT PIE13_RESERVED; + +// Non-Peripheral Interrupts: + /* Продолжает список аргументов, полей или выражение PINT XINT13;; порядок элементов сохраняется. */ + PINT XINT13; // XINT13 / CPU-Timer1 + /* Продолжает список аргументов, полей или выражение PINT TINT2;; порядок элементов сохраняется. */ + PINT TINT2; // CPU-Timer2 + /* Продолжает список аргументов, полей или выражение PINT DATALOG;; порядок элементов сохраняется. */ + PINT DATALOG; // Datalogging interrupt + /* Продолжает список аргументов, полей или выражение PINT RTOSINT;; порядок элементов сохраняется. */ + PINT RTOSINT; // RTOS interrupt + /* Продолжает список аргументов, полей или выражение PINT EMUINT;; порядок элементов сохраняется. */ + PINT EMUINT; // Emulation interrupt + /* Продолжает список аргументов, полей или выражение PINT XNMI;; порядок элементов сохраняется. */ + PINT XNMI; // Non-maskable interrupt + /* Продолжает список аргументов, полей или выражение PINT ILLEGAL;; порядок элементов сохраняется. */ + PINT ILLEGAL; // Illegal operation TRAP + /* Продолжает список аргументов, полей или выражение PINT USER1;; порядок элементов сохраняется. */ + PINT USER1; // User Defined trap 1 + /* Продолжает список аргументов, полей или выражение PINT USER2;; порядок элементов сохраняется. */ + PINT USER2; // User Defined trap 2 + /* Продолжает список аргументов, полей или выражение PINT USER3;; порядок элементов сохраняется. */ + PINT USER3; // User Defined trap 3 + /* Продолжает список аргументов, полей или выражение PINT USER4;; порядок элементов сохраняется. */ + PINT USER4; // User Defined trap 4 + /* Продолжает список аргументов, полей или выражение PINT USER5;; порядок элементов сохраняется. */ + PINT USER5; // User Defined trap 5 + /* Продолжает список аргументов, полей или выражение PINT USER6;; порядок элементов сохраняется. */ + PINT USER6; // User Defined trap 6 + /* Продолжает список аргументов, полей или выражение PINT USER7;; порядок элементов сохраняется. */ + PINT USER7; // User Defined trap 7 + /* Продолжает список аргументов, полей или выражение PINT USER8;; порядок элементов сохраняется. */ + PINT USER8; // User Defined trap 8 + /* Продолжает список аргументов, полей или выражение PINT USER9;; порядок элементов сохраняется. */ + PINT USER9; // User Defined trap 9 + /* Продолжает список аргументов, полей или выражение PINT USER10;; порядок элементов сохраняется. */ + PINT USER10; // User Defined trap 10 + /* Продолжает список аргументов, полей или выражение PINT USER11;; порядок элементов сохраняется. */ + PINT USER11; // User Defined trap 11 + /* Продолжает список аргументов, полей или выражение PINT USER12;; порядок элементов сохраняется. */ + PINT USER12; // User Defined trap 12 + +// Group 1 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT SEQ1INT;; порядок элементов сохраняется. */ + PINT SEQ1INT; + /* Продолжает список аргументов, полей или выражение PINT SEQ2INT;; порядок элементов сохраняется. */ + PINT SEQ2INT; + /* Продолжает список аргументов, полей или выражение PINT rsvd1_3;; порядок элементов сохраняется. */ + PINT rsvd1_3; + /* Продолжает список аргументов, полей или выражение PINT XINT1;; порядок элементов сохраняется. */ + PINT XINT1; + /* Продолжает список аргументов, полей или выражение PINT XINT2;; порядок элементов сохраняется. */ + PINT XINT2; + /* Продолжает список аргументов, полей или выражение PINT ADCINT;; порядок элементов сохраняется. */ + PINT ADCINT; // ADC + /* Продолжает список аргументов, полей или выражение PINT TINT0;; порядок элементов сохраняется. */ + PINT TINT0; // Timer 0 + /* Продолжает список аргументов, полей или выражение PINT WAKEINT;; порядок элементов сохраняется. */ + PINT WAKEINT; // WD + +// Group 2 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT EPWM1_TZINT;; порядок элементов сохраняется. */ + PINT EPWM1_TZINT; // EPWM-1 + /* Продолжает список аргументов, полей или выражение PINT EPWM2_TZINT;; порядок элементов сохраняется. */ + PINT EPWM2_TZINT; // EPWM-2 + /* Продолжает список аргументов, полей или выражение PINT EPWM3_TZINT;; порядок элементов сохраняется. */ + PINT EPWM3_TZINT; // EPWM-3 + /* Продолжает список аргументов, полей или выражение PINT EPWM4_TZINT;; порядок элементов сохраняется. */ + PINT EPWM4_TZINT; // EPWM-4 + /* Продолжает список аргументов, полей или выражение PINT EPWM5_TZINT;; порядок элементов сохраняется. */ + PINT EPWM5_TZINT; // EPWM-5 + /* Продолжает список аргументов, полей или выражение PINT EPWM6_TZINT;; порядок элементов сохраняется. */ + PINT EPWM6_TZINT; // EPWM-6 + /* Продолжает список аргументов, полей или выражение PINT rsvd2_7;; порядок элементов сохраняется. */ + PINT rsvd2_7; + /* Продолжает список аргументов, полей или выражение PINT rsvd2_8;; порядок элементов сохраняется. */ + PINT rsvd2_8; + +// Group 3 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT EPWM1_INT;; порядок элементов сохраняется. */ + PINT EPWM1_INT; // EPWM-1 + /* Продолжает список аргументов, полей или выражение PINT EPWM2_INT;; порядок элементов сохраняется. */ + PINT EPWM2_INT; // EPWM-2 + /* Продолжает список аргументов, полей или выражение PINT EPWM3_INT;; порядок элементов сохраняется. */ + PINT EPWM3_INT; // EPWM-3 + /* Продолжает список аргументов, полей или выражение PINT EPWM4_INT;; порядок элементов сохраняется. */ + PINT EPWM4_INT; // EPWM-4 + /* Продолжает список аргументов, полей или выражение PINT EPWM5_INT;; порядок элементов сохраняется. */ + PINT EPWM5_INT; // EPWM-5 + /* Продолжает список аргументов, полей или выражение PINT EPWM6_INT;; порядок элементов сохраняется. */ + PINT EPWM6_INT; // EPWM-6 + /* Продолжает список аргументов, полей или выражение PINT rsvd3_7;; порядок элементов сохраняется. */ + PINT rsvd3_7; + /* Продолжает список аргументов, полей или выражение PINT rsvd3_8;; порядок элементов сохраняется. */ + PINT rsvd3_8; + +// Group 4 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT ECAP1_INT;; порядок элементов сохраняется. */ + PINT ECAP1_INT; // ECAP-1 + /* Продолжает список аргументов, полей или выражение PINT ECAP2_INT;; порядок элементов сохраняется. */ + PINT ECAP2_INT; // ECAP-2 + /* Продолжает список аргументов, полей или выражение PINT ECAP3_INT;; порядок элементов сохраняется. */ + PINT ECAP3_INT; // ECAP-3 + /* Продолжает список аргументов, полей или выражение PINT ECAP4_INT;; порядок элементов сохраняется. */ + PINT ECAP4_INT; // ECAP-4 + /* Продолжает список аргументов, полей или выражение PINT ECAP5_INT;; порядок элементов сохраняется. */ + PINT ECAP5_INT; // ECAP-5 + /* Продолжает список аргументов, полей или выражение PINT ECAP6_INT;; порядок элементов сохраняется. */ + PINT ECAP6_INT; // ECAP-6 + /* Продолжает список аргументов, полей или выражение PINT rsvd4_7;; порядок элементов сохраняется. */ + PINT rsvd4_7; + /* Продолжает список аргументов, полей или выражение PINT rsvd4_8;; порядок элементов сохраняется. */ + PINT rsvd4_8; + +// Group 5 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT EQEP1_INT;; порядок элементов сохраняется. */ + PINT EQEP1_INT; // EQEP-1 + /* Продолжает список аргументов, полей или выражение PINT EQEP2_INT;; порядок элементов сохраняется. */ + PINT EQEP2_INT; // EQEP-2 + /* Продолжает список аргументов, полей или выражение PINT rsvd5_3;; порядок элементов сохраняется. */ + PINT rsvd5_3; + /* Продолжает список аргументов, полей или выражение PINT rsvd5_4;; порядок элементов сохраняется. */ + PINT rsvd5_4; + /* Продолжает список аргументов, полей или выражение PINT rsvd5_5;; порядок элементов сохраняется. */ + PINT rsvd5_5; + /* Продолжает список аргументов, полей или выражение PINT rsvd5_6;; порядок элементов сохраняется. */ + PINT rsvd5_6; + /* Продолжает список аргументов, полей или выражение PINT rsvd5_7;; порядок элементов сохраняется. */ + PINT rsvd5_7; + /* Продолжает список аргументов, полей или выражение PINT rsvd5_8;; порядок элементов сохраняется. */ + PINT rsvd5_8; + +// Group 6 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT SPIRXINTA;; порядок элементов сохраняется. */ + PINT SPIRXINTA; // SPI-A + /* Продолжает список аргументов, полей или выражение PINT SPITXINTA;; порядок элементов сохраняется. */ + PINT SPITXINTA; // SPI-A + /* Продолжает список аргументов, полей или выражение PINT MRINTB;; порядок элементов сохраняется. */ + PINT MRINTB; // McBSP-B + /* Продолжает список аргументов, полей или выражение PINT MXINTB;; порядок элементов сохраняется. */ + PINT MXINTB; // McBSP-B + /* Продолжает список аргументов, полей или выражение PINT MRINTA;; порядок элементов сохраняется. */ + PINT MRINTA; // McBSP-A + /* Продолжает список аргументов, полей или выражение PINT MXINTA;; порядок элементов сохраняется. */ + PINT MXINTA; // McBSP-A + /* Продолжает список аргументов, полей или выражение PINT rsvd6_7;; порядок элементов сохраняется. */ + PINT rsvd6_7; + /* Продолжает список аргументов, полей или выражение PINT rsvd6_8;; порядок элементов сохраняется. */ + PINT rsvd6_8; + +// Group 7 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT DINTCH1;; порядок элементов сохраняется. */ + PINT DINTCH1; // DMA + /* Продолжает список аргументов, полей или выражение PINT DINTCH2;; порядок элементов сохраняется. */ + PINT DINTCH2; // DMA + /* Продолжает список аргументов, полей или выражение PINT DINTCH3;; порядок элементов сохраняется. */ + PINT DINTCH3; // DMA + /* Продолжает список аргументов, полей или выражение PINT DINTCH4;; порядок элементов сохраняется. */ + PINT DINTCH4; // DMA + /* Продолжает список аргументов, полей или выражение PINT DINTCH5;; порядок элементов сохраняется. */ + PINT DINTCH5; // DMA + /* Продолжает список аргументов, полей или выражение PINT DINTCH6;; порядок элементов сохраняется. */ + PINT DINTCH6; // DMA + /* Продолжает список аргументов, полей или выражение PINT rsvd7_7;; порядок элементов сохраняется. */ + PINT rsvd7_7; + /* Продолжает список аргументов, полей или выражение PINT rsvd7_8;; порядок элементов сохраняется. */ + PINT rsvd7_8; + +// Group 8 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT I2CINT1A;; порядок элементов сохраняется. */ + PINT I2CINT1A; // I2C-A + /* Продолжает список аргументов, полей или выражение PINT I2CINT2A;; порядок элементов сохраняется. */ + PINT I2CINT2A; // I2C-A + /* Продолжает список аргументов, полей или выражение PINT rsvd8_3;; порядок элементов сохраняется. */ + PINT rsvd8_3; + /* Продолжает список аргументов, полей или выражение PINT rsvd8_4;; порядок элементов сохраняется. */ + PINT rsvd8_4; + /* Продолжает список аргументов, полей или выражение PINT SCIRXINTC;; порядок элементов сохраняется. */ + PINT SCIRXINTC; // SCI-C + /* Продолжает список аргументов, полей или выражение PINT SCITXINTC;; порядок элементов сохраняется. */ + PINT SCITXINTC; // SCI-C + /* Продолжает список аргументов, полей или выражение PINT rsvd8_7;; порядок элементов сохраняется. */ + PINT rsvd8_7; + /* Продолжает список аргументов, полей или выражение PINT rsvd8_8;; порядок элементов сохраняется. */ + PINT rsvd8_8; + +// Group 9 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT SCIRXINTA;; порядок элементов сохраняется. */ + PINT SCIRXINTA; // SCI-A + /* Продолжает список аргументов, полей или выражение PINT SCITXINTA;; порядок элементов сохраняется. */ + PINT SCITXINTA; // SCI-A + /* Продолжает список аргументов, полей или выражение PINT SCIRXINTB;; порядок элементов сохраняется. */ + PINT SCIRXINTB; // SCI-B + /* Продолжает список аргументов, полей или выражение PINT SCITXINTB;; порядок элементов сохраняется. */ + PINT SCITXINTB; // SCI-B + /* Продолжает список аргументов, полей или выражение PINT ECAN0INTA;; порядок элементов сохраняется. */ + PINT ECAN0INTA; // eCAN-A + /* Продолжает список аргументов, полей или выражение PINT ECAN1INTA;; порядок элементов сохраняется. */ + PINT ECAN1INTA; // eCAN-A + /* Продолжает список аргументов, полей или выражение PINT ECAN0INTB;; порядок элементов сохраняется. */ + PINT ECAN0INTB; // eCAN-B + /* Продолжает список аргументов, полей или выражение PINT ECAN1INTB;; порядок элементов сохраняется. */ + PINT ECAN1INTB; // eCAN-B + +// Group 10 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT rsvd10_1;; порядок элементов сохраняется. */ + PINT rsvd10_1; + /* Продолжает список аргументов, полей или выражение PINT rsvd10_2;; порядок элементов сохраняется. */ + PINT rsvd10_2; + /* Продолжает список аргументов, полей или выражение PINT rsvd10_3;; порядок элементов сохраняется. */ + PINT rsvd10_3; + /* Продолжает список аргументов, полей или выражение PINT rsvd10_4;; порядок элементов сохраняется. */ + PINT rsvd10_4; + /* Продолжает список аргументов, полей или выражение PINT rsvd10_5;; порядок элементов сохраняется. */ + PINT rsvd10_5; + /* Продолжает список аргументов, полей или выражение PINT rsvd10_6;; порядок элементов сохраняется. */ + PINT rsvd10_6; + /* Продолжает список аргументов, полей или выражение PINT rsvd10_7;; порядок элементов сохраняется. */ + PINT rsvd10_7; + /* Продолжает список аргументов, полей или выражение PINT rsvd10_8;; порядок элементов сохраняется. */ + PINT rsvd10_8; + +// Group 11 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT rsvd11_1;; порядок элементов сохраняется. */ + PINT rsvd11_1; + /* Продолжает список аргументов, полей или выражение PINT rsvd11_2;; порядок элементов сохраняется. */ + PINT rsvd11_2; + /* Продолжает список аргументов, полей или выражение PINT rsvd11_3;; порядок элементов сохраняется. */ + PINT rsvd11_3; + /* Продолжает список аргументов, полей или выражение PINT rsvd11_4;; порядок элементов сохраняется. */ + PINT rsvd11_4; + /* Продолжает список аргументов, полей или выражение PINT rsvd11_5;; порядок элементов сохраняется. */ + PINT rsvd11_5; + /* Продолжает список аргументов, полей или выражение PINT rsvd11_6;; порядок элементов сохраняется. */ + PINT rsvd11_6; + /* Продолжает список аргументов, полей или выражение PINT rsvd11_7;; порядок элементов сохраняется. */ + PINT rsvd11_7; + /* Продолжает список аргументов, полей или выражение PINT rsvd11_8;; порядок элементов сохраняется. */ + PINT rsvd11_8; + +// Group 12 PIE Peripheral Vectors: + /* Продолжает список аргументов, полей или выражение PINT XINT3;; порядок элементов сохраняется. */ + PINT XINT3; // External interrupt + /* Продолжает список аргументов, полей или выражение PINT XINT4;; порядок элементов сохраняется. */ + PINT XINT4; + /* Продолжает список аргументов, полей или выражение PINT XINT5;; порядок элементов сохраняется. */ + PINT XINT5; + /* Продолжает список аргументов, полей или выражение PINT XINT6;; порядок элементов сохраняется. */ + PINT XINT6; + /* Продолжает список аргументов, полей или выражение PINT XINT7;; порядок элементов сохраняется. */ + PINT XINT7; + /* Продолжает список аргументов, полей или выражение PINT rsvd12_6;; порядок элементов сохраняется. */ + PINT rsvd12_6; + /* Продолжает список аргументов, полей или выражение PINT LVF;; порядок элементов сохраняется. */ + PINT LVF; // Latched overflow + /* Продолжает список аргументов, полей или выражение PINT LUF;; порядок элементов сохраняется. */ + PINT LUF; // Latched underflow +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// PIE Interrupt Vector Table External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern struct PIE_VECT_TABLE PieVectTable;; порядок элементов сохраняется. */ +extern struct PIE_VECT_TABLE PieVectTable; + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_PIE_VECT_H definition + +//=========================================================================== +// End of file. +//=========================================================================== + diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Sci.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Sci.h new file mode 100644 index 0000000..83b5a65 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Sci.h @@ -0,0 +1,377 @@ +/* Поставляемое TI описание Sci для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/2 $ +// Checkin $Date: March 1, 2007 15:57:02 $ +//########################################################################### +// +// FILE: DSP2833x_Sci.h +// +// TITLE: DSP2833x Device SCI Register Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_SCI_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_SCI_H +/* Определяет защитный символ или переключатель DSP2833x_SCI_H для последующей компиляции. */ +#define DSP2833x_SCI_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +//--------------------------------------------------------------------------- +// SCI Individual Register Bit Definitions + +//---------------------------------------------------------- +// SCICCR communication control register bit definitions: +// + +/* Описывает структуру SCICCR_BITS; порядок полей определяет расположение данных. */ +struct SCICCR_BITS { // bit description + /* Битовое поле SCICHAR, ширина 3 бит; данные SCICHAR. */ + Uint16 SCICHAR:3; // 2:0 Character length control + /* Битовое поле ADDRIDLE_MODE, ширина 1 бит; ADDRIDLE режим. */ + Uint16 ADDRIDLE_MODE:1; // 3 ADDR/IDLE Mode control + /* Битовое поле LOOPBKENA, ширина 1 бит; данные LOOPBKENA. */ + Uint16 LOOPBKENA:1; // 4 Loop Back enable + /* Битовое поле PARITYENA, ширина 1 бит; данные PARITYENA. */ + Uint16 PARITYENA:1; // 5 Parity enable + /* Битовое поле PARITY, ширина 1 бит; чётность. */ + Uint16 PARITY:1; // 6 Even or Odd Parity + /* Битовое поле STOPBITS, ширина 1 бит; данные STOPBITS. */ + Uint16 STOPBITS:1; // 7 Number of Stop Bits + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Объединяет несколько представлений SCICCR_REG в одной области памяти. */ +union SCICCR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SCICCR_BITS bit;; порядок полей определяет расположение данных. */ + struct SCICCR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//------------------------------------------- +// SCICTL1 control register 1 bit definitions: +// + +/* Описывает структуру SCICTL1_BITS; порядок полей определяет расположение данных. */ +struct SCICTL1_BITS { // bit description + /* Битовое поле RXENA, ширина 1 бит; данные RXENA. */ + Uint16 RXENA:1; // 0 SCI receiver enable + /* Битовое поле TXENA, ширина 1 бит; данные TXENA. */ + Uint16 TXENA:1; // 1 SCI transmitter enable + /* Битовое поле SLEEP, ширина 1 бит; данные SLEEP. */ + Uint16 SLEEP:1; // 2 SCI sleep + /* Битовое поле TXWAKE, ширина 1 бит; данные TXWAKE. */ + Uint16 TXWAKE:1; // 3 Transmitter wakeup method + /* Битовое поле rsvd, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:1; // 4 reserved + /* Битовое поле SWRESET, ширина 1 бит; данные SWRESET. */ + Uint16 SWRESET:1; // 5 Software reset + /* Битовое поле RXERRINTENA, ширина 1 бит; данные RXERRINTENA. */ + Uint16 RXERRINTENA:1; // 6 Recieve interrupt enable + /* Битовое поле rsvd1, ширина 9 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:9; // 15:7 reserved + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SCICTL1_REG в одной области памяти. */ +union SCICTL1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SCICTL1_BITS bit;; порядок полей определяет расположение данных. */ + struct SCICTL1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------- +// SCICTL2 control register 2 bit definitions: +// + +/* Описывает структуру SCICTL2_BITS; порядок полей определяет расположение данных. */ +struct SCICTL2_BITS { // bit description + /* Битовое поле TXINTENA, ширина 1 бит; данные TXINTENA. */ + Uint16 TXINTENA:1; // 0 Transmit interrupt enable + /* Битовое поле RXBKINTENA, ширина 1 бит; данные RXBKINTENA. */ + Uint16 RXBKINTENA:1; // 1 Receiver-buffer break enable + /* Битовое поле rsvd, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:4; // 5:2 reserved + /* Битовое поле TXEMPTY, ширина 1 бит; данные TXEMPTY. */ + Uint16 TXEMPTY:1; // 6 Transmitter empty flag + /* Битовое поле TXRDY, ширина 1 бит; данные TXRDY. */ + Uint16 TXRDY:1; // 7 Transmitter ready flag + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 15:8 reserved + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SCICTL2_REG в одной области памяти. */ +union SCICTL2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SCICTL2_BITS bit;; порядок полей определяет расположение данных. */ + struct SCICTL2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------- +// SCIRXST Receiver status register bit definitions: +// + +/* Описывает структуру SCIRXST_BITS; порядок полей определяет расположение данных. */ +struct SCIRXST_BITS { // bit description + /* Битовое поле rsvd, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:1; // 0 reserved + /* Битовое поле RXWAKE, ширина 1 бит; данные RXWAKE. */ + Uint16 RXWAKE:1; // 1 Receiver wakeup detect flag + /* Битовое поле PE, ширина 1 бит; данные PE. */ + Uint16 PE:1; // 2 Parity error flag + /* Битовое поле OE, ширина 1 бит; данные OE. */ + Uint16 OE:1; // 3 Overrun error flag + /* Битовое поле FE, ширина 1 бит; данные FE. */ + Uint16 FE:1; // 4 Framing error flag + /* Битовое поле BRKDT, ширина 1 бит; данные BRKDT. */ + Uint16 BRKDT:1; // 5 Break-detect flag + /* Битовое поле RXRDY, ширина 1 бит; данные RXRDY. */ + Uint16 RXRDY:1; // 6 Receiver ready flag + /* Битовое поле RXERROR, ширина 1 бит; данные RXERROR. */ + Uint16 RXERROR:1; // 7 Receiver error flag + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SCIRXST_REG в одной области памяти. */ +union SCIRXST_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SCIRXST_BITS bit;; порядок полей определяет расположение данных. */ + struct SCIRXST_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//---------------------------------------------------- +// SCIRXBUF Receiver Data Buffer with FIFO bit definitions: +// + +/* Описывает структуру SCIRXBUF_BITS; порядок полей определяет расположение данных. */ +struct SCIRXBUF_BITS { // bits description + /* Битовое поле RXDT, ширина 8 бит; данные RXDT. */ + Uint16 RXDT:8; // 7:0 Receive word + /* Битовое поле rsvd, ширина 6 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:6; // 13:8 reserved + /* Битовое поле SCIFFPE, ширина 1 бит; данные SCIFFPE. */ + Uint16 SCIFFPE:1; // 14 SCI PE error in FIFO mode + /* Битовое поле SCIFFFE, ширина 1 бит; данные SCIFFFE. */ + Uint16 SCIFFFE:1; // 15 SCI FE error in FIFO mode +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SCIRXBUF_REG в одной области памяти. */ +union SCIRXBUF_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SCIRXBUF_BITS bit;; порядок полей определяет расположение данных. */ + struct SCIRXBUF_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//-------------------------------------------------- +// SCIPRI Priority control register bit definitions: +// +// + +/* Описывает структуру SCIPRI_BITS; порядок полей определяет расположение данных. */ +struct SCIPRI_BITS { // bit description + /* Битовое поле rsvd, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:3; // 2:0 reserved + /* Битовое поле FREE, ширина 1 бит; данные FREE. */ + Uint16 FREE:1; // 3 Free emulation suspend mode + /* Битовое поле SOFT, ширина 1 бит; данные SOFT. */ + Uint16 SOFT:1; // 4 Soft emulation suspend mode + /* Битовое поле rsvd1, ширина 3 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:3; // 7:5 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SCIPRI_REG в одной области памяти. */ +union SCIPRI_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SCIPRI_BITS bit;; порядок полей определяет расположение данных. */ + struct SCIPRI_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//------------------------------------------------- +// SCI FIFO Transmit register bit definitions: +// +// + +/* Описывает структуру SCIFFTX_BITS; порядок полей определяет расположение данных. */ +struct SCIFFTX_BITS { // bit description + /* Битовое поле TXFFIL, ширина 5 бит; данные TXFFIL. */ + Uint16 TXFFIL:5; // 4:0 Interrupt level + /* Битовое поле TXFFIENA, ширина 1 бит; данные TXFFIENA. */ + Uint16 TXFFIENA:1; // 5 Interrupt enable + /* Битовое поле TXFFINTCLR, ширина 1 бит; данные TXFFINTCLR. */ + Uint16 TXFFINTCLR:1; // 6 Clear INT flag + /* Битовое поле TXFFINT, ширина 1 бит; данные TXFFINT. */ + Uint16 TXFFINT:1; // 7 INT flag + /* Битовое поле TXFFST, ширина 5 бит; данные TXFFST. */ + Uint16 TXFFST:5; // 12:8 FIFO status + /* Битовое поле TXFIFOXRESET, ширина 1 бит; данные TXFIFOXRESET. */ + Uint16 TXFIFOXRESET:1; // 13 FIFO reset + /* Битовое поле SCIFFENA, ширина 1 бит; данные SCIFFENA. */ + Uint16 SCIFFENA:1; // 14 Enhancement enable + /* Битовое поле SCIRST, ширина 1 бит; данные SCIRST. */ + Uint16 SCIRST:1; // 15 SCI reset rx/tx channels + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SCIFFTX_REG в одной области памяти. */ +union SCIFFTX_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SCIFFTX_BITS bit;; порядок полей определяет расположение данных. */ + struct SCIFFTX_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//------------------------------------------------ +// SCI FIFO recieve register bit definitions: +// +// + +/* Описывает структуру SCIFFRX_BITS; порядок полей определяет расположение данных. */ +struct SCIFFRX_BITS { // bits description + /* Битовое поле RXFFIL, ширина 5 бит; данные RXFFIL. */ + Uint16 RXFFIL:5; // 4:0 Interrupt level + /* Битовое поле RXFFIENA, ширина 1 бит; данные RXFFIENA. */ + Uint16 RXFFIENA:1; // 5 Interrupt enable + /* Битовое поле RXFFINTCLR, ширина 1 бит; данные RXFFINTCLR. */ + Uint16 RXFFINTCLR:1; // 6 Clear INT flag + /* Битовое поле RXFFINT, ширина 1 бит; данные RXFFINT. */ + Uint16 RXFFINT:1; // 7 INT flag + /* Битовое поле RXFFST, ширина 5 бит; данные RXFFST. */ + Uint16 RXFFST:5; // 12:8 FIFO status + /* Битовое поле RXFIFORESET, ширина 1 бит; данные RXFIFORESET. */ + Uint16 RXFIFORESET:1; // 13 FIFO reset + /* Битовое поле RXFFOVRCLR, ширина 1 бит; данные RXFFOVRCLR. */ + Uint16 RXFFOVRCLR:1; // 14 Clear overflow + /* Битовое поле RXFFOVF, ширина 1 бит; данные RXFFOVF. */ + Uint16 RXFFOVF:1; // 15 FIFO overflow + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SCIFFRX_REG в одной области памяти. */ +union SCIFFRX_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SCIFFRX_BITS bit;; порядок полей определяет расположение данных. */ + struct SCIFFRX_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// SCI FIFO control register bit definitions: +/* Описывает структуру SCIFFCT_BITS; порядок полей определяет расположение данных. */ +struct SCIFFCT_BITS { // bits description + /* Битовое поле FFTXDLY, ширина 8 бит; данные FFTXDLY. */ + Uint16 FFTXDLY:8; // 7:0 FIFO transmit delay + /* Битовое поле rsvd, ширина 5 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:5; // 12:8 reserved + /* Битовое поле CDC, ширина 1 бит; данные CDC. */ + Uint16 CDC:1; // 13 Auto baud mode enable + /* Битовое поле ABDCLR, ширина 1 бит; данные ABDCLR. */ + Uint16 ABDCLR:1; // 14 Auto baud clear + /* Битовое поле ABD, ширина 1 бит; данные ABD. */ + Uint16 ABD:1; // 15 Auto baud detect +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SCIFFCT_REG в одной области памяти. */ +union SCIFFCT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SCIFFCT_BITS bit;; порядок полей определяет расположение данных. */ + struct SCIFFCT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// SCI Register File: +// +/* Описывает структуру SCI_REGS; порядок полей определяет расположение данных. */ +struct SCI_REGS { + /* Объединяет несколько представлений SCICCR_REG SCICCR; в одной области памяти. */ + union SCICCR_REG SCICCR; // Communications control register + /* Объединяет несколько представлений SCICTL1_REG SCICTL1; в одной области памяти. */ + union SCICTL1_REG SCICTL1; // Control register 1 + /* Объявляет SCIHBAUD — данные SCIHBAUD. */ + Uint16 SCIHBAUD; // Baud rate (high) register + /* Объявляет SCILBAUD — данные SCILBAUD. */ + Uint16 SCILBAUD; // Baud rate (low) register + /* Объединяет несколько представлений SCICTL2_REG SCICTL2; в одной области памяти. */ + union SCICTL2_REG SCICTL2; // Control register 2 + /* Объединяет несколько представлений SCIRXST_REG SCIRXST; в одной области памяти. */ + union SCIRXST_REG SCIRXST; // Recieve status register + /* Объявляет SCIRXEMU — данные SCIRXEMU. */ + Uint16 SCIRXEMU; // Recieve emulation buffer register + /* Объединяет несколько представлений SCIRXBUF_REG SCIRXBUF; в одной области памяти. */ + union SCIRXBUF_REG SCIRXBUF; // Recieve data buffer + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1; // reserved + /* Объявляет SCITXBUF — данные SCITXBUF. */ + Uint16 SCITXBUF; // Transmit data buffer + /* Объединяет несколько представлений SCIFFTX_REG SCIFFTX; в одной области памяти. */ + union SCIFFTX_REG SCIFFTX; // FIFO transmit register + /* Объединяет несколько представлений SCIFFRX_REG SCIFFRX; в одной области памяти. */ + union SCIFFRX_REG SCIFFRX; // FIFO recieve register + /* Объединяет несколько представлений SCIFFCT_REG SCIFFCT; в одной области памяти. */ + union SCIFFCT_REG SCIFFCT; // FIFO control register + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2; // reserved + /* Объявляет rsvd3 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3; // reserved + /* Объединяет несколько представлений SCIPRI_REG SCIPRI; в одной области памяти. */ + union SCIPRI_REG SCIPRI; // FIFO Priority control +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// SCI External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct SCI_REGS SciaRegs;; порядок элементов сохраняется. */ +extern volatile struct SCI_REGS SciaRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct SCI_REGS ScibRegs;; порядок элементов сохраняется. */ +extern volatile struct SCI_REGS ScibRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct SCI_REGS ScicRegs;; порядок элементов сохраняется. */ +extern volatile struct SCI_REGS ScicRegs; + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_SCI_H definition + +//=========================================================================== +// End of file. +//=========================================================================== + diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Spi.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Spi.h new file mode 100644 index 0000000..cdce516 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Spi.h @@ -0,0 +1,292 @@ +/* Поставляемое TI описание Spi для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/3 $ +// Checkin $Date: April 17, 2008 11:08:27 $ +//########################################################################### +// +// FILE: DSP2833x_Spi.h +// +// TITLE: DSP2833x Device SPI Register Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_SPI_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_SPI_H +/* Определяет защитный символ или переключатель DSP2833x_SPI_H для последующей компиляции. */ +#define DSP2833x_SPI_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +//--------------------------------------------------------------------------- +// SPI Individual Register Bit Definitions: +// +// SPI FIFO Transmit register bit definitions: +/* Описывает структуру SPIFFTX_BITS; порядок полей определяет расположение данных. */ +struct SPIFFTX_BITS { // bit description + /* Битовое поле TXFFIL, ширина 5 бит; данные TXFFIL. */ + Uint16 TXFFIL:5; // 4:0 Interrupt level + /* Битовое поле TXFFIENA, ширина 1 бит; данные TXFFIENA. */ + Uint16 TXFFIENA:1; // 5 Interrupt enable + /* Битовое поле TXFFINTCLR, ширина 1 бит; данные TXFFINTCLR. */ + Uint16 TXFFINTCLR:1; // 6 Clear INT flag + /* Битовое поле TXFFINT, ширина 1 бит; данные TXFFINT. */ + Uint16 TXFFINT:1; // 7 INT flag + /* Битовое поле TXFFST, ширина 5 бит; данные TXFFST. */ + Uint16 TXFFST:5; // 12:8 FIFO status + /* Битовое поле TXFIFO, ширина 1 бит; данные TXFIFO. */ + Uint16 TXFIFO:1; // 13 FIFO reset + /* Битовое поле SPIFFENA, ширина 1 бит; данные SPIFFENA. */ + Uint16 SPIFFENA:1; // 14 Enhancement enable + /* Битовое поле SPIRST, ширина 1 бит; данные SPIRST. */ + Uint16 SPIRST:1; // 15 Reset SPI +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SPIFFTX_REG в одной области памяти. */ +union SPIFFTX_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SPIFFTX_BITS bit;; порядок полей определяет расположение данных. */ + struct SPIFFTX_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//-------------------------------------------- +// SPI FIFO recieve register bit definitions: +// +// +/* Описывает структуру SPIFFRX_BITS; порядок полей определяет расположение данных. */ +struct SPIFFRX_BITS { // bits description + /* Битовое поле RXFFIL, ширина 5 бит; данные RXFFIL. */ + Uint16 RXFFIL:5; // 4:0 Interrupt level + /* Битовое поле RXFFIENA, ширина 1 бит; данные RXFFIENA. */ + Uint16 RXFFIENA:1; // 5 Interrupt enable + /* Битовое поле RXFFINTCLR, ширина 1 бит; данные RXFFINTCLR. */ + Uint16 RXFFINTCLR:1; // 6 Clear INT flag + /* Битовое поле RXFFINT, ширина 1 бит; данные RXFFINT. */ + Uint16 RXFFINT:1; // 7 INT flag + /* Битовое поле RXFFST, ширина 5 бит; данные RXFFST. */ + Uint16 RXFFST:5; // 12:8 FIFO status + /* Битовое поле RXFIFORESET, ширина 1 бит; данные RXFIFORESET. */ + Uint16 RXFIFORESET:1; // 13 FIFO reset + /* Битовое поле RXFFOVFCLR, ширина 1 бит; данные RXFFOVFCLR. */ + Uint16 RXFFOVFCLR:1; // 14 Clear overflow + /* Битовое поле RXFFOVF, ширина 1 бит; данные RXFFOVF. */ + Uint16 RXFFOVF:1; // 15 FIFO overflow + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SPIFFRX_REG в одной области памяти. */ +union SPIFFRX_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SPIFFRX_BITS bit;; порядок полей определяет расположение данных. */ + struct SPIFFRX_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//-------------------------------------------- +// SPI FIFO control register bit definitions: +// +// +/* Описывает структуру SPIFFCT_BITS; порядок полей определяет расположение данных. */ +struct SPIFFCT_BITS { // bits description + /* Битовое поле TXDLY, ширина 8 бит; данные TXDLY. */ + Uint16 TXDLY:8; // 7:0 FIFO transmit delay + /* Битовое поле rsvd, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SPIFFCT_REG в одной области памяти. */ +union SPIFFCT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SPIFFCT_BITS bit;; порядок полей определяет расположение данных. */ + struct SPIFFCT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------- +// SPI configuration register bit definitions: +// +// +/* Описывает структуру SPICCR_BITS; порядок полей определяет расположение данных. */ +struct SPICCR_BITS { // bits description + /* Битовое поле SPICHAR, ширина 4 бит; данные SPICHAR. */ + Uint16 SPICHAR:4; // 3:0 Character length control + /* Битовое поле SPILBK, ширина 1 бит; данные SPILBK. */ + Uint16 SPILBK:1; // 4 Loop-back enable/disable + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 5 reserved + /* Битовое поле CLKPOLARITY, ширина 1 бит; данные CLKPOLARITY. */ + Uint16 CLKPOLARITY:1; // 6 Clock polarity + /* Битовое поле SPISWRESET, ширина 1 бит; данные SPISWRESET. */ + Uint16 SPISWRESET:1; // 7 SPI SW Reset + /* Битовое поле rsvd2, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SPICCR_REG в одной области памяти. */ +union SPICCR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SPICCR_BITS bit;; порядок полей определяет расположение данных. */ + struct SPICCR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//------------------------------------------------- +// SPI operation control register bit definitions: +// +// +/* Описывает структуру SPICTL_BITS; порядок полей определяет расположение данных. */ +struct SPICTL_BITS { // bits description + /* Битовое поле SPIINTENA, ширина 1 бит; данные SPIINTENA. */ + Uint16 SPIINTENA:1; // 0 Interrupt enable + /* Битовое поле TALK, ширина 1 бит; данные TALK. */ + Uint16 TALK:1; // 1 Master/Slave transmit enable + /* Битовое поле MASTER_SLAVE, ширина 1 бит; данные MASTER_SLAVE. */ + Uint16 MASTER_SLAVE:1; // 2 Network control mode + /* Битовое поле CLK_PHASE, ширина 1 бит; CLK фаза. */ + Uint16 CLK_PHASE:1; // 3 Clock phase select + /* Битовое поле OVERRUNINTENA, ширина 1 бит; данные OVERRUNINTENA. */ + Uint16 OVERRUNINTENA:1; // 4 Overrun interrupt enable + /* Битовое поле rsvd, ширина 11 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:11; // 15:5 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SPICTL_REG в одной области памяти. */ +union SPICTL_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SPICTL_BITS bit;; порядок полей определяет расположение данных. */ + struct SPICTL_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//-------------------------------------- +// SPI status register bit definitions: +// +// +/* Описывает структуру SPISTS_BITS; порядок полей определяет расположение данных. */ +struct SPISTS_BITS { // bits description + /* Битовое поле rsvd1, ширина 5 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:5; // 4:0 reserved + /* Битовое поле BUFFULL_FLAG, ширина 1 бит; BUFFULL флаг. */ + Uint16 BUFFULL_FLAG:1; // 5 SPI transmit buffer full flag + /* Битовое поле INT_FLAG, ширина 1 бит; INT флаг. */ + Uint16 INT_FLAG:1; // 6 SPI interrupt flag + /* Битовое поле OVERRUN_FLAG, ширина 1 бит; OVERRUN флаг. */ + Uint16 OVERRUN_FLAG:1; // 7 SPI reciever overrun flag + /* Битовое поле rsvd2, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:8; // 15:8 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SPISTS_REG в одной области памяти. */ +union SPISTS_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SPISTS_BITS bit;; порядок полей определяет расположение данных. */ + struct SPISTS_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//------------------------------------------------ +// SPI priority control register bit definitions: +// +// +/* Описывает структуру SPIPRI_BITS; порядок полей определяет расположение данных. */ +struct SPIPRI_BITS { // bits description + /* Битовое поле rsvd1, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:4; // 3:0 reserved + /* Битовое поле FREE, ширина 1 бит; данные FREE. */ + Uint16 FREE:1; // 4 Free emulation mode control + /* Битовое поле SOFT, ширина 1 бит; данные SOFT. */ + Uint16 SOFT:1; // 5 Soft emulation mode control + /* Битовое поле rsvd2, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:1; // 6 reserved + /* Битовое поле rsvd3, ширина 9 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:9; // 15:7 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений SPIPRI_REG в одной области памяти. */ +union SPIPRI_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру SPIPRI_BITS bit;; порядок полей определяет расположение данных. */ + struct SPIPRI_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// SPI Register File: +// +/* Описывает структуру SPI_REGS; порядок полей определяет расположение данных. */ +struct SPI_REGS { + /* Объединяет несколько представлений SPICCR_REG SPICCR; в одной области памяти. */ + union SPICCR_REG SPICCR; // Configuration register + /* Объединяет несколько представлений SPICTL_REG SPICTL; в одной области памяти. */ + union SPICTL_REG SPICTL; // Operation control register + /* Объединяет несколько представлений SPISTS_REG SPISTS; в одной области памяти. */ + union SPISTS_REG SPISTS; // Status register + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1; // reserved + /* Объявляет SPIBRR — данные SPIBRR. */ + Uint16 SPIBRR; // Baud Rate + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2; // reserved + /* Объявляет SPIRXEMU — данные SPIRXEMU. */ + Uint16 SPIRXEMU; // Emulation buffer + /* Объявляет SPIRXBUF — данные SPIRXBUF. */ + Uint16 SPIRXBUF; // Serial input buffer + /* Объявляет SPITXBUF — данные SPITXBUF. */ + Uint16 SPITXBUF; // Serial output buffer + /* Объявляет SPIDAT — данные SPIDAT. */ + Uint16 SPIDAT; // Serial data + /* Объединяет несколько представлений SPIFFTX_REG SPIFFTX; в одной области памяти. */ + union SPIFFTX_REG SPIFFTX; // FIFO transmit register + /* Объединяет несколько представлений SPIFFRX_REG SPIFFRX; в одной области памяти. */ + union SPIFFRX_REG SPIFFRX; // FIFO recieve register + /* Объединяет несколько представлений SPIFFCT_REG SPIFFCT; в одной области памяти. */ + union SPIFFCT_REG SPIFFCT; // FIFO control register + /* Объявляет rsvd3 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3[2]; // reserved + /* Объединяет несколько представлений SPIPRI_REG SPIPRI; в одной области памяти. */ + union SPIPRI_REG SPIPRI; // FIFO Priority control +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// SPI External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct SPI_REGS SpiaRegs;; порядок элементов сохраняется. */ +extern volatile struct SPI_REGS SpiaRegs; + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_SPI_H definition + +//=========================================================================== +// End of file. +//=========================================================================== + diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_SysCtrl.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_SysCtrl.h new file mode 100644 index 0000000..0ab964e --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_SysCtrl.h @@ -0,0 +1,642 @@ +/* Поставляемое TI описание SysCtrl для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/5 $ +// Checkin $Date: May 12, 2008 09:34:58 $ +//########################################################################### +// +// FILE: DSP2833x_SysCtrl.h +// +// TITLE: DSP2833x Device System Control Register Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_SYS_CTRL_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_SYS_CTRL_H +/* Определяет защитный символ или переключатель DSP2833x_SYS_CTRL_H для последующей компиляции. */ +#define DSP2833x_SYS_CTRL_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +//--------------------------------------------------------------------------- +// System Control Individual Register Bit Definitions: +// + + +// PLL Status Register +/* Описывает структуру PLLSTS_BITS; порядок полей определяет расположение данных. */ +struct PLLSTS_BITS { // bits description + /* Битовое поле PLLLOCKS, ширина 1 бит; данные PLLLOCKS. */ + Uint16 PLLLOCKS:1; // 0 PLL lock status + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 1 reserved + /* Битовое поле PLLOFF, ширина 1 бит; данные PLLOFF. */ + Uint16 PLLOFF:1; // 2 PLL off bit + /* Битовое поле MCLKSTS, ширина 1 бит; данные MCLKSTS. */ + Uint16 MCLKSTS:1; // 3 Missing clock status bit + /* Битовое поле MCLKCLR, ширина 1 бит; данные MCLKCLR. */ + Uint16 MCLKCLR:1; // 4 Missing clock clear bit + /* Битовое поле OSCOFF, ширина 1 бит; данные OSCOFF. */ + Uint16 OSCOFF:1; // 5 Oscillator clock off + /* Битовое поле MCLKOFF, ширина 1 бит; данные MCLKOFF. */ + Uint16 MCLKOFF:1; // 6 Missing clock detect + /* Битовое поле DIVSEL, ширина 2 бит; данные DIVSEL. */ + Uint16 DIVSEL:2; // 7 Divide Select + /* Битовое поле rsvd2, ширина 7 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:7; // 15:7 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PLLSTS_REG в одной области памяти. */ +union PLLSTS_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PLLSTS_BITS bit;; порядок полей определяет расположение данных. */ + struct PLLSTS_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// High speed peripheral clock register bit definitions: +/* Описывает структуру HISPCP_BITS; порядок полей определяет расположение данных. */ +struct HISPCP_BITS { // bits description + /* Битовое поле HSPCLK, ширина 3 бит; данные HSPCLK. */ + Uint16 HSPCLK:3; // 2:0 Rate relative to SYSCLKOUT + /* Битовое поле rsvd1, ширина 13 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:13; // 15:3 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений HISPCP_REG в одной области памяти. */ +union HISPCP_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру HISPCP_BITS bit;; порядок полей определяет расположение данных. */ + struct HISPCP_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// Low speed peripheral clock register bit definitions: +/* Описывает структуру LOSPCP_BITS; порядок полей определяет расположение данных. */ +struct LOSPCP_BITS { // bits description + /* Битовое поле LSPCLK, ширина 3 бит; данные LSPCLK. */ + Uint16 LSPCLK:3; // 2:0 Rate relative to SYSCLKOUT + /* Битовое поле rsvd1, ширина 13 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:13; // 15:3 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений LOSPCP_REG в одной области памяти. */ +union LOSPCP_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру LOSPCP_BITS bit;; порядок полей определяет расположение данных. */ + struct LOSPCP_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// Peripheral clock control register 0 bit definitions: +/* Описывает структуру PCLKCR0_BITS; порядок полей определяет расположение данных. */ +struct PCLKCR0_BITS { // bits description + /* Битовое поле rsvd1, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:2; // 1:0 reserved + /* Битовое поле TBCLKSYNC, ширина 1 бит; данные TBCLKSYNC. */ + Uint16 TBCLKSYNC:1; // 2 EWPM Module TBCLK enable/sync + /* Битовое поле ADCENCLK, ширина 1 бит; данные ADCENCLK. */ + Uint16 ADCENCLK:1; // 3 Enable high speed clk to ADC + /* Битовое поле I2CAENCLK, ширина 1 бит; данные I2CAENCLK. */ + Uint16 I2CAENCLK:1; // 4 Enable SYSCLKOUT to I2C-A + /* Битовое поле SCICENCLK, ширина 1 бит; данные SCICENCLK. */ + Uint16 SCICENCLK:1; // 5 Enalbe low speed clk to SCI-C + /* Битовое поле rsvd2, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:2; // 7:6 reserved + /* Битовое поле SPIAENCLK, ширина 1 бит; данные SPIAENCLK. */ + Uint16 SPIAENCLK:1; // 8 Enable low speed clk to SPI-A + /* Битовое поле rsvd3, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:1; // 9 reserved + /* Битовое поле SCIAENCLK, ширина 1 бит; данные SCIAENCLK. */ + Uint16 SCIAENCLK:1; // 10 Enable low speed clk to SCI-A + /* Битовое поле SCIBENCLK, ширина 1 бит; данные SCIBENCLK. */ + Uint16 SCIBENCLK:1; // 11 Enable low speed clk to SCI-B + /* Битовое поле MCBSPAENCLK, ширина 1 бит; данные MCBSPAENCLK. */ + Uint16 MCBSPAENCLK:1; // 12 Enable low speed clk to McBSP-A + /* Битовое поле MCBSPBENCLK, ширина 1 бит; данные MCBSPBENCLK. */ + Uint16 MCBSPBENCLK:1; // 13 Enable low speed clk to McBSP-B + /* Битовое поле ECANAENCLK, ширина 1 бит; данные ECANAENCLK. */ + Uint16 ECANAENCLK:1; // 14 Enable system clk to eCAN-A + /* Битовое поле ECANBENCLK, ширина 1 бит; данные ECANBENCLK. */ + Uint16 ECANBENCLK:1; // 15 Enable system clk to eCAN-B +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PCLKCR0_REG в одной области памяти. */ +union PCLKCR0_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PCLKCR0_BITS bit;; порядок полей определяет расположение данных. */ + struct PCLKCR0_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// Peripheral clock control register 1 bit definitions: +/* Описывает структуру PCLKCR1_BITS; порядок полей определяет расположение данных. */ +struct PCLKCR1_BITS { // bits description + /* Битовое поле EPWM1ENCLK, ширина 1 бит; данные EPWM1ENCLK. */ + Uint16 EPWM1ENCLK:1; // 0 Enable SYSCLKOUT to EPWM1 + /* Битовое поле EPWM2ENCLK, ширина 1 бит; данные EPWM2ENCLK. */ + Uint16 EPWM2ENCLK:1; // 1 Enable SYSCLKOUT to EPWM2 + /* Битовое поле EPWM3ENCLK, ширина 1 бит; данные EPWM3ENCLK. */ + Uint16 EPWM3ENCLK:1; // 2 Enable SYSCLKOUT to EPWM3 + /* Битовое поле EPWM4ENCLK, ширина 1 бит; данные EPWM4ENCLK. */ + Uint16 EPWM4ENCLK:1; // 3 Enable SYSCLKOUT to EPWM4 + /* Битовое поле EPWM5ENCLK, ширина 1 бит; данные EPWM5ENCLK. */ + Uint16 EPWM5ENCLK:1; // 4 Enable SYSCLKOUT to EPWM5 + /* Битовое поле EPWM6ENCLK, ширина 1 бит; данные EPWM6ENCLK. */ + Uint16 EPWM6ENCLK:1; // 5 Enable SYSCLKOUT to EPWM6 + /* Битовое поле rsvd1, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:2; // 7:6 reserved + /* Битовое поле ECAP1ENCLK, ширина 1 бит; данные ECAP1ENCLK. */ + Uint16 ECAP1ENCLK:1; // 8 Enable SYSCLKOUT to ECAP1 + /* Битовое поле ECAP2ENCLK, ширина 1 бит; данные ECAP2ENCLK. */ + Uint16 ECAP2ENCLK:1; // 9 Enable SYSCLKOUT to ECAP2 + /* Битовое поле ECAP3ENCLK, ширина 1 бит; данные ECAP3ENCLK. */ + Uint16 ECAP3ENCLK:1; // 10 Enable SYSCLKOUT to ECAP3 + /* Битовое поле ECAP4ENCLK, ширина 1 бит; данные ECAP4ENCLK. */ + Uint16 ECAP4ENCLK:1; // 11 Enable SYSCLKOUT to ECAP4 + /* Битовое поле ECAP5ENCLK, ширина 1 бит; данные ECAP5ENCLK. */ + Uint16 ECAP5ENCLK:1; // 12 Enable SYSCLKOUT to ECAP5 + /* Битовое поле ECAP6ENCLK, ширина 1 бит; данные ECAP6ENCLK. */ + Uint16 ECAP6ENCLK:1; // 13 Enable SYSCLKOUT to ECAP6 + /* Битовое поле EQEP1ENCLK, ширина 1 бит; данные EQEP1ENCLK. */ + Uint16 EQEP1ENCLK:1; // 14 Enable SYSCLKOUT to EQEP1 + /* Битовое поле EQEP2ENCLK, ширина 1 бит; данные EQEP2ENCLK. */ + Uint16 EQEP2ENCLK:1; // 15 Enable SYSCLKOUT to EQEP2 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PCLKCR1_REG в одной области памяти. */ +union PCLKCR1_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PCLKCR1_BITS bit;; порядок полей определяет расположение данных. */ + struct PCLKCR1_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +// Peripheral clock control register 2 bit definitions: +/* Описывает структуру PCLKCR3_BITS; порядок полей определяет расположение данных. */ +struct PCLKCR3_BITS { // bits description + /* Битовое поле rsvd1, ширина 8 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:8; // 7:0 reserved + /* Битовое поле CPUTIMER0ENCLK, ширина 1 бит; данные CPUTIMER0ENCLK. */ + Uint16 CPUTIMER0ENCLK:1; // 8 Enable SYSCLKOUT to CPU-Timer 0 + /* Битовое поле CPUTIMER1ENCLK, ширина 1 бит; данные CPUTIMER1ENCLK. */ + Uint16 CPUTIMER1ENCLK:1; // 9 Enable SYSCLKOUT to CPU-Timer 1 + /* Битовое поле CPUTIMER2ENCLK, ширина 1 бит; данные CPUTIMER2ENCLK. */ + Uint16 CPUTIMER2ENCLK:1; // 10 Enable SYSCLKOUT to CPU-Timer 2 + /* Битовое поле DMAENCLK, ширина 1 бит; данные DMAENCLK. */ + Uint16 DMAENCLK:1; // 11 Enable the DMA clock + /* Битовое поле XINTFENCLK, ширина 1 бит; данные XINTFENCLK. */ + Uint16 XINTFENCLK:1; // 12 Enable SYSCLKOUT to XINTF + /* Битовое поле GPIOINENCLK, ширина 1 бит; аппаратная линия ввода/вывода GPIOINENCLK. */ + Uint16 GPIOINENCLK:1; // Enable GPIO input clock + /* Битовое поле rsvd2, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:2; // 15:14 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PCLKCR3_REG в одной области памяти. */ +union PCLKCR3_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PCLKCR3_BITS bit;; порядок полей определяет расположение данных. */ + struct PCLKCR3_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + +// PLL control register bit definitions: +/* Описывает структуру PLLCR_BITS; порядок полей определяет расположение данных. */ +struct PLLCR_BITS { // bits description + /* Битовое поле DIV, ширина 4 бит; данные DIV. */ + Uint16 DIV:4; // 3:0 Set clock ratio for the PLL + /* Битовое поле rsvd1, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:12; // 15:4 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений PLLCR_REG в одной области памяти. */ +union PLLCR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру PLLCR_BITS bit;; порядок полей определяет расположение данных. */ + struct PLLCR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// Low Power Mode 0 control register bit definitions: +/* Описывает структуру LPMCR0_BITS; порядок полей определяет расположение данных. */ +struct LPMCR0_BITS { // bits description + /* Битовое поле LPM, ширина 2 бит; данные LPM. */ + Uint16 LPM:2; // 1:0 Set the low power mode + /* Битовое поле QUALSTDBY, ширина 6 бит; данные QUALSTDBY. */ + Uint16 QUALSTDBY:6; // 7:2 Qualification + /* Битовое поле rsvd1, ширина 7 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:7; // 14:8 reserved + /* Битовое поле WDINTE, ширина 1 бит; данные WDINTE. */ + Uint16 WDINTE:1; // 15 Enables WD to wake the device from STANDBY +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений LPMCR0_REG в одной области памяти. */ +union LPMCR0_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру LPMCR0_BITS bit;; порядок полей определяет расположение данных. */ + struct LPMCR0_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// Dual-mapping configuration register bit definitions: +/* Описывает структуру MAPCNF_BITS; порядок полей определяет расположение данных. */ +struct MAPCNF_BITS { // bits description + /* Битовое поле MAPEPWM, ширина 1 бит; данные MAPEPWM. */ + Uint16 MAPEPWM:1; // 0 EPWM dual-map enable + /* Битовое поле rsvd1, ширина 15 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:15; // 15:1 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений MAPCNF_REG в одной области памяти. */ +union MAPCNF_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру MAPCNF_BITS bit;; порядок полей определяет расположение данных. */ + struct MAPCNF_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// System Control Register File: +// +/* Описывает структуру SYS_CTRL_REGS; порядок полей определяет расположение данных. */ +struct SYS_CTRL_REGS { + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1; // 0 + /* Объединяет несколько представлений PLLSTS_REG PLLSTS; в одной области памяти. */ + union PLLSTS_REG PLLSTS; // 1 + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2[8]; // 2-9 + /* Объединяет несколько представлений HISPCP_REG HISPCP; в одной области памяти. */ + union HISPCP_REG HISPCP; // 10: High-speed peripheral clock pre-scaler + /* Объединяет несколько представлений LOSPCP_REG LOSPCP; в одной области памяти. */ + union LOSPCP_REG LOSPCP; // 11: Low-speed peripheral clock pre-scaler + /* Объединяет несколько представлений PCLKCR0_REG PCLKCR0; в одной области памяти. */ + union PCLKCR0_REG PCLKCR0; // 12: Peripheral clock control register + /* Объединяет несколько представлений PCLKCR1_REG PCLKCR1; в одной области памяти. */ + union PCLKCR1_REG PCLKCR1; // 13: Peripheral clock control register + /* Объединяет несколько представлений LPMCR0_REG LPMCR0; в одной области памяти. */ + union LPMCR0_REG LPMCR0; // 14: Low-power mode control register 0 + /* Объявляет rsvd3 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3; // 15: reserved + /* Объединяет несколько представлений PCLKCR3_REG PCLKCR3; в одной области памяти. */ + union PCLKCR3_REG PCLKCR3; // 16: Peripheral clock control register + /* Объединяет несколько представлений PLLCR_REG PLLCR; в одной области памяти. */ + union PLLCR_REG PLLCR; // 17: PLL control register + // No bit definitions are defined for SCSR because + // a read-modify-write instruction can clear the WDOVERRIDE bit + /* Объявляет SCSR — данные SCSR. */ + Uint16 SCSR; // 18: System control and status register + /* Объявляет WDCNTR — данные WDCNTR. */ + Uint16 WDCNTR; // 19: WD counter register + /* Объявляет rsvd4 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd4; // 20 + /* Объявляет WDKEY — данные WDKEY. */ + Uint16 WDKEY; // 21: WD reset key register + /* Объявляет rsvd5 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd5[3]; // 22-24 + // No bit definitions are defined for WDCR because + // the proper value must be written to the WDCHK field + // whenever writing to this register. + /* Объявляет WDCR — данные WDCR. */ + Uint16 WDCR; // 25: WD timer control register + /* Объявляет rsvd6 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd6[4]; // 26-29 + /* Объединяет несколько представлений MAPCNF_REG MAPCNF; в одной области памяти. */ + union MAPCNF_REG MAPCNF; // 30: Dual-mapping configuration register + /* Объявляет rsvd7 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd7[1]; // 31 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* --------------------------------------------------- */ +/* CSM Registers */ +/* */ +/* ----------------------------------------------------*/ + +/* CSM Status & Control register bit definitions */ +/* Описывает структуру CSMSCR_BITS; порядок полей определяет расположение данных. */ +struct CSMSCR_BITS { // bit description + /* Битовое поле SECURE, ширина 1 бит; данные SECURE. */ + Uint16 SECURE:1; // 0 Secure flag + /* Битовое поле rsvd1, ширина 14 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:14; // 14-1 reserved + /* Битовое поле FORCESEC, ширина 1 бит; данные FORCESEC. */ + Uint16 FORCESEC:1; // 15 Force Secure control bit + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений CSMSCR_REG в одной области памяти. */ +union CSMSCR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру CSMSCR_BITS bit;; порядок полей определяет расположение данных. */ + struct CSMSCR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* CSM Register File */ +/* Описывает структуру CSM_REGS; порядок полей определяет расположение данных. */ +struct CSM_REGS { + /* Объявляет KEY0 — данные KEY0. */ + Uint16 KEY0; // KEY reg bits 15-0 + /* Объявляет KEY1 — данные KEY1. */ + Uint16 KEY1; // KEY reg bits 31-16 + /* Объявляет KEY2 — данные KEY2. */ + Uint16 KEY2; // KEY reg bits 47-32 + /* Объявляет KEY3 — данные KEY3. */ + Uint16 KEY3; // KEY reg bits 63-48 + /* Объявляет KEY4 — данные KEY4. */ + Uint16 KEY4; // KEY reg bits 79-64 + /* Объявляет KEY5 — данные KEY5. */ + Uint16 KEY5; // KEY reg bits 95-80 + /* Объявляет KEY6 — данные KEY6. */ + Uint16 KEY6; // KEY reg bits 111-96 + /* Объявляет KEY7 — данные KEY7. */ + Uint16 KEY7; // KEY reg bits 127-112 + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1; // reserved + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2; // reserved + /* Объявляет rsvd3 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3; // reserved + /* Объявляет rsvd4 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd4; // reserved + /* Объявляет rsvd5 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd5; // reserved + /* Объявляет rsvd6 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd6; // reserved + /* Объявляет rsvd7 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd7; // reserved + /* Объединяет несколько представлений CSMSCR_REG CSMSCR; в одной области памяти. */ + union CSMSCR_REG CSMSCR; // CSM Status & Control register +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Password locations */ +/* Описывает структуру CSM_PWL; порядок полей определяет расположение данных. */ +struct CSM_PWL { + /* Объявляет PSWD0 — данные PSWD0. */ + Uint16 PSWD0; // PSWD bits 15-0 + /* Объявляет PSWD1 — данные PSWD1. */ + Uint16 PSWD1; // PSWD bits 31-16 + /* Объявляет PSWD2 — данные PSWD2. */ + Uint16 PSWD2; // PSWD bits 47-32 + /* Объявляет PSWD3 — данные PSWD3. */ + Uint16 PSWD3; // PSWD bits 63-48 + /* Объявляет PSWD4 — данные PSWD4. */ + Uint16 PSWD4; // PSWD bits 79-64 + /* Объявляет PSWD5 — данные PSWD5. */ + Uint16 PSWD5; // PSWD bits 95-80 + /* Объявляет PSWD6 — данные PSWD6. */ + Uint16 PSWD6; // PSWD bits 111-96 + /* Объявляет PSWD7 — данные PSWD7. */ + Uint16 PSWD7; // PSWD bits 127-112 +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + +/* Flash Registers */ + +/* Задаёт FLASH_SLEEP = 0x0000;; данные FLASH_SLEEP. */ +#define FLASH_SLEEP 0x0000; +/* Задаёт FLASH_STANDBY = 0x0001;; данные FLASH_STANDBY. */ +#define FLASH_STANDBY 0x0001; +/* Задаёт FLASH_ACTIVE = 0x0003;; данные FLASH_ACTIVE. */ +#define FLASH_ACTIVE 0x0003; + + +/* Flash Option Register bit definitions */ +/* Описывает структуру FOPT_BITS; порядок полей определяет расположение данных. */ +struct FOPT_BITS { // bit description + /* Битовое поле ENPIPE, ширина 1 бит; данные ENPIPE. */ + Uint16 ENPIPE:1; // 0 Enable Pipeline Mode + /* Битовое поле rsvd, ширина 15 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:15; // 1-15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений FOPT_REG в одной области памяти. */ +union FOPT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру FOPT_BITS bit;; порядок полей определяет расположение данных. */ + struct FOPT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Flash Power Modes Register bit definitions */ +/* Описывает структуру FPWR_BITS; порядок полей определяет расположение данных. */ +struct FPWR_BITS { // bit description + /* Битовое поле PWR, ширина 2 бит; данные PWR. */ + Uint16 PWR:2; // 0-1 Power Mode bits + /* Битовое поле rsvd, ширина 14 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:14; // 2-15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений FPWR_REG в одной области памяти. */ +union FPWR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру FPWR_BITS bit;; порядок полей определяет расположение данных. */ + struct FPWR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Flash Status Register bit definitions */ +/* Описывает структуру FSTATUS_BITS; порядок полей определяет расположение данных. */ +struct FSTATUS_BITS { // bit description + /* Битовое поле PWRS, ширина 2 бит; данные PWRS. */ + Uint16 PWRS:2; // 0-1 Power Mode Status bits + /* Битовое поле STDBYWAITS, ширина 1 бит; данные STDBYWAITS. */ + Uint16 STDBYWAITS:1; // 2 Bank/Pump Sleep to Standby Wait Counter Status bits + /* Битовое поле ACTIVEWAITS, ширина 1 бит; данные ACTIVEWAITS. */ + Uint16 ACTIVEWAITS:1; // 3 Bank/Pump Standby to Active Wait Counter Status bits + /* Битовое поле rsvd1, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:4; // 4-7 reserved + /* Битовое поле V3STAT, ширина 1 бит; данные V3STAT. */ + Uint16 V3STAT:1; // 8 VDD3V Status Latch bit + /* Битовое поле rsvd2, ширина 7 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:7; // 9-15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений FSTATUS_REG в одной области памяти. */ +union FSTATUS_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру FSTATUS_BITS bit;; порядок полей определяет расположение данных. */ + struct FSTATUS_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Flash Sleep to Standby Wait Counter Register bit definitions */ +/* Описывает структуру FSTDBYWAIT_BITS; порядок полей определяет расположение данных. */ +struct FSTDBYWAIT_BITS { // bit description + /* Битовое поле STDBYWAIT, ширина 9 бит; данные STDBYWAIT. */ + Uint16 STDBYWAIT:9; // 0-8 Bank/Pump Sleep to Standby Wait Count bits + /* Битовое поле rsvd, ширина 7 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:7; // 9-15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений FSTDBYWAIT_REG в одной области памяти. */ +union FSTDBYWAIT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру FSTDBYWAIT_BITS bit;; порядок полей определяет расположение данных. */ + struct FSTDBYWAIT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Flash Standby to Active Wait Counter Register bit definitions */ +/* Описывает структуру FACTIVEWAIT_BITS; порядок полей определяет расположение данных. */ +struct FACTIVEWAIT_BITS { // bit description + /* Битовое поле ACTIVEWAIT, ширина 9 бит; данные ACTIVEWAIT. */ + Uint16 ACTIVEWAIT:9; // 0-8 Bank/Pump Standby to Active Wait Count bits + /* Битовое поле rsvd, ширина 7 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:7; // 9-15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений FACTIVEWAIT_REG в одной области памяти. */ +union FACTIVEWAIT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру FACTIVEWAIT_BITS bit;; порядок полей определяет расположение данных. */ + struct FACTIVEWAIT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Bank Read Access Wait State Register bit definitions */ +/* Описывает структуру FBANKWAIT_BITS; порядок полей определяет расположение данных. */ +struct FBANKWAIT_BITS { // bit description + /* Битовое поле RANDWAIT, ширина 4 бит; данные RANDWAIT. */ + Uint16 RANDWAIT:4; // 0-3 Flash Random Read Wait State bits + /* Битовое поле rsvd1, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:4; // 4-7 reserved + /* Битовое поле PAGEWAIT, ширина 4 бит; данные PAGEWAIT. */ + Uint16 PAGEWAIT:4; // 8-11 Flash Paged Read Wait State bits + /* Битовое поле rsvd2, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:4; // 12-15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений FBANKWAIT_REG в одной области памяти. */ +union FBANKWAIT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру FBANKWAIT_BITS bit;; порядок полей определяет расположение данных. */ + struct FBANKWAIT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* OTP Read Access Wait State Register bit definitions */ +/* Описывает структуру FOTPWAIT_BITS; порядок полей определяет расположение данных. */ +struct FOTPWAIT_BITS { // bit description + /* Битовое поле OTPWAIT, ширина 5 бит; данные OTPWAIT. */ + Uint16 OTPWAIT:5; // 0-4 OTP Read Wait State bits + /* Битовое поле rsvd, ширина 11 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:11; // 5-15 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Allow access to the bit fields or entire register */ +/* Объединяет несколько представлений FOTPWAIT_REG в одной области памяти. */ +union FOTPWAIT_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру FOTPWAIT_BITS bit;; порядок полей определяет расположение данных. */ + struct FOTPWAIT_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +/* Описывает структуру FLASH_REGS; порядок полей определяет расположение данных. */ +struct FLASH_REGS { + /* Объединяет несколько представлений FOPT_REG FOPT; в одной области памяти. */ + union FOPT_REG FOPT; // Option Register + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1; // reserved + /* Объединяет несколько представлений FPWR_REG FPWR; в одной области памяти. */ + union FPWR_REG FPWR; // Power Modes Register + /* Объединяет несколько представлений FSTATUS_REG FSTATUS; в одной области памяти. */ + union FSTATUS_REG FSTATUS; // Status Register + /* Объединяет несколько представлений FSTDBYWAIT_REG FSTDBYWAIT; в одной области памяти. */ + union FSTDBYWAIT_REG FSTDBYWAIT; // Pump/Bank Sleep to Standby Wait State Register + /* Объединяет несколько представлений FACTIVEWAIT_REG FACTIVEWAIT; в одной области памяти. */ + union FACTIVEWAIT_REG FACTIVEWAIT; // Pump/Bank Standby to Active Wait State Register + /* Объединяет несколько представлений FBANKWAIT_REG FBANKWAIT; в одной области памяти. */ + union FBANKWAIT_REG FBANKWAIT; // Bank Read Access Wait State Register + /* Объединяет несколько представлений FOTPWAIT_REG FOTPWAIT; в одной области памяти. */ + union FOTPWAIT_REG FOTPWAIT; // OTP Read Access Wait State Register +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// System Control External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct SYS_CTRL_REGS SysCtrlRegs;; порядок элементов сохраняется. */ +extern volatile struct SYS_CTRL_REGS SysCtrlRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct CSM_REGS CsmRegs;; порядок элементов сохраняется. */ +extern volatile struct CSM_REGS CsmRegs; +/* Продолжает список аргументов, полей или выражение extern volatile struct CSM_PWL CsmPwl;; порядок элементов сохраняется. */ +extern volatile struct CSM_PWL CsmPwl; +/* Продолжает список аргументов, полей или выражение extern volatile struct FLASH_REGS FlashRegs;; порядок элементов сохраняется. */ +extern volatile struct FLASH_REGS FlashRegs; + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_SYS_CTRL_H definition + +//=========================================================================== +// End of file. +//=========================================================================== + diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_XIntrupt.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_XIntrupt.h new file mode 100644 index 0000000..91eca18 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_XIntrupt.h @@ -0,0 +1,127 @@ +/* Поставляемое TI описание XIntrupt для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/1 $ +// Checkin $Date: August 18, 2006 13:52:39 $ +//########################################################################### +// +// FILE: DSP2833x_XIntrupt.h +// +// TITLE: DSP2833x Device External Interrupt Register Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_XINTRUPT_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_XINTRUPT_H +/* Определяет защитный символ или переключатель DSP2833x_XINTRUPT_H для последующей компиляции. */ +#define DSP2833x_XINTRUPT_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +//--------------------------------------------------------------------------- + +/* Описывает структуру XINTCR_BITS; порядок полей определяет расположение данных. */ +struct XINTCR_BITS { + /* Битовое поле ENABLE, ширина 1 бит; разрешение. */ + Uint16 ENABLE:1; // 0 enable/disable + /* Битовое поле rsvd1, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:1; // 1 reserved + /* Битовое поле POLARITY, ширина 2 бит; данные POLARITY. */ + Uint16 POLARITY:2; // 3:2 pos/neg, both triggered + /* Битовое поле rsvd2, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:12; //15:4 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XINTCR_REG в одной области памяти. */ +union XINTCR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XINTCR_BITS bit;; порядок полей определяет расположение данных. */ + struct XINTCR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру XNMICR_BITS; порядок полей определяет расположение данных. */ +struct XNMICR_BITS { + /* Битовое поле ENABLE, ширина 1 бит; разрешение. */ + Uint16 ENABLE:1; // 0 enable/disable + /* Битовое поле SELECT, ширина 1 бит; выбор. */ + Uint16 SELECT:1; // 1 Timer 1 or XNMI connected to int13 + /* Битовое поле POLARITY, ширина 2 бит; данные POLARITY. */ + Uint16 POLARITY:2; // 3:2 pos/neg, or both triggered + /* Битовое поле rsvd2, ширина 12 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:12; // 15:4 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XNMICR_REG в одной области памяти. */ +union XNMICR_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XNMICR_BITS bit;; порядок полей определяет расположение данных. */ + struct XNMICR_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + + + +//--------------------------------------------------------------------------- +// External Interrupt Register File: +// +/* Описывает структуру XINTRUPT_REGS; порядок полей определяет расположение данных. */ +struct XINTRUPT_REGS { + /* Объединяет несколько представлений XINTCR_REG XINT1CR; в одной области памяти. */ + union XINTCR_REG XINT1CR; + /* Объединяет несколько представлений XINTCR_REG XINT2CR; в одной области памяти. */ + union XINTCR_REG XINT2CR; + /* Объединяет несколько представлений XINTCR_REG XINT3CR; в одной области памяти. */ + union XINTCR_REG XINT3CR; + /* Объединяет несколько представлений XINTCR_REG XINT4CR; в одной области памяти. */ + union XINTCR_REG XINT4CR; + /* Объединяет несколько представлений XINTCR_REG XINT5CR; в одной области памяти. */ + union XINTCR_REG XINT5CR; + /* Объединяет несколько представлений XINTCR_REG XINT6CR; в одной области памяти. */ + union XINTCR_REG XINT6CR; + /* Объединяет несколько представлений XINTCR_REG XINT7CR; в одной области памяти. */ + union XINTCR_REG XINT7CR; + /* Объединяет несколько представлений XNMICR_REG XNMICR; в одной области памяти. */ + union XNMICR_REG XNMICR; + /* Объявляет XINT1CTR — данные XINT1CTR. */ + Uint16 XINT1CTR; + /* Объявляет XINT2CTR — данные XINT2CTR. */ + Uint16 XINT2CTR; + /* Объявляет rsvd — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd[5]; + /* Объявляет XNMICTR — данные XNMICTR. */ + Uint16 XNMICTR; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// External Interrupt References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct XINTRUPT_REGS XIntruptRegs;; порядок элементов сохраняется. */ +extern volatile struct XINTRUPT_REGS XIntruptRegs; + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_XINTF_H definition + +//=========================================================================== +// End of file. +//=========================================================================== + diff --git a/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Xintf.h b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Xintf.h new file mode 100644 index 0000000..63686b1 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/include/DSP2833x_Xintf.h @@ -0,0 +1,197 @@ +/* Поставляемое TI описание Xintf для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/3 $ +// Checkin $Date: March 20, 2007 16:34:08 $ +//########################################################################### +// +// FILE: DSP2833x_Xintf.h +// +// TITLE: DSP2833x Device External Interface Register Definitions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Начинает условие: DSP2833x_XINTF_H ещё не определён; защищает повторное включение или задаёт значение сборки. */ +#ifndef DSP2833x_XINTF_H +/* Определяет защитный символ или переключатель DSP2833x_XINTF_H для последующей компиляции. */ +#define DSP2833x_XINTF_H + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Задаёт C-соглашение о связывании имён при включении заголовка из C++. */ +extern "C" { +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + +// XINTF timing register bit definitions: +/* Описывает структуру XTIMING_BITS; порядок полей определяет расположение данных. */ +struct XTIMING_BITS { // bits description + /* Битовое поле XWRTRAIL, ширина 2 бит; данные XWRTRAIL. */ + Uint16 XWRTRAIL:2; // 1:0 Write access trail timing + /* Битовое поле XWRACTIVE, ширина 3 бит; данные XWRACTIVE. */ + Uint16 XWRACTIVE:3; // 4:2 Write access active timing + /* Битовое поле XWRLEAD, ширина 2 бит; данные XWRLEAD. */ + Uint16 XWRLEAD:2; // 6:5 Write access lead timing + /* Битовое поле XRDTRAIL, ширина 2 бит; данные XRDTRAIL. */ + Uint16 XRDTRAIL:2; // 8:7 Read access trail timing + /* Битовое поле XRDACTIVE, ширина 3 бит; данные XRDACTIVE. */ + Uint16 XRDACTIVE:3; // 11:9 Read access active timing + /* Битовое поле XRDLEAD, ширина 2 бит; данные XRDLEAD. */ + Uint16 XRDLEAD:2; // 13:12 Read access lead timing + /* Битовое поле USEREADY, ширина 1 бит; данные USEREADY. */ + Uint16 USEREADY:1; // 14 Extend access using HW waitstates + /* Битовое поле READYMODE, ширина 1 бит; данные READYMODE. */ + Uint16 READYMODE:1; // 15 Ready mode + /* Битовое поле XSIZE, ширина 2 бит; данные XSIZE. */ + Uint16 XSIZE:2; // 17:16 XINTF bus width - must be written as 11b + /* Битовое поле rsvd1, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:4; // 21:18 reserved + /* Битовое поле X2TIMING, ширина 1 бит; данные X2TIMING. */ + Uint16 X2TIMING:1; // 22 Double lead/active/trail timing + /* Битовое поле rsvd3, ширина 9 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:9; // 31:23 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XTIMING_REG в одной области памяти. */ +union XTIMING_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру XTIMING_BITS bit;; порядок полей определяет расположение данных. */ + struct XTIMING_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XINTF control register bit definitions: +/* Описывает структуру XINTCNF2_BITS; порядок полей определяет расположение данных. */ +struct XINTCNF2_BITS { // bits description + /* Битовое поле WRBUFF, ширина 2 бит; данные WRBUFF. */ + Uint16 WRBUFF:2; // 1:0 Write buffer depth + /* Битовое поле CLKMODE, ширина 1 бит; данные CLKMODE. */ + Uint16 CLKMODE:1; // 2 Ratio for XCLKOUT with respect to XTIMCLK + /* Битовое поле CLKOFF, ширина 1 бит; данные CLKOFF. */ + Uint16 CLKOFF:1; // 3 Disable XCLKOUT + /* Битовое поле rsvd1, ширина 2 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:2; // 5:4 reserved + /* Битовое поле WLEVEL, ширина 2 бит; данные WLEVEL. */ + Uint16 WLEVEL:2; // 7:6 Current level of the write buffer + /* Битовое поле rsvd2, ширина 1 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd2:1; // 8 reserved + /* Битовое поле HOLD, ширина 1 бит; данные HOLD. */ + Uint16 HOLD:1; // 9 Hold enable/disable + /* Битовое поле HOLDS, ширина 1 бит; данные HOLDS. */ + Uint16 HOLDS:1; // 10 Current state of HOLDn input + /* Битовое поле HOLDAS, ширина 1 бит; данные HOLDAS. */ + Uint16 HOLDAS:1; // 11 Current state of HOLDAn output + /* Битовое поле rsvd3, ширина 4 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd3:4; // 15:12 reserved + /* Битовое поле XTIMCLK, ширина 3 бит; данные XTIMCLK. */ + Uint16 XTIMCLK:3; // 18:16 Ratio for XTIMCLK + /* Битовое поле rsvd4, ширина 13 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd4:13; // 31:19 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XINTCNF2_REG в одной области памяти. */ +union XINTCNF2_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint32 all; + /* Описывает структуру XINTCNF2_BITS bit;; порядок полей определяет расположение данных. */ + struct XINTCNF2_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +// XINTF bank switching register bit definitions: +/* Описывает структуру XBANK_BITS; порядок полей определяет расположение данных. */ +struct XBANK_BITS { // bits description + /* Битовое поле BANK, ширина 3 бит; данные BANK. */ + Uint16 BANK:3; // 2:0 Zone for which banking is enabled + /* Битовое поле BCYC, ширина 3 бит; данные BCYC. */ + Uint16 BCYC:3; // 5:3 XTIMCLK cycles to add + /* Битовое поле rsvd, ширина 10 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd:10; // 15:6 reserved +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XBANK_REG в одной области памяти. */ +union XBANK_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XBANK_BITS bit;; порядок полей определяет расположение данных. */ + struct XBANK_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Описывает структуру XRESET_BITS; порядок полей определяет расположение данных. */ +struct XRESET_BITS { + /* Битовое поле XHARDRESET, ширина 1 бит; данные XHARDRESET. */ + Uint16 XHARDRESET:1; + /* Битовое поле rsvd1, ширина 15 бит; зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd1:15; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +/* Объединяет несколько представлений XRESET_REG в одной области памяти. */ +union XRESET_REG { + /* Объявляет all — представление регистра целым словом без разбиения на битовые поля. */ + Uint16 all; + /* Описывает структуру XBANK_BITS bit;; порядок полей определяет расположение данных. */ + struct XBANK_BITS bit; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + + +//--------------------------------------------------------------------------- +// XINTF Register File: +// +/* Описывает структуру XINTF_REGS; порядок полей определяет расположение данных. */ +struct XINTF_REGS { + /* Объединяет несколько представлений XTIMING_REG XTIMING0; в одной области памяти. */ + union XTIMING_REG XTIMING0; + /* Объявляет rsvd1 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint32 rsvd1[5]; + /* Объединяет несколько представлений XTIMING_REG XTIMING6; в одной области памяти. */ + union XTIMING_REG XTIMING6; + /* Объединяет несколько представлений XTIMING_REG XTIMING7; в одной области памяти. */ + union XTIMING_REG XTIMING7; + /* Объявляет rsvd2 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint32 rsvd2[2]; + /* Объединяет несколько представлений XINTCNF2_REG XINTCNF2; в одной области памяти. */ + union XINTCNF2_REG XINTCNF2; + /* Объявляет rsvd3 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint32 rsvd3; + /* Объединяет несколько представлений XBANK_REG XBANK; в одной области памяти. */ + union XBANK_REG XBANK; + /* Объявляет rsvd4 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd4; + /* Объявляет XREVISION — данные XREVISION. */ + Uint16 XREVISION; + /* Объявляет rsvd5 — зарезервированные биты для сохранения аппаратного расположения. */ + Uint16 rsvd5[2]; + /* Объединяет несколько представлений XRESET_REG XRESET; в одной области памяти. */ + union XRESET_REG XRESET; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +}; + +//--------------------------------------------------------------------------- +// XINTF External References & Function Declarations: +// +/* Продолжает список аргументов, полей или выражение extern volatile struct XINTF_REGS XintfRegs;; порядок элементов сохраняется. */ +extern volatile struct XINTF_REGS XintfRegs; + + +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} +#endif /* extern "C" */ /* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ + +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif // end of DSP2833x_XINTF_H definition + +//=========================================================================== +// No more. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_ADC_cal.asm b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_ADC_cal.asm new file mode 100644 index 0000000..1de162b --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_ADC_cal.asm @@ -0,0 +1,51 @@ +; Поставляемое ti описание adc_cal для семейства c2833x. Пояснения в UTF-8. +;; TI File $Revision: /main/1 $ +;; Checkin $Date: July 30, 2007 10:29:23 $ +;;########################################################################### +;; +;; FILE: ADC_cal.asm +;; +;; TITLE: 2833x Boot Rom ADC Cal routine. +;; +;; Functions: +;; +;; _ADC_cal - Copies device specific calibration data into ADCREFSEL and ADCOFFTRIM registers +;; Notes: +;; +;;########################################################################### +;; $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +;; $Release Date: August 1, 2008 $ +;;########################################################################### + + ; Экспортирует символ для связывания с C-кодом. Операция: .def _ADC_cal. + .def _ADC_cal + ; Задаёт текстовый псевдоним константы для ассемблера. Операция: .asg "0x711C", ADCREFSEL_LOC. + .asg "0x711C", ADCREFSEL_LOC + +;----------------------------------------------- +; _ADC_cal +;----------------------------------------------- +;----------------------------------------------- +; This is the ADC cal routine.This routine is programmed into +; reserved memory by the factory. 0xAAAA and 0xBBBB are place- +; holders for calibration data. +;The actual values programmed by TI are device specific. +; +; This function assumes that the clocks have been +; enabled to the ADC module. +;----------------------------------------------- + + ; Выбирает секцию объектного файла для следующих инструкций. Операция: .sect ".adc_cal". + .sect ".adc_cal" + +; Объявляет метку _ADC_cal для перехода или вызова. Операция: _ADC_cal. +_ADC_cal + ; Загружает регистр страниц данных DP для доступа к указанной области. Операция: MOVW DP, #ADCREFSEL_LOC >> 6. + MOVW DP, #ADCREFSEL_LOC >> 6 + ; Переносит операнд в регистр или ячейку назначения. Операция: MOV @28, #0xAAAA. + MOV @28, #0xAAAA ; actual value may not be 0xAAAA + ; Переносит операнд в регистр или ячейку назначения. Операция: MOV @29, #0xBBBB. + MOV @29, #0xBBBB ; actual value may not be 0xBBBB + ; Возвращает управление вызывающему коду через длинный адрес возврата. Операция: LRETR. + LRETR +;eof ---------- diff --git a/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_CpuTimers.c b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_CpuTimers.c new file mode 100644 index 0000000..def985e --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_CpuTimers.c @@ -0,0 +1,161 @@ +/* Поставляемое TI описание CpuTimers для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/3 $ +// Checkin $Date: March 16, 2007 08:37:30 $ +//########################################################################### +// +// FILE: DSP2833x_CpuTimers.c +// +// TITLE: CPU 32-bit Timers Initialization & Support Functions. +// +// NOTES: CpuTimer1 and CpuTimer2 are reserved for use with DSP BIOS and +// other realtime operating systems. +// +// Do not use these two timers in your application if you ever plan +// on integrating DSP-BIOS or another realtime OS. +// +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Подключает "DSP2833x_Device.h": поставляемое TI описание Device для семейства C2833x. */ +#include "DSP2833x_Device.h" // Headerfile Include File +/* Подключает "DSP2833x_Examples.h": поставляемое TI описание Examples для семейства C2833x. */ +#include "DSP2833x_Examples.h" // Examples Include File + +/* Описывает структуру CPUTIMER_VARS CpuTimer0;; порядок полей определяет расположение данных. */ +struct CPUTIMER_VARS CpuTimer0; + +// CpuTimer 1 and CpuTimer2 are used by DSP BIOS & other RTOS. Comment out if using DSP BIOS or other RTOS. +/* Описывает структуру CPUTIMER_VARS CpuTimer1;; порядок полей определяет расположение данных. */ +struct CPUTIMER_VARS CpuTimer1; +/* Описывает структуру CPUTIMER_VARS CpuTimer2;; порядок полей определяет расположение данных. */ +struct CPUTIMER_VARS CpuTimer2; + +//--------------------------------------------------------------------------- +// InitCpuTimers: +//--------------------------------------------------------------------------- +// This function initializes all three CPU timers to a known state. +// +/* Начинает функцию InitCpuTimers; назначение модуля — поставляемое TI описание CpuTimers для семейства C2833x. */ +void InitCpuTimers(void) +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + // CPU Timer 0 + // Initialize address pointers to respective timer registers: + /* Записывает CpuTimer0.RegsAddr значением &CpuTimer0Regs; данные RegsAddr. */ + CpuTimer0.RegsAddr = &CpuTimer0Regs; + // Initialize timer period to maximum: + /* Записывает CpuTimer0Regs.PRD.all значением 0xFFFFFFFF; представление регистра целым словом без разбиения на битовые поля. */ + CpuTimer0Regs.PRD.all = 0xFFFFFFFF; + // Initialize pre-scale counter to divide by 1 (SYSCLKOUT): + /* Записывает CpuTimer0Regs.TPR.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + CpuTimer0Regs.TPR.all = 0; + /* Записывает CpuTimer0Regs.TPRH.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + CpuTimer0Regs.TPRH.all = 0; + // Make sure timer is stopped: + /* Записывает CpuTimer0Regs.TCR.bit.TSS значением 1; данные TSS. */ + CpuTimer0Regs.TCR.bit.TSS = 1; + // Reload all counter register with period value: + /* Записывает CpuTimer0Regs.TCR.bit.TRB значением 1; данные TRB. */ + CpuTimer0Regs.TCR.bit.TRB = 1; + // Reset interrupt counters: + /* Записывает CpuTimer0.InterruptCount значением 0; прерывание число. */ + CpuTimer0.InterruptCount = 0; + + +// CpuTimer 1 and CpuTimer2 are reserved for DSP BIOS & other RTOS +// Do not use these two timers if you ever plan on integrating +// DSP-BIOS or another realtime OS. +// +// Initialize address pointers to respective timer registers: + /* Записывает CpuTimer1.RegsAddr значением &CpuTimer1Regs; данные RegsAddr. */ + CpuTimer1.RegsAddr = &CpuTimer1Regs; + /* Записывает CpuTimer2.RegsAddr значением &CpuTimer2Regs; данные RegsAddr. */ + CpuTimer2.RegsAddr = &CpuTimer2Regs; + // Initialize timer period to maximum: + /* Записывает CpuTimer1Regs.PRD.all значением 0xFFFFFFFF; представление регистра целым словом без разбиения на битовые поля. */ + CpuTimer1Regs.PRD.all = 0xFFFFFFFF; + /* Записывает CpuTimer2Regs.PRD.all значением 0xFFFFFFFF; представление регистра целым словом без разбиения на битовые поля. */ + CpuTimer2Regs.PRD.all = 0xFFFFFFFF; + // Initialize pre-scale counter to divide by 1 (SYSCLKOUT): + /* Записывает CpuTimer1Regs.TPR.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + CpuTimer1Regs.TPR.all = 0; + /* Записывает CpuTimer1Regs.TPRH.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + CpuTimer1Regs.TPRH.all = 0; + /* Записывает CpuTimer2Regs.TPR.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + CpuTimer2Regs.TPR.all = 0; + /* Записывает CpuTimer2Regs.TPRH.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + CpuTimer2Regs.TPRH.all = 0; + // Make sure timers are stopped: + /* Записывает CpuTimer1Regs.TCR.bit.TSS значением 1; данные TSS. */ + CpuTimer1Regs.TCR.bit.TSS = 1; + /* Записывает CpuTimer2Regs.TCR.bit.TSS значением 1; данные TSS. */ + CpuTimer2Regs.TCR.bit.TSS = 1; + // Reload all counter register with period value: + /* Записывает CpuTimer1Regs.TCR.bit.TRB значением 1; данные TRB. */ + CpuTimer1Regs.TCR.bit.TRB = 1; + /* Записывает CpuTimer2Regs.TCR.bit.TRB значением 1; данные TRB. */ + CpuTimer2Regs.TCR.bit.TRB = 1; + // Reset interrupt counters: + /* Записывает CpuTimer1.InterruptCount значением 0; прерывание число. */ + CpuTimer1.InterruptCount = 0; + /* Записывает CpuTimer2.InterruptCount значением 0; прерывание число. */ + CpuTimer2.InterruptCount = 0; + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + +//--------------------------------------------------------------------------- +// ConfigCpuTimer: +//--------------------------------------------------------------------------- +// This function initializes the selected timer to the period specified +// by the "Freq" and "Period" parameters. The "Freq" is entered as "MHz" +// and the period in "uSeconds". The timer is held in the stopped state +// after configuration. +// +/* Начинает функцию ConfigCpuTimer; назначение модуля — поставляемое TI описание CpuTimers для семейства C2833x. */ +void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period) +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Объявляет temp — данные temp. */ + Uint32 temp; + + // Initialize timer period: + /* Записывает Timer->CPUFreqInMHz значением Freq; таймер CPU Freq In M Hz. */ + Timer->CPUFreqInMHz = Freq; + /* Записывает Timer->PeriodInUSec значением Period; таймер период In U Sec. */ + Timer->PeriodInUSec = Period; + /* Записывает temp значением (long) (Freq * Period); данные temp. */ + temp = (long) (Freq * Period); + /* Записывает Timer->RegsAddr->PRD.all значением temp; представление регистра целым словом без разбиения на битовые поля. */ + Timer->RegsAddr->PRD.all = temp; + + // Set pre-scale counter to divide by 1 (SYSCLKOUT): + /* Записывает Timer->RegsAddr->TPR.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + Timer->RegsAddr->TPR.all = 0; + /* Записывает Timer->RegsAddr->TPRH.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + Timer->RegsAddr->TPRH.all = 0; + + // Initialize timer control register: + /* Записывает Timer->RegsAddr->TCR.bit.TSS значением 1; данные TSS. */ + Timer->RegsAddr->TCR.bit.TSS = 1; // 1 = Stop timer, 0 = Start/Restart Timer + /* Записывает Timer->RegsAddr->TCR.bit.TRB значением 1; данные TRB. */ + Timer->RegsAddr->TCR.bit.TRB = 1; // 1 = reload timer + /* Записывает Timer->RegsAddr->TCR.bit.SOFT значением 0; данные SOFT. */ + Timer->RegsAddr->TCR.bit.SOFT = 0; + /* Записывает Timer->RegsAddr->TCR.bit.FREE значением 0; данные FREE. */ + Timer->RegsAddr->TCR.bit.FREE = 0; // Timer Free Run Disabled + /* Записывает Timer->RegsAddr->TCR.bit.TIE значением 1; данные TIE. */ + Timer->RegsAddr->TCR.bit.TIE = 1; // 0 = Disable/ 1 = Enable Timer Interrupt + + // Reset interrupt counter: + /* Записывает Timer->InterruptCount значением 0; таймер прерывание число. */ + Timer->InterruptCount = 0; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_GlobalVariableDefs.c b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_GlobalVariableDefs.c new file mode 100644 index 0000000..74a8a7e --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_GlobalVariableDefs.c @@ -0,0 +1,746 @@ +/* Поставляемое TI описание GlobalVariableDefs для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/4 $ +// Checkin $Date: June 2, 2008 11:12:33 $ +//########################################################################### +// +// FILE: DSP2833x_GlobalVariableDefs.c +// +// TITLE: DSP2833x Global Variables and Data Section Pragmas. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Подключает "DSP2833x_Device.h": поставляемое TI описание Device для семейства C2833x. */ +#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File + +//--------------------------------------------------------------------------- +// Define Global Peripheral Variables: +// +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("AdcRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("AdcRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(AdcRegs,"AdcRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(AdcRegs,"AdcRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ADC_REGS AdcRegs;; порядок элементов сохраняется. */ +volatile struct ADC_REGS AdcRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("AdcMirrorFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("AdcMirrorFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(AdcMirror,"AdcMirrorFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(AdcMirror,"AdcMirrorFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ADC_RESULT_MIRROR_REGS AdcMirror;; порядок элементов сохраняется. */ +volatile struct ADC_RESULT_MIRROR_REGS AdcMirror; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("CpuTimer0RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("CpuTimer0RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(CpuTimer0Regs,"CpuTimer0RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(CpuTimer0Regs,"CpuTimer0RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct CPUTIMER_REGS CpuTimer0Regs;; порядок элементов сохраняется. */ +volatile struct CPUTIMER_REGS CpuTimer0Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("CpuTimer1RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("CpuTimer1RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(CpuTimer1Regs,"CpuTimer1RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(CpuTimer1Regs,"CpuTimer1RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct CPUTIMER_REGS CpuTimer1Regs;; порядок элементов сохраняется. */ +volatile struct CPUTIMER_REGS CpuTimer1Regs; + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("CpuTimer2RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("CpuTimer2RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(CpuTimer2Regs,"CpuTimer2RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(CpuTimer2Regs,"CpuTimer2RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct CPUTIMER_REGS CpuTimer2Regs;; порядок элементов сохраняется. */ +volatile struct CPUTIMER_REGS CpuTimer2Regs; + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("CsmPwlFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("CsmPwlFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(CsmPwl,"CsmPwlFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(CsmPwl,"CsmPwlFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct CSM_PWL CsmPwl;; порядок элементов сохраняется. */ +volatile struct CSM_PWL CsmPwl; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("CsmRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("CsmRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(CsmRegs,"CsmRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(CsmRegs,"CsmRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct CSM_REGS CsmRegs;; порядок элементов сохраняется. */ +volatile struct CSM_REGS CsmRegs; + + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("DevEmuRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("DevEmuRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(DevEmuRegs,"DevEmuRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(DevEmuRegs,"DevEmuRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct DEV_EMU_REGS DevEmuRegs;; порядок элементов сохраняется. */ +volatile struct DEV_EMU_REGS DevEmuRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("DmaRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("DmaRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(DmaRegs,"DmaRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(DmaRegs,"DmaRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct DMA_REGS DmaRegs;; порядок элементов сохраняется. */ +volatile struct DMA_REGS DmaRegs; + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECanaRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECanaRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECanaRegs,"ECanaRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECanaRegs,"ECanaRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ECAN_REGS ECanaRegs;; порядок элементов сохраняется. */ +volatile struct ECAN_REGS ECanaRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECanaMboxesFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECanaMboxesFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECanaMboxes,"ECanaMboxesFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECanaMboxes,"ECanaMboxesFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ECAN_MBOXES ECanaMboxes;; порядок элементов сохраняется. */ +volatile struct ECAN_MBOXES ECanaMboxes; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECanaLAMRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECanaLAMRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECanaLAMRegs,"ECanaLAMRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECanaLAMRegs,"ECanaLAMRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct LAM_REGS ECanaLAMRegs;; порядок элементов сохраняется. */ +volatile struct LAM_REGS ECanaLAMRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECanaMOTSRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECanaMOTSRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECanaMOTSRegs,"ECanaMOTSRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECanaMOTSRegs,"ECanaMOTSRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct MOTS_REGS ECanaMOTSRegs;; порядок элементов сохраняется. */ +volatile struct MOTS_REGS ECanaMOTSRegs; + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECanaMOTORegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECanaMOTORegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECanaMOTORegs,"ECanaMOTORegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECanaMOTORegs,"ECanaMOTORegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct MOTO_REGS ECanaMOTORegs;; порядок элементов сохраняется. */ +volatile struct MOTO_REGS ECanaMOTORegs; + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECanbRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECanbRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECanbRegs,"ECanbRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECanbRegs,"ECanbRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ECAN_REGS ECanbRegs;; порядок элементов сохраняется. */ +volatile struct ECAN_REGS ECanbRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECanbMboxesFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECanbMboxesFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECanbMboxes,"ECanbMboxesFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECanbMboxes,"ECanbMboxesFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ECAN_MBOXES ECanbMboxes;; порядок элементов сохраняется. */ +volatile struct ECAN_MBOXES ECanbMboxes; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECanbLAMRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECanbLAMRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECanbLAMRegs,"ECanbLAMRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECanbLAMRegs,"ECanbLAMRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct LAM_REGS ECanbLAMRegs;; порядок элементов сохраняется. */ +volatile struct LAM_REGS ECanbLAMRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECanbMOTSRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECanbMOTSRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECanbMOTSRegs,"ECanbMOTSRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECanbMOTSRegs,"ECanbMOTSRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct MOTS_REGS ECanbMOTSRegs;; порядок элементов сохраняется. */ +volatile struct MOTS_REGS ECanbMOTSRegs; + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECanbMOTORegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECanbMOTORegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECanbMOTORegs,"ECanbMOTORegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECanbMOTORegs,"ECanbMOTORegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct MOTO_REGS ECanbMOTORegs;; порядок элементов сохраняется. */ +volatile struct MOTO_REGS ECanbMOTORegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("EPwm1RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("EPwm1RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(EPwm1Regs,"EPwm1RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(EPwm1Regs,"EPwm1RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct EPWM_REGS EPwm1Regs;; порядок элементов сохраняется. */ +volatile struct EPWM_REGS EPwm1Regs; + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("EPwm2RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("EPwm2RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(EPwm2Regs,"EPwm2RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(EPwm2Regs,"EPwm2RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct EPWM_REGS EPwm2Regs;; порядок элементов сохраняется. */ +volatile struct EPWM_REGS EPwm2Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("EPwm3RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("EPwm3RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(EPwm3Regs,"EPwm3RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(EPwm3Regs,"EPwm3RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct EPWM_REGS EPwm3Regs;; порядок элементов сохраняется. */ +volatile struct EPWM_REGS EPwm3Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("EPwm4RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("EPwm4RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(EPwm4Regs,"EPwm4RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(EPwm4Regs,"EPwm4RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct EPWM_REGS EPwm4Regs;; порядок элементов сохраняется. */ +volatile struct EPWM_REGS EPwm4Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("EPwm5RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("EPwm5RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(EPwm5Regs,"EPwm5RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(EPwm5Regs,"EPwm5RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct EPWM_REGS EPwm5Regs;; порядок элементов сохраняется. */ +volatile struct EPWM_REGS EPwm5Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("EPwm6RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("EPwm6RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(EPwm6Regs,"EPwm6RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(EPwm6Regs,"EPwm6RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct EPWM_REGS EPwm6Regs;; порядок элементов сохраняется. */ +volatile struct EPWM_REGS EPwm6Regs; + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECap1RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECap1RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECap1Regs,"ECap1RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECap1Regs,"ECap1RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ECAP_REGS ECap1Regs;; порядок элементов сохраняется. */ +volatile struct ECAP_REGS ECap1Regs; + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECap2RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECap2RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECap2Regs,"ECap2RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECap2Regs,"ECap2RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ECAP_REGS ECap2Regs;; порядок элементов сохраняется. */ +volatile struct ECAP_REGS ECap2Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECap3RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECap3RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECap3Regs,"ECap3RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECap3Regs,"ECap3RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ECAP_REGS ECap3Regs;; порядок элементов сохраняется. */ +volatile struct ECAP_REGS ECap3Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECap4RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECap4RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECap4Regs,"ECap4RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECap4Regs,"ECap4RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ECAP_REGS ECap4Regs;; порядок элементов сохраняется. */ +volatile struct ECAP_REGS ECap4Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECap5RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECap5RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECap5Regs,"ECap5RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECap5Regs,"ECap5RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ECAP_REGS ECap5Regs;; порядок элементов сохраняется. */ +volatile struct ECAP_REGS ECap5Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ECap6RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ECap6RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ECap6Regs,"ECap6RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ECap6Regs,"ECap6RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct ECAP_REGS ECap6Regs;; порядок элементов сохраняется. */ +volatile struct ECAP_REGS ECap6Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("EQep1RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("EQep1RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(EQep1Regs,"EQep1RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(EQep1Regs,"EQep1RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct EQEP_REGS EQep1Regs;; порядок элементов сохраняется. */ +volatile struct EQEP_REGS EQep1Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("EQep2RegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("EQep2RegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(EQep2Regs,"EQep2RegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(EQep2Regs,"EQep2RegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct EQEP_REGS EQep2Regs;; порядок элементов сохраняется. */ +volatile struct EQEP_REGS EQep2Regs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("GpioCtrlRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("GpioCtrlRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(GpioCtrlRegs,"GpioCtrlRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(GpioCtrlRegs,"GpioCtrlRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct GPIO_CTRL_REGS GpioCtrlRegs;; порядок элементов сохраняется. */ +volatile struct GPIO_CTRL_REGS GpioCtrlRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("GpioDataRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("GpioDataRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(GpioDataRegs,"GpioDataRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(GpioDataRegs,"GpioDataRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct GPIO_DATA_REGS GpioDataRegs;; порядок элементов сохраняется. */ +volatile struct GPIO_DATA_REGS GpioDataRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("GpioIntRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("GpioIntRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(GpioIntRegs,"GpioIntRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(GpioIntRegs,"GpioIntRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct GPIO_INT_REGS GpioIntRegs;; порядок элементов сохраняется. */ +volatile struct GPIO_INT_REGS GpioIntRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("I2caRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("I2caRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(I2caRegs,"I2caRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(I2caRegs,"I2caRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct I2C_REGS I2caRegs;; порядок элементов сохраняется. */ +volatile struct I2C_REGS I2caRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("McbspaRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("McbspaRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(McbspaRegs,"McbspaRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(McbspaRegs,"McbspaRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct MCBSP_REGS McbspaRegs;; порядок элементов сохраняется. */ +volatile struct MCBSP_REGS McbspaRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("McbspbRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("McbspbRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(McbspbRegs,"McbspbRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(McbspbRegs,"McbspbRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct MCBSP_REGS McbspbRegs;; порядок элементов сохраняется. */ +volatile struct MCBSP_REGS McbspbRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("PartIdRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("PartIdRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(PartIdRegs,"PartIdRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(PartIdRegs,"PartIdRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct PARTID_REGS PartIdRegs;; порядок элементов сохраняется. */ +volatile struct PARTID_REGS PartIdRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("PieCtrlRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("PieCtrlRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(PieCtrlRegs,"PieCtrlRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(PieCtrlRegs,"PieCtrlRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct PIE_CTRL_REGS PieCtrlRegs;; порядок элементов сохраняется. */ +volatile struct PIE_CTRL_REGS PieCtrlRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("PieVectTableFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("PieVectTableFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(PieVectTable,"PieVectTableFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(PieVectTable,"PieVectTableFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Описывает структуру PIE_VECT_TABLE PieVectTable;; порядок полей определяет расположение данных. */ +struct PIE_VECT_TABLE PieVectTable; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("SciaRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("SciaRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(SciaRegs,"SciaRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(SciaRegs,"SciaRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct SCI_REGS SciaRegs;; порядок элементов сохраняется. */ +volatile struct SCI_REGS SciaRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ScibRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ScibRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ScibRegs,"ScibRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ScibRegs,"ScibRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct SCI_REGS ScibRegs;; порядок элементов сохраняется. */ +volatile struct SCI_REGS ScibRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("ScicRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("ScicRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(ScicRegs,"ScicRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(ScicRegs,"ScicRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct SCI_REGS ScicRegs;; порядок элементов сохраняется. */ +volatile struct SCI_REGS ScicRegs; + + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("SpiaRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("SpiaRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(SpiaRegs,"SpiaRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(SpiaRegs,"SpiaRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct SPI_REGS SpiaRegs;; порядок элементов сохраняется. */ +volatile struct SPI_REGS SpiaRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("SysCtrlRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("SysCtrlRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(SysCtrlRegs,"SysCtrlRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(SysCtrlRegs,"SysCtrlRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct SYS_CTRL_REGS SysCtrlRegs;; порядок элементов сохраняется. */ +volatile struct SYS_CTRL_REGS SysCtrlRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("FlashRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("FlashRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(FlashRegs,"FlashRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(FlashRegs,"FlashRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct FLASH_REGS FlashRegs;; порядок элементов сохраняется. */ +volatile struct FLASH_REGS FlashRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("XIntruptRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("XIntruptRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(XIntruptRegs,"XIntruptRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(XIntruptRegs,"XIntruptRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct XINTRUPT_REGS XIntruptRegs;; порядок элементов сохраняется. */ +volatile struct XINTRUPT_REGS XIntruptRegs; + +//---------------------------------------- +/* Включает следующий блок только при определённом символе __cplusplus. */ +#ifdef __cplusplus +/* Указание компилятору DATA_SECTION("XintfRegsFile"): размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION("XintfRegsFile") +/* Выбирает альтернативный блок текущего условия компиляции. */ +#else +/* Указание компилятору DATA_SECTION(XintfRegs,"XintfRegsFile");: размещение данных или настройка обработки объявлений. */ +#pragma DATA_SECTION(XintfRegs,"XintfRegsFile"); +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Продолжает список аргументов, полей или выражение volatile struct XINTF_REGS XintfRegs;; порядок элементов сохраняется. */ +volatile struct XINTF_REGS XintfRegs; + + + +//=========================================================================== +// End of file. +//=========================================================================== + + + + + + + + + diff --git a/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_PieCtrl.c b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_PieCtrl.c new file mode 100644 index 0000000..0ca4201 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_PieCtrl.c @@ -0,0 +1,121 @@ +/* Поставляемое TI описание PieCtrl для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/1 $ +// Checkin $Date: August 18, 2006 13:46:35 $ +//########################################################################### +// +// FILE: DSP2833x_PieCtrl.c +// +// TITLE: DSP2833x Device PIE Control Register Initialization Functions. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + +/* Подключает "DSP2833x_Device.h": поставляемое TI описание Device для семейства C2833x. */ +#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File +/* Подключает "DSP2833x_Examples.h": поставляемое TI описание Examples для семейства C2833x. */ +#include "DSP2833x_Examples.h" // DSP2833x Examples Include File + +//--------------------------------------------------------------------------- +// InitPieCtrl: +//--------------------------------------------------------------------------- +// This function initializes the PIE control registers to a known state. +// +/* Начинает функцию InitPieCtrl; назначение модуля — поставляемое TI описание PieCtrl для семейства C2833x. */ +void InitPieCtrl(void) +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + // Disable Interrupts at the CPU level: + /* Запрет маскируемых прерываний ядра. */ + DINT; + + // Disable the PIE + /* Записывает PieCtrlRegs.PIECTRL.bit.ENPIE значением 0; данные ENPIE. */ + PieCtrlRegs.PIECTRL.bit.ENPIE = 0; + + // Clear all PIEIER registers: + /* Записывает PieCtrlRegs.PIEIER1.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER1.all = 0; + /* Записывает PieCtrlRegs.PIEIER2.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER2.all = 0; + /* Записывает PieCtrlRegs.PIEIER3.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER3.all = 0; + /* Записывает PieCtrlRegs.PIEIER4.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER4.all = 0; + /* Записывает PieCtrlRegs.PIEIER5.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER5.all = 0; + /* Записывает PieCtrlRegs.PIEIER6.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER6.all = 0; + /* Записывает PieCtrlRegs.PIEIER7.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER7.all = 0; + /* Записывает PieCtrlRegs.PIEIER8.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER8.all = 0; + /* Записывает PieCtrlRegs.PIEIER9.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER9.all = 0; + /* Записывает PieCtrlRegs.PIEIER10.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER10.all = 0; + /* Записывает PieCtrlRegs.PIEIER11.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER11.all = 0; + /* Записывает PieCtrlRegs.PIEIER12.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIER12.all = 0; + + // Clear all PIEIFR registers: + /* Записывает PieCtrlRegs.PIEIFR1.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR1.all = 0; + /* Записывает PieCtrlRegs.PIEIFR2.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR2.all = 0; + /* Записывает PieCtrlRegs.PIEIFR3.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR3.all = 0; + /* Записывает PieCtrlRegs.PIEIFR4.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR4.all = 0; + /* Записывает PieCtrlRegs.PIEIFR5.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR5.all = 0; + /* Записывает PieCtrlRegs.PIEIFR6.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR6.all = 0; + /* Записывает PieCtrlRegs.PIEIFR7.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR7.all = 0; + /* Записывает PieCtrlRegs.PIEIFR8.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR8.all = 0; + /* Записывает PieCtrlRegs.PIEIFR9.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR9.all = 0; + /* Записывает PieCtrlRegs.PIEIFR10.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR10.all = 0; + /* Записывает PieCtrlRegs.PIEIFR11.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR11.all = 0; + /* Записывает PieCtrlRegs.PIEIFR12.all значением 0; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEIFR12.all = 0; + + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + +//--------------------------------------------------------------------------- +// EnableInterrupts: +//--------------------------------------------------------------------------- +// This function enables the PIE module and CPU interrupts +// +/* Начинает функцию EnableInterrupts; назначение модуля — поставляемое TI описание PieCtrl для семейства C2833x. */ +void EnableInterrupts() +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + + // Enable the PIE + /* Записывает PieCtrlRegs.PIECTRL.bit.ENPIE значением 1; данные ENPIE. */ + PieCtrlRegs.PIECTRL.bit.ENPIE = 1; + + // Enables PIE to drive a pulse into the CPU + /* Записывает PieCtrlRegs.PIEACK.all значением 0xFFFF; представление регистра целым словом без разбиения на битовые поля. */ + PieCtrlRegs.PIEACK.all = 0xFFFF; + + // Enable Interrupts at the CPU level + /* Разрешение маскируемых прерываний ядра. */ + EINT; + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_SysCtrl.c b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_SysCtrl.c new file mode 100644 index 0000000..eaa98f3 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_SysCtrl.c @@ -0,0 +1,604 @@ +/* Поставляемое TI описание SysCtrl для семейства C2833x. Русские пояснения сохранены в UTF-8. */ +// TI File $Revision: /main/7 $ +// Checkin $Date: September 20, 2007 13:30:31 $ +//########################################################################### +// +// FILE: DSP2833x_SysCtrl.c +// +// TITLE: DSP2833x Device System Control Initialization & Support Functions. +// +// DESCRIPTION: +// +// Example initialization of system resources. +// +//########################################################################### +// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +// $Release Date: August 1, 2008 $ +//########################################################################### + + +/* Подключает "DSP2833x_Device.h": поставляемое TI описание Device для семейства C2833x. */ +#include "DSP2833x_Device.h" // Headerfile Include File +/* Подключает "DSP2833x_Examples.h": поставляемое TI описание Examples для семейства C2833x. */ +#include "DSP2833x_Examples.h" // Examples Include File + +//#include "RS485.h" +//#include "message.h" + +// Functions that will be run from RAM need to be assigned to +// a different section. This section will then be mapped to a load and +// run address using the linker cmd file. + +/* Указание компилятору CODE_SECTION(InitFlash, "ramfuncs");: размещение данных или настройка обработки объявлений. */ +#pragma CODE_SECTION(InitFlash, "ramfuncs"); + +//--------------------------------------------------------------------------- +// InitSysCtrl: +//--------------------------------------------------------------------------- +// This function initializes the System Control registers to a known state. +// - Disables the watchdog +// - Set the PLLCR for proper SYSCLKOUT frequency +// - Set the pre-scaler for the high and low frequency peripheral clocks +// - Enable the clocks to the peripherals + +/* Объявляет SYSCLKOUT — данные SYSCLKOUT; LSPCLK — данные LSPCLK; HSPCLK — данные HSPCLK. */ +long SYSCLKOUT, LSPCLK, HSPCLK; + +/* Начинает функцию InitSysCtrl; назначение модуля — поставляемое TI описание SysCtrl для семейства C2833x. */ +void InitSysCtrl(void) +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + + // Disable the watchdog + /* Вызывает DisableDog с аргументами () в текущей последовательности операций. */ + DisableDog(); + + // Initialize the PLL control: PLLCR and DIVSEL + // DSP28_PLLCR and DSP28_DIVSEL are defined in DSP2833x_Examples.h + /* Инициализирует модуль вызовом InitPll(DSP28_PLLCR,DSP28_DIVSEL); перед его дальнейшим использованием. */ + InitPll(DSP28_PLLCR,DSP28_DIVSEL); + + // Initialize the peripheral clocks + /* Инициализирует модуль вызовом InitPeripheralClocks(); перед его дальнейшим использованием. */ + InitPeripheralClocks(); +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + + +//--------------------------------------------------------------------------- +// Example: InitFlash: +//--------------------------------------------------------------------------- +// This function initializes the Flash Control registers + +// CAUTION +// This function MUST be executed out of RAM. Executing it +// out of OTP/Flash will yield unpredictable results + +/* Начинает функцию InitFlash; назначение модуля — поставляемое TI описание SysCtrl для семейства C2833x. */ +void InitFlash(void) +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Разрешение записи в защищённые регистры периферии. */ + EALLOW; + //Enable Flash Pipeline mode to improve performance + //of code executed from Flash. + /* Записывает FlashRegs.FOPT.bit.ENPIPE значением 1; данные ENPIPE. */ + FlashRegs.FOPT.bit.ENPIPE = 1; + + // CAUTION + //Minimum waitstates required for the flash operating + //at a given CPU rate must be characterized by TI. + //Refer to the datasheet for the latest information. +/* Условие компиляции CPU_FRQ_150MHZ: выбранный блок включается в текущий вариант прошивки. */ +#if CPU_FRQ_150MHZ + //Set the Paged Waitstate for the Flash + /* Записывает FlashRegs.FBANKWAIT.bit.PAGEWAIT значением 5; данные PAGEWAIT. */ + FlashRegs.FBANKWAIT.bit.PAGEWAIT = 5; + + //Set the Random Waitstate for the Flash + /* Записывает FlashRegs.FBANKWAIT.bit.RANDWAIT значением 5; данные RANDWAIT. */ + FlashRegs.FBANKWAIT.bit.RANDWAIT = 5; + + //Set the Waitstate for the OTP + /* Записывает FlashRegs.FOTPWAIT.bit.OTPWAIT значением 8; данные OTPWAIT. */ + FlashRegs.FOTPWAIT.bit.OTPWAIT = 8; +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + +/* Условие компиляции CPU_FRQ_100MHZ: выбранный блок включается в текущий вариант прошивки. */ +#if CPU_FRQ_100MHZ + //Set the Paged Waitstate for the Flash + /* Записывает FlashRegs.FBANKWAIT.bit.PAGEWAIT значением 3; данные PAGEWAIT. */ + FlashRegs.FBANKWAIT.bit.PAGEWAIT = 3; + + //Set the Random Waitstate for the Flash + /* Записывает FlashRegs.FBANKWAIT.bit.RANDWAIT значением 3; данные RANDWAIT. */ + FlashRegs.FBANKWAIT.bit.RANDWAIT = 3; + + //Set the Waitstate for the OTP + /* Записывает FlashRegs.FOTPWAIT.bit.OTPWAIT значением 5; данные OTPWAIT. */ + FlashRegs.FOTPWAIT.bit.OTPWAIT = 5; +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + // CAUTION + //ONLY THE DEFAULT VALUE FOR THESE 2 REGISTERS SHOULD BE USED + /* Записывает FlashRegs.FSTDBYWAIT.bit.STDBYWAIT значением 0x01FF; данные STDBYWAIT. */ + FlashRegs.FSTDBYWAIT.bit.STDBYWAIT = 0x01FF; + /* Записывает FlashRegs.FACTIVEWAIT.bit.ACTIVEWAIT значением 0x01FF; данные ACTIVEWAIT. */ + FlashRegs.FACTIVEWAIT.bit.ACTIVEWAIT = 0x01FF; + /* Закрытие доступа к защищённым регистрам периферии. */ + EDIS; + + //Force a pipeline flush to ensure that the write to + //the last register configured occurs before returning. + + /* Вызывает asm с аргументами (" RPT #7 || NOP") в текущей последовательности операций. */ + asm(" RPT #7 || NOP"); +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + + +//--------------------------------------------------------------------------- +// Example: ServiceDog: +//--------------------------------------------------------------------------- +// This function resets the watchdog timer. +// Enable this function for using ServiceDog in the application + +/* Начинает функцию ServiceDog; назначение модуля — поставляемое TI описание SysCtrl для семейства C2833x. */ +void ServiceDog(void) +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Проверяет if(SysCtrlRegs.PLLCR.bit.DIV == DSP28_PLLCR); последующий оператор выполняется только при истинном условии. */ + if(SysCtrlRegs.PLLCR.bit.DIV == DSP28_PLLCR) + /* Проверяет if(SysCtrlRegs.PLLSTS.bit.DIVSEL == DSP28_DIVSEL); последующий оператор выполняется только при истинном условии. */ + if(SysCtrlRegs.PLLSTS.bit.DIVSEL == DSP28_DIVSEL) + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Разрешение записи в защищённые регистры периферии. */ + EALLOW; + /* Записывает SysCtrlRegs.WDKEY значением 0x0055; данные WDKEY. */ + SysCtrlRegs.WDKEY = 0x0055; + /* Записывает SysCtrlRegs.WDKEY значением 0x00AA; данные WDKEY. */ + SysCtrlRegs.WDKEY = 0x00AA; + /* Закрытие доступа к защищённым регистрам периферии. */ + EDIS; + /* Завершает ServiceDog без возвращаемого значения. */ + return; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} } + + +//--------------------------------------------------------------------------- +// Example: DisableDog: +//--------------------------------------------------------------------------- +// This function disables the watchdog timer. + +/* Начинает функцию DisableDog; назначение модуля — поставляемое TI описание SysCtrl для семейства C2833x. */ +void DisableDog(void) +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Разрешение записи в защищённые регистры периферии. */ + EALLOW; + /* Записывает SysCtrlRegs.WDCR значением 0x0068; данные WDCR. */ + SysCtrlRegs.WDCR= 0x0068; + /* Закрытие доступа к защищённым регистрам периферии. */ + EDIS; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + +//--------------------------------------------------------------------------- +// Example: InitPll: +//--------------------------------------------------------------------------- +// This function initializes the PLLCR register. + +/* Начинает функцию InitPll; назначение модуля — поставляемое TI описание SysCtrl для семейства C2833x. */ +void InitPll(Uint16 divval, Uint16 divsel) +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Объявляет clkVal — данные clkVal. */ + long clkVal; + + // Make sure the PLL is not running in limp mode + /* Проверяет if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0); последующий оператор выполняется только при истинном условии. */ + if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0) + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + // Missing external clock has been detected + // Replace this line with a call to an appropriate + // SystemShutdown(); function. + /* Вызывает asm с аргументами (" ESTOP0") в текущей последовательности операций. */ + asm(" ESTOP0"); + /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ + } + + // DIVSEL MUST be 0 before PLLCR can be changed from + // 0x0000. It is set to 0 by an external reset XRSn + // This puts us in 1/4 + /* Проверяет if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0); последующий оператор выполняется только при истинном условии. */ + if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0) + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Разрешение записи в защищённые регистры периферии. */ + EALLOW; + /* Записывает SysCtrlRegs.PLLSTS.bit.DIVSEL значением 0; данные DIVSEL. */ + SysCtrlRegs.PLLSTS.bit.DIVSEL = 0; + /* Закрытие доступа к защищённым регистрам периферии. */ + EDIS; + /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ + } + + // Change the PLLCR +// if (SysCtrlRegs.PLLCR.bit.DIV != val) + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + + /* Разрешение записи в защищённые регистры периферии. */ + EALLOW; + // Before setting PLLCR turn off missing clock detect logic + /* Записывает SysCtrlRegs.PLLSTS.bit.MCLKOFF значением 1; данные MCLKOFF. */ + SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1; + /* Записывает SysCtrlRegs.PLLCR.bit.DIV значением divval; данные DIV. */ + SysCtrlRegs.PLLCR.bit.DIV = divval; + /* Закрытие доступа к защищённым регистрам периферии. */ + EDIS; + + /* Записывает clkVal значением (divval)?divval:1; данные clkVal. */ + clkVal = (divval)?divval:1; + /* Записывает clkVal значением XCLKIN * clkVal; данные clkVal. */ + clkVal = XCLKIN * clkVal; + + // Optional: Wait for PLL to lock. + // During this time the CPU will switch to OSCCLK/2 until + // the PLL is stable. Once the PLL is stable the CPU will + // switch to the new PLL value. + // + // This time-to-lock is monitored by a PLL lock counter. + // + // Code is not required to sit and wait for the PLL to lock. + // However, if the code does anything that is timing critical, + // and requires the correct clock be locked, then it is best to + // wait until this switching has completed. + + // Wait for the PLL lock bit to be set. + + // The watchdog should be disabled before this loop, or fed within + // the loop via ServiceDog(). + + // Uncomment to disable the watchdog + /* Вызывает DisableDog с аргументами () в текущей последовательности операций. */ + DisableDog(); + + /* Повторяет или ожидает, пока выполняется while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1). */ + while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1) + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + // Uncomment to service the watchdog + // ServiceDog(); + /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ + } + + /* Разрешение записи в защищённые регистры периферии. */ + EALLOW; + /* Записывает SysCtrlRegs.PLLSTS.bit.MCLKOFF значением 0; данные MCLKOFF. */ + SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0; + /* Закрытие доступа к защищённым регистрам периферии. */ + EDIS; + /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ + } + + // If switching to 1/2 + /* Проверяет if((divsel == 1) или (divsel == 2)); последующий оператор выполняется только при истинном условии. */ + if((divsel == 1)||(divsel == 2)) + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Разрешение записи в защищённые регистры периферии. */ + EALLOW; + /* Записывает SysCtrlRegs.PLLSTS.bit.DIVSEL значением divsel; данные DIVSEL. */ + SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel; + /* Закрытие доступа к защищённым регистрам периферии. */ + EDIS; + /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ + } + + /* Проверяет if(divsel == 0) clkVal /= 4; последующий оператор выполняется только при истинном условии. */ + if(divsel == 0) clkVal /= 4; + /* Проверяет if(divsel == 1) clkVal /= 4; последующий оператор выполняется только при истинном условии. */ + if(divsel == 1) clkVal /= 4; + /* Проверяет if(divsel == 2) clkVal /= 2; последующий оператор выполняется только при истинном условии. */ + if(divsel == 2) clkVal /= 2; + + // If switching to 1/1 + // * First go to 1/2 and let the power settle + // The time required will depend on the system, this is only an example + // * Then switch to 1/1 + + /* Проверяет if((divval == 0) и (divsel == 3)); последующий оператор выполняется только при истинном условии. */ + if((divval == 0) && (divsel == 3)) + /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ + { + /* Разрешение записи в защищённые регистры периферии. */ + EALLOW; + /* Записывает SysCtrlRegs.PLLSTS.bit.DIVSEL значением 2; данные DIVSEL. */ + SysCtrlRegs.PLLSTS.bit.DIVSEL = 2; + /* Вызывает DELAY_US с аргументами (50L) в текущей последовательности операций. */ + DELAY_US(50L); +// pause_us(50L); + /* Записывает SysCtrlRegs.PLLSTS.bit.DIVSEL значением 3; данные DIVSEL. */ + SysCtrlRegs.PLLSTS.bit.DIVSEL = 3; + /* Закрытие доступа к защищённым регистрам периферии. */ + EDIS; + /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ + } + + /* Записывает SYSCLKOUT значением clkVal; данные SYSCLKOUT. */ + SYSCLKOUT = clkVal; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + +//-------------------------------------------------------------------------- +// Example: InitPeripheralClocks: +//--------------------------------------------------------------------------- +// This function initializes the clocks to the peripheral modules. +// First the high and low clock prescalers are set +// Second the clocks are enabled to each peripheral. +// To reduce power, leave clocks to unused peripherals disabled +// +// Note: If a peripherals clock is not enabled then you cannot +// read or write to the registers for that peripheral + +/* Начинает функцию InitPeripheralClocks; назначение модуля — поставляемое TI описание SysCtrl для семейства C2833x. */ +void InitPeripheralClocks(void) +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Объявляет Val — данные Val. */ + long Val; + + /* Разрешение записи в защищённые регистры периферии. */ + EALLOW; + +// HISPCP/LOSPCP prescale register settings, normally it will be set to default values + +/* Условие компиляции CLKMULT == 0: выбранный блок включается в текущий вариант прошивки. */ +#if CLKMULT == 0 + /* Записывает SysCtrlRegs.HISPCP.all значением 0x0000; представление регистра целым словом без разбиения на битовые поля. */ + SysCtrlRegs.HISPCP.all = 0x0000; +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции CLKMULT == 1: выбранный блок включается в текущий вариант прошивки. */ +#if CLKMULT == 1 + /* Записывает SysCtrlRegs.HISPCP.all значением 0x0000; представление регистра целым словом без разбиения на битовые поля. */ + SysCtrlRegs.HISPCP.all = 0x0000; +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции CLKMULT == 2: выбранный блок включается в текущий вариант прошивки. */ +#if CLKMULT == 2 + /* Записывает SysCtrlRegs.HISPCP.all значением 0x0001; представление регистра целым словом без разбиения на битовые поля. */ + SysCtrlRegs.HISPCP.all = 0x0001; +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции CLKMULT == 3: выбранный блок включается в текущий вариант прошивки. */ +#if CLKMULT == 3 + /* Записывает SysCtrlRegs.HISPCP.all значением 0x0002; представление регистра целым словом без разбиения на битовые поля. */ + SysCtrlRegs.HISPCP.all = 0x0002; +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции CLKMULT == 4: выбранный блок включается в текущий вариант прошивки. */ +#if CLKMULT == 4 + /* Записывает SysCtrlRegs.HISPCP.all значением 0x0002; представление регистра целым словом без разбиения на битовые поля. */ + SysCtrlRegs.HISPCP.all = 0x0002; +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif +/* Условие компиляции CLKMULT == 5: выбранный блок включается в текущий вариант прошивки. */ +#if CLKMULT == 5 + /* Записывает SysCtrlRegs.HISPCP.all значением 0x0003; представление регистра целым словом без разбиения на битовые поля. */ + SysCtrlRegs.HISPCP.all = 0x0003; +/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */ +#endif + + /* Записывает SysCtrlRegs.LOSPCP.all значением 0x0000; представление регистра целым словом без разбиения на битовые поля. */ + SysCtrlRegs.LOSPCP.all = 0x0000; + + /* Записывает Val значением (SysCtrlRegs.HISPCP.all)?; данные Val. */ + Val = (SysCtrlRegs.HISPCP.all)? + /* Продолжает список аргументов, полей или выражение SysCtrlRegs.HISPCP.all*2 : 1;; порядок элементов сохраняется. */ + SysCtrlRegs.HISPCP.all*2 : 1; + /* Записывает Val значением SYSCLKOUT / Val; данные Val. */ + Val = SYSCLKOUT / Val; + + /* Записывает HSPCLK значением Val; данные HSPCLK. */ + HSPCLK = Val; + + /* Записывает Val значением (SysCtrlRegs.LOSPCP.all)?; данные Val. */ + Val = (SysCtrlRegs.LOSPCP.all)? + /* Продолжает список аргументов, полей или выражение SysCtrlRegs.LOSPCP.all*2 : 1;; порядок элементов сохраняется. */ + SysCtrlRegs.LOSPCP.all*2 : 1; + /* Записывает Val значением SYSCLKOUT / Val; данные Val. */ + Val = SYSCLKOUT / Val; + /* Записывает LSPCLK значением Val; данные LSPCLK. */ + LSPCLK = Val; + +// XCLKOUT to SYSCLKOUT ratio. By default XCLKOUT = 1/4 SYSCLKOUT + // XTIMCLK = SYSCLKOUT/2 + /* Записывает XintfRegs.XINTCNF2.bit.XTIMCLK значением 1; данные XTIMCLK. */ + XintfRegs.XINTCNF2.bit.XTIMCLK = 1; + // XCLKOUT = XTIMCLK/2 + /* Записывает XintfRegs.XINTCNF2.bit.CLKMODE значением 1; данные CLKMODE. */ + XintfRegs.XINTCNF2.bit.CLKMODE = 1; + // Enable XCLKOUT + /* Записывает XintfRegs.XINTCNF2.bit.CLKOFF значением 0; данные CLKOFF. */ + XintfRegs.XINTCNF2.bit.CLKOFF = 0; + +// Peripheral clock enables set for the selected peripherals. +// If you are not using a peripheral leave the clock off +// to save on power. +// +// Note: not all peripherals are available on all 2833x derivates. +// Refer to the datasheet for your particular device. +// +// This function is not written to be an example of efficient code. + + /* Записывает SysCtrlRegs.PCLKCR0.bit.ADCENCLK значением 1; данные ADCENCLK. */ + SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // ADC + + // *IMPORTANT* + // The ADC_cal function, which copies the ADC calibration values from TI reserved + // OTP into the ADCREFSEL and ADCOFFTRIM registers, occurs automatically in the + // Boot ROM. If the boot ROM code is bypassed during the debug process, the + // following function MUST be called for the ADC to function according + // to specification. The clocks to the ADC MUST be enabled before calling this + // function. + // See the device data manual and/or the ADC Reference + // Manual for more information. + + /* Вызывает ADC_cal с аргументами () в текущей последовательности операций. */ + ADC_cal(); + + + /* Записывает SysCtrlRegs.PCLKCR0.bit.I2CAENCLK значением 1; данные I2CAENCLK. */ + SysCtrlRegs.PCLKCR0.bit.I2CAENCLK = 1; // I2C + /* Записывает SysCtrlRegs.PCLKCR0.bit.SCIAENCLK значением 1; данные SCIAENCLK. */ + SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1; // SCI-A + /* Записывает SysCtrlRegs.PCLKCR0.bit.SCIBENCLK значением 1; данные SCIBENCLK. */ + SysCtrlRegs.PCLKCR0.bit.SCIBENCLK = 1; // SCI-B + /* Записывает SysCtrlRegs.PCLKCR0.bit.SCICENCLK значением 1; данные SCICENCLK. */ + SysCtrlRegs.PCLKCR0.bit.SCICENCLK = 1; // SCI-C + /* Записывает SysCtrlRegs.PCLKCR0.bit.SPIAENCLK значением 1; данные SPIAENCLK. */ + SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1; // SPI-A + /* Записывает SysCtrlRegs.PCLKCR0.bit.MCBSPAENCLK значением 1; данные MCBSPAENCLK. */ + SysCtrlRegs.PCLKCR0.bit.MCBSPAENCLK = 1; // McBSP-A + /* Записывает SysCtrlRegs.PCLKCR0.bit.MCBSPBENCLK значением 1; данные MCBSPBENCLK. */ + SysCtrlRegs.PCLKCR0.bit.MCBSPBENCLK = 1; // McBSP-B + /* Записывает SysCtrlRegs.PCLKCR0.bit.ECANAENCLK значением 1; данные ECANAENCLK. */ + SysCtrlRegs.PCLKCR0.bit.ECANAENCLK=1; // eCAN-A + /* Записывает SysCtrlRegs.PCLKCR0.bit.ECANBENCLK значением 1; данные ECANBENCLK. */ + SysCtrlRegs.PCLKCR0.bit.ECANBENCLK=1; // eCAN-B + + /* Записывает SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC значением 0; данные TBCLKSYNC. */ + SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Disable TBCLK within the ePWM + /* Записывает SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK значением 1; данные EPWM1ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1; // ePWM1 + /* Записывает SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK значением 1; данные EPWM2ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK = 1; // ePWM2 + /* Записывает SysCtrlRegs.PCLKCR1.bit.EPWM3ENCLK значением 1; данные EPWM3ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.EPWM3ENCLK = 1; // ePWM3 + /* Записывает SysCtrlRegs.PCLKCR1.bit.EPWM4ENCLK значением 1; данные EPWM4ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.EPWM4ENCLK = 1; // ePWM4 + /* Записывает SysCtrlRegs.PCLKCR1.bit.EPWM5ENCLK значением 1; данные EPWM5ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.EPWM5ENCLK = 1; // ePWM5 + /* Записывает SysCtrlRegs.PCLKCR1.bit.EPWM6ENCLK значением 1; данные EPWM6ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.EPWM6ENCLK = 1; // ePWM6 + /* Записывает SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC значением 1; данные TBCLKSYNC. */ + SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Enable TBCLK within the ePWM + + /* Записывает SysCtrlRegs.PCLKCR1.bit.ECAP3ENCLK значением 1; данные ECAP3ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.ECAP3ENCLK = 1; // eCAP3 + /* Записывает SysCtrlRegs.PCLKCR1.bit.ECAP4ENCLK значением 1; данные ECAP4ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.ECAP4ENCLK = 1; // eCAP4 + /* Записывает SysCtrlRegs.PCLKCR1.bit.ECAP5ENCLK значением 1; данные ECAP5ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.ECAP5ENCLK = 1; // eCAP5 + /* Записывает SysCtrlRegs.PCLKCR1.bit.ECAP6ENCLK значением 1; данные ECAP6ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.ECAP6ENCLK = 1; // eCAP6 + /* Записывает SysCtrlRegs.PCLKCR1.bit.ECAP1ENCLK значением 1; данные ECAP1ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.ECAP1ENCLK = 1; // eCAP1 + /* Записывает SysCtrlRegs.PCLKCR1.bit.ECAP2ENCLK значением 1; данные ECAP2ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.ECAP2ENCLK = 1; // eCAP2 + /* Записывает SysCtrlRegs.PCLKCR1.bit.EQEP1ENCLK значением 1; данные EQEP1ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.EQEP1ENCLK = 1; // eQEP1 + /* Записывает SysCtrlRegs.PCLKCR1.bit.EQEP2ENCLK значением 1; данные EQEP2ENCLK. */ + SysCtrlRegs.PCLKCR1.bit.EQEP2ENCLK = 1; // eQEP2 + + /* Записывает SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK значением 1; данные CPUTIMER0ENCLK. */ + SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; // CPU Timer 0 + /* Записывает SysCtrlRegs.PCLKCR3.bit.CPUTIMER1ENCLK значением 1; данные CPUTIMER1ENCLK. */ + SysCtrlRegs.PCLKCR3.bit.CPUTIMER1ENCLK = 1; // CPU Timer 1 + /* Записывает SysCtrlRegs.PCLKCR3.bit.CPUTIMER2ENCLK значением 1; данные CPUTIMER2ENCLK. */ + SysCtrlRegs.PCLKCR3.bit.CPUTIMER2ENCLK = 1; // CPU Timer 2 + + /* Записывает SysCtrlRegs.PCLKCR3.bit.DMAENCLK значением 1; данные DMAENCLK. */ + SysCtrlRegs.PCLKCR3.bit.DMAENCLK = 1; // DMA Clock + /* Записывает SysCtrlRegs.PCLKCR3.bit.XINTFENCLK значением 1; данные XINTFENCLK. */ + SysCtrlRegs.PCLKCR3.bit.XINTFENCLK = 1; // XTIMCLK + /* Записывает SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK значением 1; аппаратная линия ввода/вывода GPIOINENCLK. */ + SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1; // GPIO input clock + + /* Закрытие доступа к защищённым регистрам периферии. */ + EDIS; +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + +//--------------------------------------------------------------------------- +// Example: CsmUnlock: +//--------------------------------------------------------------------------- +// This function unlocks the CSM. User must replace 0xFFFF's with current +// password for the DSP. Returns 1 if unlock is successful. + +/* Задаёт STATUS_FAIL = 0; состояние FAIL. */ +#define STATUS_FAIL 0 +/* Задаёт STATUS_SUCCESS = 1; состояние SUCCESS. */ +#define STATUS_SUCCESS 1 + +/* Начинает функцию CsmUnlock; назначение модуля — поставляемое TI описание SysCtrl для семейства C2833x. */ +Uint16 CsmUnlock() +/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ +{ + /* Объявляет temp — данные temp. volatile требует фактического чтения или записи при каждом доступе. */ + volatile Uint16 temp; + + // Load the key registers with the current password. The 0xFFFF's are dummy + // passwords. User should replace them with the correct password for the DSP. + + /* Разрешение записи в защищённые регистры периферии. */ + EALLOW; + /* Записывает CsmRegs.KEY0 значением 0xFFFF; данные KEY0. */ + CsmRegs.KEY0 = 0xFFFF; + /* Записывает CsmRegs.KEY1 значением 0xFFFF; данные KEY1. */ + CsmRegs.KEY1 = 0xFFFF; + /* Записывает CsmRegs.KEY2 значением 0xFFFF; данные KEY2. */ + CsmRegs.KEY2 = 0xFFFF; + /* Записывает CsmRegs.KEY3 значением 0xFFFF; данные KEY3. */ + CsmRegs.KEY3 = 0xFFFF; + /* Записывает CsmRegs.KEY4 значением 0xFFFF; данные KEY4. */ + CsmRegs.KEY4 = 0xFFFF; + /* Записывает CsmRegs.KEY5 значением 0xFFFF; данные KEY5. */ + CsmRegs.KEY5 = 0xFFFF; + /* Записывает CsmRegs.KEY6 значением 0xFFFF; данные KEY6. */ + CsmRegs.KEY6 = 0xFFFF; + /* Записывает CsmRegs.KEY7 значением 0xFFFF; данные KEY7. */ + CsmRegs.KEY7 = 0xFFFF; + /* Закрытие доступа к защищённым регистрам периферии. */ + EDIS; + + // Perform a dummy read of the password locations + // if they match the key values, the CSM will unlock + + /* Записывает temp значением CsmPwl.PSWD0; данные temp. */ + temp = CsmPwl.PSWD0; + /* Записывает temp значением CsmPwl.PSWD1; данные temp. */ + temp = CsmPwl.PSWD1; + /* Записывает temp значением CsmPwl.PSWD2; данные temp. */ + temp = CsmPwl.PSWD2; + /* Записывает temp значением CsmPwl.PSWD3; данные temp. */ + temp = CsmPwl.PSWD3; + /* Записывает temp значением CsmPwl.PSWD4; данные temp. */ + temp = CsmPwl.PSWD4; + /* Записывает temp значением CsmPwl.PSWD5; данные temp. */ + temp = CsmPwl.PSWD5; + /* Записывает temp значением CsmPwl.PSWD6; данные temp. */ + temp = CsmPwl.PSWD6; + /* Записывает temp значением CsmPwl.PSWD7; данные temp. */ + temp = CsmPwl.PSWD7; + + // If the CSM unlocked, return succes, otherwise return + // failure. + /* Проверяет if (CsmRegs.CSMSCR.bit.SECURE == 0) return STATUS_SUCCESS; последующий оператор выполняется только при истинном условии. */ + if (CsmRegs.CSMSCR.bit.SECURE == 0) return STATUS_SUCCESS; + /* Выполняет альтернативу, если предыдущее условие if оказалось ложным. */ + else return STATUS_FAIL; + +/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ +} + + +//=========================================================================== +// End of file. +//=========================================================================== diff --git a/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_usDelay.asm b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_usDelay.asm new file mode 100644 index 0000000..9425409 --- /dev/null +++ b/c/protocan-boot/vendor/ti/f28335/source/DSP2833x_usDelay.asm @@ -0,0 +1,84 @@ +; Поставляемое ti описание usdelay для семейства c2833x. Пояснения в UTF-8. +;// TI File $Revision: /main/4 $ +;// Checkin $Date: July 30, 2007 10:28:57 $ +;//########################################################################### +;// +;// FILE: DSP2833x_usDelay.asm +;// +;// TITLE: Simple delay function +;// +;// DESCRIPTION: +;// +;// This is a simple delay function that can be used to insert a specified +;// delay into code. +;// +;// This function is only accurate if executed from internal zero-waitstate +;// SARAM. If it is executed from waitstate memory then the delay will be +;// longer then specified. +;// +;// To use this function: +;// +;// 1 - update the CPU clock speed in the DSP2833x_Examples.h +;// file. For example: +;// #define CPU_RATE 6.667L // for a 150MHz CPU clock speed +;// or #define CPU_RATE 10.000L // for a 100MHz CPU clock speed +;// +;// 2 - Call this function by using the DELAY_US(A) macro +;// that is defined in the DSP2833x_Examples.h file. This macro +;// will convert the number of microseconds specified +;// into a loop count for use with this function. +;// This count will be based on the CPU frequency you specify. +;// +;// 3 - For the most accurate delay +;// - Execute this function in 0 waitstate RAM. +;// - Disable interrupts before calling the function +;// If you do not disable interrupts, then think of +;// this as an "at least" delay function as the actual +;// delay may be longer. +;// +;// The C assembly call from the DELAY_US(time) macro will +;// look as follows: +;// +;// extern void Delay(long LoopCount); +;// +;// MOV AL,#LowLoopCount +;// MOV AH,#HighLoopCount +;// LCR _Delay +;// +;// Or as follows (if count is less then 16-bits): +;// +;// MOV ACC,#LoopCount +;// LCR _Delay +;// +;// +;//########################################################################### +;// $TI Release: DSP2833x/DSP2823x Header Files V1.20 $ +;// $Release Date: August 1, 2008 $ +;//########################################################################### + + ; Экспортирует символ для связывания с C-кодом. Операция: .def _DSP28x_usDelay. + .def _DSP28x_usDelay + ; Выбирает секцию объектного файла для следующих инструкций. Операция: .sect ".text". + .sect ".text" + + ; Объявляет глобальный символ для линкера. Операция: .global __DSP28x_usDelay. + .global __DSP28x_usDelay +; Объявляет метку _DSP28x_usDelay: для перехода или вызова. Операция: _DSP28x_usDelay:. +_DSP28x_usDelay: + ; Вычитает операнд и обновляет арифметическое состояние. Операция: SUB ACC,#1. + SUB ACC,#1 + ; Выполняет условный переход по флагам результата. Операция: BF _DSP28x_usDelay,GEQ. + BF _DSP28x_usDelay,GEQ ;; Loop if ACC >= 0 + ; Возвращает управление вызывающему коду через длинный адрес возврата. Операция: LRETR. + LRETR + +;There is a 9/10 cycle overhead and each loop +;takes five cycles. The LoopCount is given by +;the following formula: +; DELAY_CPU_CYCLES = 9 + 5*LoopCount +; LoopCount = (DELAY_CPU_CYCLES - 9) / 5 +; The macro DELAY_US(A) performs this calculation for you +; +;//=========================================================================== +;// End of file. +;//=========================================================================== diff --git a/c/set-protocol/CMakeLists.txt b/c/set-protocol/CMakeLists.txt index 6a6b56d..39a83b5 100644 --- a/c/set-protocol/CMakeLists.txt +++ b/c/set-protocol/CMakeLists.txt @@ -20,6 +20,7 @@ set(SETPROTOCOL_V2_SOURCES src/set_telemetry.c src/set_plot.c src/set_trends.c + src/set_gas_watch.c # Собирает единый кодек GAS_WATCH2 и MCU-захват выбранных GAS-слов для static/shared целей. src/set_spectrum.c src/set_signal.c src/set_wavegen.c @@ -37,6 +38,7 @@ set(SETPROTOCOL_LEGACY_SOURCES src/pcan_crc.c src/pcan_frame.c src/pcan_gas.c + src/pcan_gas_slot.c # Собирает GAS SLOT типа 0x4 с Word0-маской и тремя значениями независимо от регистрового GAS 0x3. src/pcan_id.c src/pcan_link.c src/pcan_modbus_server.c @@ -44,10 +46,13 @@ set(SETPROTOCOL_LEGACY_SOURCES ) set(SETPROTOCOL_SOURCES + src/deif_xdi.c # Общее C99-ядро DEIF для всех платформ. + src/set_invertor_gas.c # Подключает две проекции одной карты STM Invertor: GAS 0x3 и масочный GAS SLOT 0x4. src/set_regmap.c src/set_emu_ump.c src/set_emu_tms.c src/set_emu_igbt.c + src/set_igbt_realtime.c # Общий аппаратный IGBT v4 использует нс, сохраняя прежнюю модель v3 и её ABI. src/set_emu_server.c ${SETPROTOCOL_V2_SOURCES} ${SETPROTOCOL_LEGACY_SOURCES} @@ -94,6 +99,18 @@ endif() option(SETP_BUILD_TESTS "Build host tests" ON) if(SETP_BUILD_TESTS) enable_testing() + add_executable(test_deif_xdi tests/test_deif_xdi.c) # Прямые проверки C-контракта DEIF. + target_link_libraries(test_deif_xdi PRIVATE setprotocol_static) # Используется единственное общее ядро. + add_test(NAME deif_xdi COMMAND test_deif_xdi "${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/deif-xdi-v1.tsv") # Векторы общие с JNI и Python. + add_executable(test_invertor_gas tests/test_invertor_gas.c) # Проверяет два формата, общие значения, маски, границы и транзакционные callbacks. + target_link_libraries(test_invertor_gas PRIVATE setprotocol_static) # Проверяем ту же реализацию, что подключается к прошивке. + add_test(NAME invertor_gas COMMAND test_invertor_gas) # Новый контракт выполняется стандартным CTest вместе с остальными протоколами. + add_executable(test_gas_register tests/test_gas_register.c) # Проверяет запись одной уставки без соседей, границы 0…65535 и изоляцию типа 0x3. + target_link_libraries(test_gas_register PRIVATE setprotocol_static) # Запускает проверки на том же ядре, которое используют прошивки и host-клиенты. + add_test(NAME protocan_gas_register COMMAND test_gas_register) # Отдельный тест защищает восстановленный регистровый контракт. + add_executable(test_gas_slot tests/test_gas_slot.c) # Проверяет MsgType=0x4, маску Word0, сохранение соседей и границы PERIPH. + target_link_libraries(test_gas_slot PRIVATE setprotocol_static) # Использует ту же библиотеку, что MCU и клиенты. + add_test(NAME protocan_gas_slot COMMAND test_gas_slot) # Делает проверку нового формата частью штатного CTest. add_executable(test_emulator_services tests/test_emulator_services.c ports/example-emulator/service.c) target_link_libraries(test_emulator_services PRIVATE setprotocol_static) add_test(NAME emulator_services COMMAND test_emulator_services) @@ -170,6 +187,9 @@ if(SETP_BUILD_TESTS) add_executable(test_trends tests/test_trends.c) target_link_libraries(test_trends PRIVATE setprotocol_static) add_test(NAME shared_trends COMMAND test_trends) + add_executable(test_gas_watch tests/test_gas_watch.c) # Собирает транзакционные проверки конфигурации и эталонных байтов GAS_WATCH2. + target_link_libraries(test_gas_watch PRIVATE setprotocol_static) # Проверяет настоящее общее ядро, а не копию алгоритма в тесте. + add_test(NAME gas_watch_v2 COMMAND test_gas_watch) # Регистрирует новый контракт рядом с неизменёнными legacy-проверками. add_executable(test_spectrum tests/test_spectrum.c) target_link_libraries(test_spectrum PRIVATE setprotocol_static) add_test(NAME shared_spectrum COMMAND test_spectrum) diff --git a/c/set-protocol/README.md b/c/set-protocol/README.md index 170cc1b..0320214 100644 --- a/c/set-protocol/README.md +++ b/c/set-protocol/README.md @@ -1,5 +1,10 @@ # SETProtocol +Пакетный сбор выбранных GAS-регистров: [GAS_WATCH2](docs/GAS_WATCH2.md). +Конфигурация применяется целиком; выборка содержит поколение списка, +номер захвата, время устройства и достоверность каждого слова. Старый GAS_WATCH +сохраняет формат; новые C/ctypes/JNI-адаптеры включаются явно. + `periph28335_eeprom_*` — read-only reader физической EEPROM Бальзам-167 (AT25256B, 32 КиБ), со стабильным C ABI и портом `python/protocan/periph28335_eeprom.py`. Разметка платы задана в @@ -112,3 +117,7 @@ FFI-клиенты подключают `setprotocol_abi.h`. Имена функ [PLOT_PROCESSING.md](docs/PLOT_PROCESSING.md). Генератор сигнала, USB и порты ЦАП F407/G474: [SIGNAL_GENERATOR.md](docs/SIGNAL_GENERATOR.md). + +## GAS: регистры 0x3 и слоты 0x4 + +[Адресация GAS](docs/GAS_SLOT.md): `0x3` — отдельные 16-битные регистры `0…65535`, запись 1…4 слов. `0x4` — слот с Word0-маской и тремя значениями; PERIPH сохраняет 200 слов в 67 слотах `0xMM00…0xMM42`. Формат определяется MsgType, без настройки профиля. diff --git a/c/set-protocol/docs/DEIF_XDI.md b/c/set-protocol/docs/DEIF_XDI.md new file mode 100644 index 0000000..5247930 --- /dev/null +++ b/c/set-protocol/docs/DEIF_XDI.md @@ -0,0 +1,132 @@ +# Общее ядро DEIF XDi / CANopen + +Единственная реализация профиля DEIF находится в `include/deif_xdi.h` и +`src/deif_xdi.c`. Desktop использует её через `python/set_devices/deif_native.py`, +Android — через `ports/android/set_deif_jni.c` и `deif/DeifXdi.kt`. +Кодеки, адресация, числовой каталог, NMT, сроки, SDO и выбор азимута +не реализуются повторно в Python или Kotlin. + +Основание профиля: DEIF XDi-net/CANopen reference manual 4189350066D, +§§1–3, §9.11, Appendix 3 и Appendix 5. Набор переменных соответствует +наблюдаемой библиотеке: азимут, RPM, RPM%, мощность AC2 и POWER%. +Абсолютная мощность остаётся RAW до подтверждения её физической единицы. + +## Два режима + +- **Пассивный наблюдатель** принимает данные без включения симуляции, + ничего не отправляет, скрывает устаревшее показание через пять секунд. +- **CAN-SLAVE** принимает данные от внешнего MASTER и производит Boot-up, + heartbeat, EMCY и ответы на явно поддерживаемые SDO. После 3000 мс без + обновления поля сохраняет последнее валидное число и сообщает Data lost; + мигание выполняет GUI по готовой маске устаревших входов. + +Пассивный режим предназначен в том числе для обычного приёма показаний +без занятия собственного Node-ID в сети. На MPDO в активном режиме +также нет ответного PDO. В нормальном обмене SLAVE передаёт heartbeat. + +## Азимут + +Фактическое значение `0x3001:02` и сетевое задание `0x3001:07` хранятся +независимо. `setp_deif_angle` возвращает значение и его тип: + +- `0` — пригодного показания нет; +- `1` — фактический угол; +- `2` — принятое задание, которое GUI обязан подписывать как задание. + +При исходной привязке фактического угла до первого кадра `0x02` допускается +показывать принятое `0x07`. После первого фактического кадра задание его +не подменяет. Ошибочный фактический I16 также не заменяется старым заданием. +Явная ручная привязка к `0x07` остаётся индикатором задания. +Локальный черновик MASTER не входит в состояние C-модели. + +Эталонный кадр `STD 0x201 / 01 01 30 07 84 03 00 00` должен показывать +**90° · задание** и при выключенной симуляции. Node-ID физического SLAVE +не является источником этой SAM-рассылки: источник здесь Node 1. + +## Адресация и сервисы + +SAM согласует источник с COB-ID и поддерживает legacy broadcast `0x27F`. +DAM проверяет собственный Node-ID и выбранный RPDO. XDi-net резервирует +RPDO1 для SAM и Node 127 для сервисного прибора. Чистый CANopen допускает +DAM RPDO1. Все кадры профиля являются Classic CAN STD data frames. + +После Boot-up выдаётся Pre-operational; стандартный self-start занимает +1000 мс. Исходный период heartbeat — 500 мс. NMT Start/Stop/Pre-operational, +Reset node и Reset communication принимаются только для собственного узла +либо broadcast 0. Reset communication сохраняет прикладные значения и +возвращает несохранённые коммуникационные параметры к исходным значениям. + +SDO обслуживается в Operational и Pre-operational, в Stopped не отвечает. +Чтение: `0x1000:00`, `0x1001:00`, `0x1017:00`, `0x1018:00/01` и привязанные +I16-переменные. До обновления переменной возвращается `0x7FFF`. +Запись: U16 `0x1017:00`. Ноль отключает HB только вне XDi-net. +Неизвестный индекс, подиндекс, неподдерживаемая запись или команда дают +стандартный SDO abort. Серийный номер и код конкретного изделия не выдумываются. + +Это явный поднабор профиля индикации, а не полный EDS прошивки. LSS, +segmented SDO, EEPROM, произвольные конфигурационные записи, TPDO mapping, +двухканальное резервирование и механика привода не моделируются. + +## Контракт портов + +Память состояния выделяет вызывающий через `setp_deif_state_size`. +Буфер должен иметь выравнивание не слабее `uint64_t`; ctypes использует +массив `uint64`, JNI — direct ByteBuffer. Private-layout состояния не +передаётся между языками и не сериализуется. + +Все часы передаются как монотонные миллисекунды. C не вызывает ОС, +не использует Qt/JVM и не выделяет динамическую память. Каждый прибор +имеет отдельный контекст. JNI-порт сериализует операции экземпляра. + +`setp_deif_poll` выдаёт готовые кадры однократно. Порт обслуживает его +регулярно и после запросов SDO; очередь ограничена 16 событиями. Экранная +пауза CAN-журнала не должна останавливать протокол. Потеря подключения, +ошибка TX и закрытие владельца останавливают активный сервер. + +`setp_deif_make/master/service/angle_command` создают готовые сообщения. +`setp_deif_selector_info/readdress/route` обслуживают редакторы профиля: +UI не извлекает endian, смещения или адресные маски самостоятельно. +Локализованные тексты и мигание готовых показаний остаются в GUI. + +При отсутствии нативного ядра порт выдаёт явную ошибку. Python/Kotlin +fallback протокола отсутствует. Windows source build может использовать +дополнительную сборку того же C-ядра `setprotocol_deif.dll`; путь задаёт +приложение либо стандартный загрузчик находит компонент рядом с основной +DLL. Новый автономный EXE использует собственную основную DLL с DEIF. + +## Android/JVM: настройки и локальный стенд + +`DeifSettings` хранит профиль SLAVE, независимые параметры MASTER, +выбор пяти отправляемых объектов, калибровки управления, единицу POWER +и ручные привязки. Сериализация не сохраняет запуск симуляции или таймеров. +`readdressed` переносит связанные SAM/DAM-адреса через C, сохраняя отдельные +ручные источники, индексы объектов и масштабы. + +`DeifWorkspace` объединяет пассивное наблюдение, физический CAN-SLAVE +и автономный стенд. Он получает монотонное время от приложения и возвращает +готовые кадры раздельными маршрутами MASTER и SLAVE. Локальная симуляция +не возвращает физические кадры; остановленный локальный SLAVE отклоняет +MASTER и команды экрана вместо переключения на адаптер. +NMT разрешён только работающему локальному SLAVE. Физический сервер +отклоняет запуск встроенного MASTER. + +`DeifXdi.master/make/service/selector/bind/binding/selectorInfo/readdress/validate` +являются тонкими вызовами существующего C ABI. Порты не строят COB-ID, +индексы, little-endian I16, NMT или диммер повторно. Перевод касания +в заданный пользователем масштаб относится к управлению интерфейсом; +интерактивная отрисовка, отдельное подтверждение яркости и палитры, +хранилище настроек, USB и жизненный цикл остаются у приложения. + +`DeifWorkspaceTest` проверяет точные builders, автономный приём интерактивных +заданий, отсутствие физического TX на локальном стенде, ограничения NMT, +независимые периоды MASTER/heartbeat, ошибки JNI, сохранение профиля +и перенос адресов без потери ручных привязок. + +## Проверки + +`tests/fixtures/deif-xdi-v1.tsv` — единые эталонные байты для C, Python и JNI. +Их используют `tests/test_deif_xdi.c`, `python/tests/test_deif_shared.py` и +`ports/android/tests/.../deif/DeifXdiTest.kt`. Отдельно проверяются пассивные +90°, независимый фактический угол, Boot-up, NMT, heartbeat и отсутствие +выдуманного ответного PDO. Desktop дополнительно проверяет миграцию старой +пустой привязки без включения симуляции и без физического TX. diff --git a/c/set-protocol/docs/GAS_SLOT.md b/c/set-protocol/docs/GAS_SLOT.md new file mode 100644 index 0000000..e2274c3 --- /dev/null +++ b/c/set-protocol/docs/GAS_SLOT.md @@ -0,0 +1,27 @@ +# GAS SLOT 0x4: маска в Word0 + +Нормативный контракт: [ОАП](../../../doc/setcan/protocan/OAP.md). GAS `0x3` адресует отдельные 16-битные регистры; GAS SLOT `0x4` использует собственный адрес слота и заменяет прежний Modbus Coil. + +Один кадр: `Word0=маска`, `Word1`, `Word2`, `Word3`; все слова little-endian. В Word0 допустимы только непустые комбинации битов 1…3 (`0x0002…0x000E` с нулевым битом 0). Бит выбирает одноимённое слово. Запись всегда DLC=8; невыбранные значения игнорируются и сохраняются в устройстве. `DLC=0` запрашивает чтение; ответ DLC=8 содержит маску достоверных слов. RTR, standard/error frame, пустой ответ и усечённые данные отвергаются. + +Изменить только Word2 на `0x1234`: payload `04 00 00 00 34 12 00 00`. Полная запись трёх значений использует маску `0x000E`. Word0 — метаданные, не четвёртый регистр. + +## MCU + +`pcan_gas_slot_handle_address(type, id, port, request, response)` обслуживает любой узел и слот 0…65535. Возвращает 1 при ответе, 0 после записи, -1 при отказе. Provider чтения заполняет четыре wire-слова, включая Word0-маску; provider записи сначала проверяет все выбранные права и значения, затем изменяет только отмеченные позиции под общей блокировкой. Кодек не гарантирует транзакционность внешних Flash/callback операций. + +`pcan_gas_slot_handle(mode, ...)` дополнительно проверяет страницу PERIPH. `Slot=(mode<<8)|LocalSlot`, LocalSlot 0…66. Три значения на слот сохраняют 200 слов на mode; в последнем слоте доступны Word1/Word2. `pcan_gas_slot_native(local, word, write, &address)` принимает word 1…3 и переводит `3*local+word-1` в прежние native-сервисы. Нулевая позиция, резерв и запрещённая запись отвергаются. + +Вызывать обработчик из главного цикла/задачи; ISR только принимает кадры. DLC измеряется wire-октетами, в том числе на C28x с 16-битным char. Общий формат не выделяет все 384 КиБ логического пространства в RAM. + +## Python и Android + +`GasSlots.frame(5, 0)` возвращает `(0x11540500, b'')`. `frame(5, 0, [0x0004, 0, 0x1234, 0])` меняет только Word2. `frame_address(7, 14, 65535, [...])` адресует независимый узел и полный 16-битный слот. `decode()` проверяет PERIPH, `decode_address()` — общий формат. Wire-маска и endian формируются единственным C-кодеком. + +Android/JNI: `nativeRequestId`/`nativeDecode` для PERIPH; `nativeAddressId`/`nativeDecodeWords` для общего узла; `nativeEncode` принимает маску и три значения. Пустой запрос возвращает пустой набор значений; ошибка — null. + +В CAN-журнале тип 0x4 выбирается автоматически по MsgType. Параметра `gas_profile` нет; 0x3 всегда отображается как регистры. GAS_WATCH2 и регистровые провайдеры 0x3 сохраняют адреса и ABI. + +## Проверки + +CTest: `protocan_gas_register`, `protocan_gas_slot`, `protocan_modbus_server`; Python: `test_gas_slots.py`; JNI host smoke. Общие эталоны: `doc/setcan/protocan/examples/gas-slot-vectors.json`. Старые узлы Coil 0x4 несовместимы с новым назначением и обновляются согласованно. diff --git a/c/set-protocol/docs/GAS_WATCH2.md b/c/set-protocol/docs/GAS_WATCH2.md new file mode 100644 index 0000000..f3261f7 --- /dev/null +++ b/c/set-protocol/docs/GAS_WATCH2.md @@ -0,0 +1,202 @@ +# GAS_WATCH2: список адресов и пакетная выборка + +> GAS `0x3` использует адреса отдельных 16-битных регистров. GAS SLOT `0x4` — отдельный сервис с маской в Word0 и тремя значениями Word1…Word3. Спецификация: `doc/setcan/protocan/OAP.md`; адреса этого документа остаются регистровыми. + +`include/set_gas_watch.h` и `src/set_gas_watch.c` реализуют выбранный клиентом +список GAS-регистров, транзакционную настройку и захват значений в отдельную +структуру. График и архив могут использовать одну готовую выборку. +Ядро — C99, без HAL, часов ОС, heap, глобального состояния и драйверов связи. + +Старые `gui_watch_t`, `GAS_WATCH_SET` / `GAS_WATCH_DATA` и ABI +`set_trend_watch_*` сохраняют сигнатуры и побайтовый формат. +Расширение включается явно и не меняет существующую типизированную +телеметрию `set_telemetry` / SETProtocol v2 `SUBSCRIBE`. + +## Что подключается к МК + +Код `templates` компилируется в прошивку. Она создаёт `set_gas_watch_t` +в собственной RAM, предоставляет `pcan_gas_map_t` и вызывает API из своего +диспетчера команд и таймера. Нового процесса или среды исполнения на МК нет. + +| Компонент | Ответственность | +|---|---| +| `set_gas_watch_t` | Собственная копия списка адресов, период, поколение и расписание | +| `set_gas_watch_sample_t` | Значения, достоверность каждого слова, время и номер захвата | +| `pcan_gas_map_t` | Доступ к RAM/обработчикам источников; GAS-адрес не является указателем MCU | +| Порт платы | Блокировка, локальное время, таймер, диспетчер и очередь передачи | +| Python/JNI/Kotlin | Преобразование моделей и pending/active без второго кодека | +| GUI | Имена, типы, масштаб, цвет, видимость и объединение запросов вкладок | + +Минимальные исходники: `set_gas_watch.c`, `pcan_gas.c`, `pcan_id.c`, +`set_protocol.c`; заголовки берутся из `include`. Полная CMake/NDK/host-сборка +уже включает новый модуль. Состояние и выборка используют ограниченные +массивы; реальные размеры структур определяются `sizeof` на целевом MCU. + +Пример последовательности вызовов в прошивке: + +```c +#include "set_gas_watch.h" /* Подключает список GAS-слов и независимый от транспорта захват. */ +static set_gas_watch_t watch; /* Хранит одну управляемую подписку в RAM платы; память выделяет проект. */ +static set_gas_watch_sample_t sample; /* Сохраняет выборку до завершения работы всех её потребителей. */ +/* При старте сессии: set_gas_watch_init(&watch); память и timer предоставляет прошивка. */ +/* В диспетчере, под общей блокировкой: set_gas_watch_apply(&watch, &map, payload, size). */ +/* При успехе, под той же блокировкой: set_gas_watch_encode_ack(&watch, tx, sizeof(tx)). */ +/* После снятия блокировки: отправить ACK транспортом проекта, при ошибке вернуть NACK/статус. */ +/* В таймере, под общей блокировкой: проверить set_gas_watch_due(&watch, now_ms). */ +/* Когда пора: set_gas_watch_capture(&watch, &map, now_ms, &sample), затем снять блокировку. */ +/* В задаче передачи: set_gas_watch_encode_sample(&sample, tx, sizeof(tx)), затем поставить tx в очередь. */ +``` + +Пример показывает места вызовов; проект предоставляет `map`, `payload`, +буферы, `now_ms`, lock и транспорт. Он обязан проверять результаты API. +Для `[0x0000, 0x0001, 0xFF01]` ядро читает три разрозненных GAS-слова +и формирует один логический пакет, не читая промежуточный диапазон. +Адреса передаются при настройке; DATA содержит значения и метаданные. + +## Настройка и поколения + +Набор ограничен **64 словами по 16 бит**, а не 64 произвольными параметрами. +Многословный параметр занимает несколько позиций. Дубли адресов отклоняются; +владелец подписки объединяет запросы вкладок до отправки. + +`set_gas_watch_request` проверяет модель и строит payload. +`set_gas_watch_apply` проверяет весь пакет и карту: все адреса должны +существовать, разрешать чтение и иметь RAM либо callback чтения. Проверка +не вызывает источники. Отказ сохраняет прежние адреса, период, sequence и +расписание. Частичного принятия нет; коды заданы в `set_gas_watch_result_t`. + +`config_id` — ненулевой 32-битный номер, назначаемый управляющим клиентом. +Любое изменение периода или порядка/состава адресов требует нового поколения. +После первой команды принимается модульная разность `new_id - old_id` +в диапазоне `1..0x7FFFFFFF`. Переход `0xFFFFFFFF → 1` допустим, ноль +зарезервирован. Разрыв между последовательными поколениями меньше `2^31`. +Поколения нельзя переиспользовать, пока в обмене могут оставаться старые пакеты. + +Точный повтор действующего id со всем прежним содержимым успешен и не +сбрасывает захват: потерянный ACK можно запросить повторно. Тот же id +с другим содержимым, старый id и разность `2^31` дают `SET_GAS_WATCH_CONFLICT`. +Остановка — новая конфигурация `period_ms = 0, count = 0`, карта не требуется. +Пустой список с ненулевым периодом и непустой список с нулевым запрещены. + +`set_gas_watch_encode_ack` возвращает полную применённую конфигурацию, +включая адреса. Клиент проверяет её через `set_gas_watch_ack` и заменяет +active только после успеха. Новая команда хранится как pending; DATA +сопоставляются с active. ACK уже заменённого pending отвергается. +Ошибка команды/ACK сохраняет прежний active. + +Один экземпляр обслуживает одного управляющего клиента. Если устройство +сохранило состояние после переподключения, клиент продолжает номера поколений. +`reset()` адаптера очищает только его pending/active, не посылает stop +и не сбрасывает устройство. Проект может явно вызвать `set_gas_watch_init` +при завершении управляющей сессии, разрешив новой сессии произвольный первый id. + +## Захват и синхронизация + +Приложение сериализует все обращения к состоянию, изменения карты, +обновления исходного кэша и захват одним подходящим lock/IRQ-портом. +Транзакционность API означает отсутствие частичной настройки при ошибке; +присваивание C-структуры само по себе не даёт межпоточную атомарность. +Ядро не управляет IRQ и не содержит скрытых ожиданий. + +Под lock выполняются применение конфигурации, подготовка ACK, +проверка `set_gas_watch_due` и `set_gas_watch_capture`. Сам `capture` +допускает явный захват вне расписания и не проверяет due. +После снятия lock приложение кодирует готовую выборку и передаёт её +транспорту. Кодировщик не обращается к источникам. + +При блокировке IRQ callbacks читают только быструю RAM: без запросов +CAN/Modbus, ожидания периферии и выделения памяти. Удалённые источники +обновляют кэш заранее. Общая блокировка согласует чтение кэша, но не +синхронизирует физические измерения нескольких устройств и не определяет +свежесть удалённых данных. + +Отказ отдельного источника даёт `valid = 0, value = 0` и не отменяет выборку. +Корректное нулевое значение имеет `valid = 1`. Повреждённая карта целиком +или остановленная подписка возвращают `false` без изменения состояния и выхода. + +Первый номер выборки нового поколения — 0; далее он увеличивается по +модулю `2^32`. Каждый захват учитывается, даже если транспорт затем его +потерял. Повторная отправка готовой выборки сохраняет тот же номер. +Время передаётся портом **в миллисекундах устройства**, без подмены часами GUI. +Потребитель разворачивает переполнение времени в длинную ось своего сеанса. + +Первый захват разрешён сразу; следующий срок — `now_ms + period_ms`. +После опоздания нет пачки догоняющих выборок. Приложение проверяет таймер +чаще одного раза за `2^31` мс для корректного модульного сравнения u32. + +Изменение GAS и конфигурации не меняет готовую выборку. Приложение хранит +её до окончания чтения всеми потребителями, используя очередь или двойной +буфер при необходимости. Входные/выходные структуры и массивы API не +должны перекрываться в памяти. + +## Wire payload версии 2 + +Числа little-endian, размеры ниже в байтах. Выравнивание C-структур +в обмене не используется. Для GUI protocol v1 добавлены отдельные типы: + +| Тип GUI v1 | Назначение | +|---|---| +| `0x14 GAS_WATCH2_SET` | Настройка и полное эхо принятой конфигурации | +| `0x15 GAS_WATCH2_DATA` | Выборка; внешний sequence равен 0 | + +Внешняя версия остаётся GUI v1. Старые типы `0x12/0x13` не меняются. +Неподдерживаемая команда завершается явным отказом, автоматического fallback нет. +`0x0014 UNSUBSCRIBE` SETProtocol v2 относится к другому кадрированию +и сохраняет смысл. Обёртка нового GAS_WATCH2 для SETProtocol v2 согласуется +отдельно с его существующей типизированной телеметрией. + +Конфигурация и ACK: `12 + 2N` байт, максимум 140. + +| Смещение | Тип | Значение | +|---:|---|---| +| 0 | u16 | версия payload: 2 | +| 2 | u16 | период, мс | +| 4 | u32 | config_id, не ноль | +| 8 | u16 | N, число адресов: 0..64 | +| 10 | u16 | резерв, строго 0 | +| 12 | N × u16 | уникальные GAS-адреса в порядке значений | + +Выборка: `16 + ceil(N/8) + 2N` байт, максимум 152. + +| Смещение | Тип | Значение | +|---:|---|---| +| 0 | u16 | версия payload: 2 | +| 2 | u16 | N, число значений: 1..64 | +| 4 | u32 | config_id | +| 8 | u32 | sequence захвата | +| 12 | u32 | timestamp_ms устройства | +| 16 | ceil(N/8) байт | битовая маска достоверности | +| 16 + ceil(N/8) | N × u16 | сырые значения в порядке списка | + +Канал i соответствует биту `i % 8` байта `i / 8`, младший бит первым. +Неиспользуемые старшие биты последнего байта нулевые. Недостоверные слова +обязательно нулевые: кодировщик нормализует их, декодировщик отвергает +неканонический вход. Ошибки версии, точной длины, id, ожидаемого количества +или вместимости выхода возвращают `-1` без изменения выходных аргументов. +Успешный результат — число слов, включая отмеченные недостоверными. + +Classic CAN требует сегментации логического пакета портом: восемь байт +данных кадра не вмещают всю выборку. Окно Modbus для снимка подключается +отдельным проектным адаптером. + +## Клиенты и проверки + +`python/protocan/gas_watch.py` предоставляет `GasWatchConfig`, +`GasWatchSample`, `NativeGasWatch`; Android-порт — `GuiGasWatch2.kt` и JNI. +Оба используют C request/ack/decode; недостоверный канал представлен +Python `None` / Kotlin `null`. Старый DLL сообщает о необходимости +пересборки нового режима вместо второго кодека на языке GUI. + +Стабильные ABI-символы `set_gas_watch_request`, `set_gas_watch_ack`, +`set_gas_watch_decode` добавлены без изменения версии и прежних символов. +Сборки CMake, прямой host builder и Android NDK включают новый исходник. +Общий эталон — `tests/fixtures/gas-watch-v2.json`. +C-тест `gas_watch_v2` проверяет wire, транзакционность, поколения, +ошибки источников, независимость выборки, bitmap и переполнения. +Python/JVM используют те же байты через настоящие DLL/JNI. + +Это изменение общего ядра и адаптеров в `templates`. Переключение внешних +SETGUI/Android на новую ревизию сабмодуля, объединение подписок вкладок +и подключение к диспетчеру конкретной платы выполняются в этих проектах. +Архивный `c/gas-logger` сохраняет собственный формат истории; его +динамическая перенастройка здесь не включается. diff --git a/c/set-protocol/docs/GUI_TRENDS.md b/c/set-protocol/docs/GUI_TRENDS.md index 2898b89..cf21839 100644 --- a/c/set-protocol/docs/GUI_TRENDS.md +++ b/c/set-protocol/docs/GUI_TRENDS.md @@ -1,5 +1,9 @@ # Общие тренды для Android GUI и SETGUI +Расширенная подписка с подтверждением полного списка, поколением конфигурации +и признаками достоверности: [GAS_WATCH2](GAS_WATCH2.md). Она включается отдельно; +описанный ниже прежний GAS_WATCH и формат настроек сохраняют совместимость. + Модуль задаёт совместимые настройки и числовые источники графиков. Он не рисует экран, не открывает файлы или порты и не управляет прошивкой устройства. diff --git a/c/set-protocol/docs/STM_INVERTOR_GAS.md b/c/set-protocol/docs/STM_INVERTOR_GAS.md new file mode 100644 index 0000000..d0a34d6 --- /dev/null +++ b/c/set-protocol/docs/STM_INVERTOR_GAS.md @@ -0,0 +1,38 @@ +# STM Invertor: GAS 0x03 и GAS SLOT 0x04 + +Узел: DeviceType `0x7`, DeviceID `0xE`. Обработчик `set_invertor_gas_handle()` выбирает формат только по MsgType и использует существующие кодеки `pcan_gas` и `pcan_gas_slot`. + +| Доступ | Адреса | Содержимое | +| --- | --- | --- | +| GAS `0x03` | Регистры `0x0000…0x02ED` / 0…749 | По 1…4 последовательных 16-битных значения; DLC 2/4/6/8 | +| GAS SLOT `0x04` | Слоты `0x0000…0x00F9` / 0…249 | Word0 — маска; Word1…Word3 — три значения; DLC 8 | + +Это две проекции **одних 750 значений**. Отдельного массива слотов нет. Для слота `s` и полезного слова `w=1…3`: `Register=3*s+w-1`. Обратное отображение: `Slot=Register/3`, `Word=1+Register%3`. Word0 не является регистром. + +Начальные адреса относятся к узлу 7/E и не перенумеровывают PERIPH. Наличие 750 адресов не требует выделения 1500 байт сплошной RAM: provider обслуживает только существующие данные и явно отклоняет неподключённые значения. + +## Примеры + +Запись регистра 1 значением `0x1234`: ID `0x17E30001`, DLC 2, Data `34 12`. + +Запись того же значения через слот 0 / Word2: ID `0x17E40000`, DLC 8, Data `04 00 00 00 34 12 00 00`. Word1 и Word3 сохраняются. + +Чтение любого представления использует DLC=0, Route=0. Ответ имеет Route=1. Первый регистровый ответ использует ID `0x1FE30000`, слотный — `0x1FE40000`. Прикладного ACK записи нет; при необходимости результат применения проверяется чтением статуса устройства. + +## Прикладной порт + +`read(context, address, value)` возвращает ноль для достоверного значения. Ошибка не подменяется успешным нулём. Регистровое чтение останавливается на первом недоступном адресе; слотный ответ отмечает маской каждую доступную позицию. Полностью недоступный слот не возвращает пустую успешную маску. + +`write(context, addresses, values, count)` получает выбранные адреса единым набором. Provider сначала проверяет все права, диапазоны, состояния и значения, затем применяет набор под общей блокировкой. Неотмеченные позиции слота ему не передаются. Масочная запись не делает скрытого чтения и не требует перезаписывать readonly-соседей. + +Регистровый адаптер сначала собирает все слова через существующий кодек 0x03. Он не вызывает write-provider при частичном выходе за 750 регистров. Усиленная проверка относится к этому адаптеру изделия и не меняет общий контракт блочной записи `pcan_gas` для остальных устройств. + +Вызовы обработки одного экземпляра сериализуются приложением. Снимок чтения и применение записи защищает приложение; библиотека не включает прерывания, аппаратные разрешения или HAL. Наличие запроса на запись не подтверждает физическое выполнение команды силовой частью. + +## Клиентские привязки + +`set_invertor_gas_build()` возвращает готовые CAN ID и октеты; `set_invertor_gas_decode()` — проверенные тип, адрес и wire-слова ответа. Python/JNI не повторяют endian, маски идентификатора или формулу адресации. Размеры карт получают через `set_invertor_gas_limit()`. + +`set_invertor_gas_register()` и `set_invertor_gas_coordinate()` возвращают проверенные координаты, не меняя выходы при отказе. Диспетчер не переводит повреждённый 0x04 в 0x03 и не принимает запросы соседнего узла либо эхо ответа как запись. + +Тест `test_invertor_gas.c` проверяет оба wire-вектора, общий источник данных, маски, сохранение соседей, readonly, единственное применение набора, границы 249/749, ошибочные длины, флаги и адреса, а также клиентский ABI. diff --git a/c/set-protocol/docs/legacy/GAS.md b/c/set-protocol/docs/legacy/GAS.md index 51207fc..ceed7be 100644 --- a/c/set-protocol/docs/legacy/GAS.md +++ b/c/set-protocol/docs/legacy/GAS.md @@ -1,5 +1,7 @@ # Общее адресное пространство (GAS) +> GAS `0x3` использует адреса отдельных 16-битных регистров. GAS SLOT `0x4` — отдельный сервис с маской в Word0 и тремя значениями Word1…Word3. Спецификация: `doc/setcan/protocan/OAP.md`; адреса этого документа остаются регистровыми. + Плоское пространство 16-битных регистров с адресом `0x0000..0xFFFF`. Пространство собирается из **регионов**; регионы не перекрываются и хранятся отсортированными по адресу, поиск — двоичный. diff --git a/c/set-protocol/docs/legacy/OAP.md b/c/set-protocol/docs/legacy/OAP.md index b33a350..34ce935 100644 --- a/c/set-protocol/docs/legacy/OAP.md +++ b/c/set-protocol/docs/legacy/OAP.md @@ -1,14 +1,16 @@ # Общее адресное пространство +> GAS `0x3` использует адреса отдельных 16-битных регистров. GAS SLOT `0x4` — отдельный сервис с маской в Word0 и тремя значениями Word1…Word3. Спецификация: `doc/setcan/protocan/OAP.md`; адреса этого документа остаются регистровыми. + Статус: **Stable, данные ведутся в XLSX** Порядок значений: **16-битные регистры, little-endian в CAN payload** Редактируемый источник реестра: -[`Протокол CAN и ОАП.xlsx`](../../Протокол%20CAN%20и%20ОАП.xlsx). +[`Протокол CAN и ОАП.xlsx`](../../../../doc/setcan/Протокол%20CAN%20и%20ОАП.xlsx). Просматриваемая большая таблица находится в -[`Протокол CAN и ОАП.html`](../../Протокол%20CAN%20и%20ОАП.html) и -[`Протокол CAN и ОАП.md`](../../Протокол%20CAN%20и%20ОАП.md). +[`Протокол CAN и ОАП.html`](../../../../doc/setcan/Протокол%20CAN%20и%20ОАП.html) и +[`Протокол CAN и ОАП.md`](../../../../doc/setcan/Протокол%20CAN%20и%20ОАП.md). ## Назначение diff --git a/c/set-protocol/docs/legacy/PROTOCOL.md b/c/set-protocol/docs/legacy/PROTOCOL.md index 5f76f3c..4c044d2 100644 --- a/c/set-protocol/docs/legacy/PROTOCOL.md +++ b/c/set-protocol/docs/legacy/PROTOCOL.md @@ -1,7 +1,9 @@ # ProtoCAN — базовый протокол +> GAS `0x3` использует адреса отдельных 16-битных регистров. GAS SLOT `0x4` — отдельный сервис с маской в Word0 и тремя значениями Word1…Word3. Полный контракт: [ОАП](../../../../doc/setcan/protocan/OAP.md). Существующие регистровые сервисы сохраняют свои адреса. + Статус: **Stable с зарезервированным загрузочным расширением** -Версия: **1.0** +Версия: **2.2: единый Modbus 0x5, функции и количество 1…4**
Порядок байтов payload: **little-endian**, если явно не указано иное ## Назначение @@ -59,11 +61,10 @@ can_id = | `0x0` | `BROADCAST` | ПМ → все | зависит от команды | stable | | `0x1` | `DISCRETE` | оба | 0…8 | stable | | `0x2` | `ANALOG` | оба | 0…8 | stable | -| `0x3` | `GAS` | оба | 0/2/4/6/8 | stable | -| `0x4` | `MODBUS_COIL` | оба | 0…8 | stable | -| `0x5` | `MODBUS_DISCRETE` | оба | 0…8 | stable | -| `0x6` | `MODBUS_HOLDING` | оба | 0…8 | stable | -| `0x7` | `MODBUS_INPUT` | оба | 0…8 | stable | +| `0x3` | `GAS` | оба | 0/2/4/6/8 | регистры 0…65535 | +| `0x4` | `GAS_SLOT` | оба | 0/8 | Word0 — маска, Word1…Word3 — значения | +| `0x5` | `MODBUS` | оба | 0/1/2/4/6/8 | функции 1…4, количество 1…4 | +| `0x6…0x7` | резерв | — | — | свободны | | `0x8` | `ERROR` | прибор → ПМ | 0 | stable | | `0x9` | `BOOT_CONTROL` | ПМ → прибор | 0/8 | draft | | `0xA` | `BOOT_DATA_A` | ПМ → прибор | 8 | draft | @@ -81,13 +82,43 @@ can_id = |---|---| | broadcast | команда `[15:4]`, параметр `[3:0]` | | discrete/analog | подтип `[15:12]`, значение/адрес `[11:0]` | -| Modbus | начальный адрес `[15:4]`, количество `[3:0]` | -| GAS | адрес первого 16-битного регистра `[15:0]` | +| Modbus 0x5 | адрес `[15:4]`, функция − 1 `[3:2]`, количество − 1 `[1:0]` | +| GAS 0x3 | адрес первого 16-битного регистра `[15:0]` | +| GAS SLOT 0x4 | адрес слота `[15:0]`; маска — в Word0 payload, значения — Word1…Word3 | | error | дополнительная информация `[15:8]`, код `[7:0]` | | settings | номер сборки `[15:8]`, позиция `[7:0]` | | boot control/status | `SessionID[15:8]`, команда `[7:0]` | | boot data | `BlockIndex[15:0]` | +## Единый Modbus `0x5` + +Все четыре банка используют один `MsgType=0x5`. Коды `0x6` и `0x7` свободны. +Начальный адрес занимает `[15:4]` и лежит в диапазоне `0x000…0xFFF`. +Биты `[3:2]` содержат `Function − 1`, биты `[1:0]` — `RegCount − 1`. +Физические значения функции и количества: **1…4**. Всё окно должно помещаться +в 4096 адресов: `StrAdr + RegCount ≤ 4096`. + +| Функция | Банк | Элемент | DLC данных | +|---:|---|---|---| +| 1 | Coil | дискретный выход | 1 байт для 1…4 битов | +| 2 | Discrete | дискретный вход | 1 байт для 1…4 битов | +| 3 | Holding | 16-битный регистр | `2 × RegCount`, 2/4/6/8 байт | +| 4 | Input | 16-битный регистр | `2 × RegCount`, 2/4/6/8 байт | + +Это селектор банка в ProtoCAN по нумерации функций Modbus, без RTU-заголовка +и CRC. Сохраняется правило ProtoCAN: `Route=0, DLC=0` читает окно; +непустой payload записывает Coil/Holding, Discrete/Input доступны только +для чтения. Ответ имеет `Route=1`, сохраняет `MsgBody` и содержит значения +либо эхо успешной записи. RTR запрещён. Биты упакованы начиная с младшего, +старшие неиспользуемые биты нулевые. Регистры передаются little-endian. + +Пример: адрес `0x123`, функция 3, четыре регистра дают +`MsgBody = (0x123 << 4) | ((3 − 1) << 2) | (4 − 1) = 0x123B`. + +Изменение wire-формата несовместимо с прежними отдельными типами +`0x5/0x6/0x7`: узлы и клиенты обновляются согласованно. Тип GAS SLOT `0x4` +сохраняет своё назначение. + ## Общие правила обмена - Многобайтовые значения в `DATA` передаются little-endian. diff --git a/c/set-protocol/include/deif_xdi.h b/c/set-protocol/include/deif_xdi.h new file mode 100644 index 0000000..7924820 --- /dev/null +++ b/c/set-protocol/include/deif_xdi.h @@ -0,0 +1,41 @@ +#ifndef SETP_DEIF_XDI_H /* Защита переносимого ABI от повторного включения. */ +#define SETP_DEIF_XDI_H /* Контракт DEIF одинаков для ctypes, JNI и прошивок. */ +#include "pcan_abi.h" /* Общий макрос экспорта и целочисленные типы стабильного ABI. */ +#ifdef __cplusplus /* C++-потребители должны видеть тот же немодифицированный ABI символов. */ +extern "C" { /* Реализация остаётся C99 для ctypes, JNI и MCU. */ +#endif /* Начало совместимого C ABI. */ +typedef struct { /* Готовый стандартный CAN-кадр; упаковка транспортного моста остаётся отдельным слоем. */ + uint32_t can_id; /* 11-битный COB-ID, вычисленный ядром. */ + uint32_t dlc; /* Число используемых байтов Classic CAN, от нуля до восьми. */ + uint8_t data[8]; /* Готовые wire-байты без преобразований в GUI. */ +} setp_deif_frame_t; /* Размер структуры фиксирован: 16 байт без указателей. */ +PCAN_ABI_API int setp_deif_version(void); /* Версия этого независимого расширения ABI. */ +PCAN_ABI_API size_t setp_deif_state_size(void); /* Размер состояния, память выделяет вызывающая сторона. */ +PCAN_ABI_API int setp_deif_catalog(unsigned field, int32_t *metadata); /* base, subindex, десятичное разрешение; поле 0…7. */ +PCAN_ABI_API int setp_deif_selector(unsigned field, unsigned node, unsigned instance, unsigned dam, uint8_t *out); /* Четырёхбайтный селектор без дублирования endian в портах. */ +PCAN_ABI_API int setp_deif_inspect(uint32_t id, const uint8_t *data, size_t size, unsigned flags, int32_t *out); /* Метаданные кадра и детерминированный код ошибки. */ +PCAN_ABI_API int setp_deif_make(unsigned field, unsigned node, unsigned instance, int32_t value, uint32_t id, unsigned dam, setp_deif_frame_t *out); /* Данные MASTER, яркость и палитра. */ +PCAN_ABI_API int setp_deif_master(unsigned node, const int32_t *values, uint32_t id, unsigned dam, unsigned angle_subindex, setp_deif_frame_t *out); /* Порядок пяти объектов MASTER хранится только в C-каталоге. */ +PCAN_ABI_API int setp_deif_service(unsigned kind, unsigned node, unsigned value, setp_deif_frame_t *out); /* kind=0 строит heartbeat, kind=1 — локальную команду NMT. */ +PCAN_ABI_API int setp_deif_angle_command(const setp_deif_frame_t *actual, setp_deif_frame_t *out); /* Строит отдельное задание из фактического угла без изменения wire-байтов в UI. */ +PCAN_ABI_API int setp_deif_selector_info(const uint8_t *selector, int32_t *out); /* Node, index, subindex и DAM для редактора привязок. */ +PCAN_ABI_API int setp_deif_readdress(const uint8_t *selector, unsigned node, unsigned mode, uint8_t *out); /* Переносит только адрес; mode=2 сохраняет текущий SAM/DAM. */ +PCAN_ABI_API int setp_deif_route(unsigned node, unsigned dam, uint32_t previous, unsigned operation, uint32_t *out); /* COB-ID, Node и адрес; operation=0 согласовать, 1 сохранить, 2 извлечь Node. */ +PCAN_ABI_API int setp_deif_validate(uint32_t id, const uint8_t *data, size_t size, unsigned flags, unsigned slave); /* slave=0 проверяет MASTER, иначе серверные ответы своего узла. */ +PCAN_ABI_API int setp_deif_init(void *state, size_t size, unsigned node, unsigned source, unsigned xdi, unsigned self_start, unsigned pdo, unsigned group, unsigned services, uint32_t monitor_id); /* Инициализация профиля без системных часов и heap. */ +PCAN_ABI_API int setp_deif_bind(void *state, unsigned field, const uint8_t *selector, double scale); /* Привязка индикатора к явному объекту библиотеки. */ +PCAN_ABI_API int setp_deif_get_binding(void *state, unsigned field, uint8_t *selector, double *scale); /* Готовая привязка и масштаб текущего C-профиля. */ +PCAN_ABI_API int setp_deif_default_angle(void *state, uint8_t *selector, double *scale); /* Восстановление отсутствующей старой привязки с адресацией существующих полей. */ +PCAN_ABI_API int setp_deif_start(void *state, uint64_t now, unsigned reset_values); /* Время задаётся монотонными миллисекундами порта. */ +PCAN_ABI_API void setp_deif_stop(void *state); /* Выключенный узел прекращает все служебные события. */ +PCAN_ABI_API void setp_deif_reset_values(void *state); /* Сбрасывает только измерения и их временные отметки. */ +PCAN_ABI_API int setp_deif_accept(void *state, uint32_t id, const uint8_t *data, size_t size, unsigned flags, uint64_t now); /* Приём STD MPDO, NMT и expedited SDO. */ +PCAN_ABI_API size_t setp_deif_poll(void *state, uint64_t now, setp_deif_frame_t *out, size_t capacity); /* Таймеры и однократная выдача очереди Boot-up/HB/EMCY/SDO. */ +PCAN_ABI_API int setp_deif_read(void *state, unsigned field, uint64_t now, unsigned expiry_ms, double *value, int64_t *metadata); /* metadata: seen_ms, raw, статус, флаги seen/valid/stale. */ +PCAN_ABI_API unsigned setp_deif_lost(void *state, uint64_t now); /* Маска входов без обновлений 3000 мс. */ +PCAN_ABI_API int setp_deif_angle(void *state, uint64_t now, unsigned expiry_ms, double *value); /* 1 — фактический угол, 2 — явно помеченное задание, 0 — нет данных. */ +PCAN_ABI_API int setp_deif_meta(void *state, int64_t *out); /* active, NMT, start, lastHB, period, accepted, group, brightness, palette, error. */ +#ifdef __cplusplus /* Закрываем C ABI перед возвратом в C++-контекст клиента. */ +} /* extern C не влияет на чистый C99-компилятор. */ +#endif /* Совместимость с C++-портами. */ +#endif /* SETP_DEIF_XDI_H: все алгоритмы находятся в единственном C99-модуле. */ diff --git a/c/set-protocol/include/gui_frame.h b/c/set-protocol/include/gui_frame.h index 7b8a784..a0bcbd9 100644 --- a/c/set-protocol/include/gui_frame.h +++ b/c/set-protocol/include/gui_frame.h @@ -61,6 +61,8 @@ extern "C" { #define GUI_MSG_GAS_CATALOG 0x11U #define GUI_MSG_GAS_WATCH_SET 0x12U #define GUI_MSG_GAS_WATCH_DATA 0x13U +#define GUI_MSG_GAS_WATCH2_SET 0x14U /* Новый тип GUI v1 для версионированного полного списка GAS; payload описан в GAS_WATCH2.md. */ +#define GUI_MSG_GAS_WATCH2_DATA 0x15U /* Новый тип GUI v1 для самостоятельной выборки с поколением, временем и маской достоверности. */ #define GUI_MSG_NACK 0x80U #define GUI_MSG_ACK 0x81U #define GUI_MSG_ERROR 0x82U diff --git a/c/set-protocol/include/pcan_gas.h b/c/set-protocol/include/pcan_gas.h index 312e910..b101ba5 100644 --- a/c/set-protocol/include/pcan_gas.h +++ b/c/set-protocol/include/pcan_gas.h @@ -8,6 +8,7 @@ * @file pcan_gas.h * @brief Общее адресное пространство (General Address Space). * + * Тип 0x3 адресует отдельные регистры; независимый тип 0x4 описан в pcan_gas_slot.h. * Плоское пространство 16-битных регистров с адресом 0x0000..0xFFFF, * собранное из регионов. Регион либо ссылается на массив в памяти, * либо обслуживается колбэками - так в карту попадают и обычные @@ -120,7 +121,7 @@ void pcan_gas_regs_to_frame(pcan_frame_t *frame, uint32_t base_id, * * DLC = 0 - запрос на чтение: в rsp кладётся до 4 регистров с адреса * MsgBody, Route переключается на FROM_DEVICE. - * DLC > 0 - запись: регистры пишутся в карту, ответ не формируется. + * DLC = 2/4/6/8 - запись одного/двух/трёх/четырёх регистров; остальные слова не меняются. * * @param[out] rsp кадр ответа; заполняется, только если функция вернула true. * @return true, если ответ нужно передать. diff --git a/c/set-protocol/include/pcan_gas_slot.h b/c/set-protocol/include/pcan_gas_slot.h new file mode 100644 index 0000000..12ce89e --- /dev/null +++ b/c/set-protocol/include/pcan_gas_slot.h @@ -0,0 +1,48 @@ +#ifndef PCAN_GAS_SLOT_H /* Отдельный интерфейс исключает смешение нового номера слота со старым адресом регистра. */ +#define PCAN_GAS_SLOT_H /* Защита допускает включение из общего заголовка и непосредственно из порта MCU. */ +#include /* Фиксированные слова и uint_least8_t доступны также на C28x без восьмибитного char. */ +#include /* NULL используется без зависимости от ОС и динамической памяти. */ +#include /* CHAR_BIT выбирает экспорт host ABI отдельно от 16-битного C28x. */ +#if CHAR_BIT == 8 /* Host/ARM используют существующий экспорт DLL/SO. */ +#include "pcan_abi.h" /* Переиспользуем публичный экспорт единого host-кодека. */ +#elif !defined(PCAN_ABI_API) /* Встроенный C28x статически собирает функции без Windows-атрибутов. */ +#define PCAN_ABI_API /* Не требуем отсутствующий на C28x uint8_t из host ABI. */ +#endif /* Все последующие объявления одинаковы по смыслу на ARM, host и C28x. */ +#ifdef __cplusplus /* C++ и JNI связываются с C99-ядром через стандартные C-имена. */ +extern "C" { /* Начинаем область совместимого C ABI. */ +#endif /* Дальнейшие объявления пригодны также для чистого C. */ +#define PCAN_GAS_SLOT_WORDS 4U /* Восемь октетов кадра содержат четыре wire-слова: маску Word0 и три значения Word1…Word3. */ +#define PCAN_GAS_SLOT_DATA_WORDS 3U /* Два октета маски оставляют шесть октетов для трёх независимых 16-битных значений. */ +#define PCAN_GAS_SLOT_MASK 0x000EU /* Биты 1…3 выбирают одноимённые значения; бит 0 и биты 4…15 зарезервированы. */ +#define PCAN_GAS_SLOT_MODE_COUNT 32U /* Два типа PERIPH по шестнадцать DeviceID дают mode 0…31. */ +#define PCAN_GAS_SLOT_MODE_SLOTS 67U /* Округление 200/3 вверх сохраняет все регистры PERIPH; в последнем слоте действуют два значения. */ +#define PCAN_GAS_SLOT_MODE_WORDS 200U /* Значение измеряется в 16-битных словах, не в байтах MCU. */ +#define PCAN_GAS_SLOT_FLAG_IDE 1U /* Флаг Extended ID совпадает с транспортом pcan_frame; отдельно объявлен для C28x-порта. */ +#define PCAN_GAS_SLOT_FLAG_RTR 2U /* RTR запрещён слотным профилем; запрос чтения использует data frame с DLC=0. */ +#define PCAN_GAS_SLOT_FLAG_ERR 8U /* Ошибочный кадр моста не должен читаться как запрос к данным. */ +typedef int (*pcan_gas_slot_read_fn)(void *, uint16_t, uint16_t[4]); /* Provider возвращает маску достоверных значений в Word0 и три значения; ноль означает успех. */ +typedef int (*pcan_gas_slot_write_fn)(void *, uint16_t, const uint16_t[4]); /* Provider сначала проверяет все выбранные слова, затем меняет только биты 1…3 маски Word0 под общей блокировкой. */ +typedef struct { /* Независимый MCU-кадр не меняет legacy ABI и не требует uint8_t на C28x. */ + uint32_t id; /* Расширенный CAN ID содержит адрес узла и 16-битный номер слота. */ + unsigned flags; /* IDE/RTR/ERR используют документированные значения транспортных флагов. */ + unsigned dlc; /* Длина измеряется в октетах линии, а не в sizeof элементов C28x. */ + uint_least8_t data[8]; /* На C28x октет хранится в 16-битной ячейке; значения строго 0…255. */ +} pcan_gas_slot_frame_t; /* Порт переводит структуру в регистры CAN, не копируя wire-структуру через ABI. */ +typedef struct { /* Один порт соединяет общий обработчик с данными конкретного узла без глобальной памяти. */ + void *context; /* Контекст принадлежит проекту и должен жить дольше обработчика. */ + pcan_gas_slot_read_fn read; /* NULL запрещает чтение; callback получает полный 16-битный адрес слота. */ + pcan_gas_slot_write_fn write; /* NULL запрещает запись; callback не должен менять соседние слоты. */ +} pcan_gas_slot_port_t; /* Размер существующих структур pcan_gas не изменяется. */ +PCAN_ABI_API int32_t pcan_gas_slot_address(unsigned mode, unsigned local); /* Возвращает (mode<<8)|local либо -1 для mode>31 или local>66. */ +PCAN_ABI_API uint32_t pcan_gas_slot_id(unsigned device_type, unsigned device_id, unsigned address, unsigned route); /* Формирует MsgType=0x4 для любого узла и адреса 0…65535 без сужения неверных входов. */ +PCAN_ABI_API uint32_t pcan_gas_slot_request_id(unsigned mode, unsigned local, unsigned route); /* Формирует Extended ID PERIPH с Priority=1 и MsgType=0x4; ноль означает ошибку. */ +PCAN_ABI_API int pcan_gas_slot_encode(const uint16_t *words, unsigned count, uint_least8_t *data); /* Допускает count=0 либо четыре wire-слова с непустой маской в Word0; длина измеряется октетами. */ +PCAN_ABI_API int pcan_gas_slot_decode_words(uint32_t id, unsigned flags, const uint_least8_t *data, unsigned dlc, uint16_t *words); /* Проверяет общий слотный кадр любого узла; возвращает 0/4 либо -1 без изменения выхода при отказе. */ +PCAN_ABI_API int pcan_gas_slot_decode(uint32_t id, unsigned flags, const uint_least8_t *data, unsigned dlc, unsigned *mode, unsigned *local, uint16_t *words); /* Проверяет узел, слот и октеты; возвращает 0/4 либо -1 без изменения выходов. */ +PCAN_ABI_API int pcan_gas_slot_native(unsigned local, unsigned word, unsigned write, uint16_t *address); /* Переводит Word1…Word3 в родной адрес PERIPH; Word0 является маской и не адресует регистр. */ +PCAN_ABI_API int pcan_gas_slot_handle_address(unsigned device_type, unsigned device_id, const pcan_gas_slot_port_t *port, const pcan_gas_slot_frame_t *request, pcan_gas_slot_frame_t *response); /* Обслуживает масочную запись и чтение 0x4 для любого узла; не вызывает Modbus или GAS 0x3. */ +PCAN_ABI_API int pcan_gas_slot_handle(unsigned mode, const pcan_gas_slot_port_t *port, const pcan_gas_slot_frame_t *request, pcan_gas_slot_frame_t *response); /* Возвращает 1 для ответа, 0 после записи, -1 при отказе; не вызывает legacy fallback. */ +#ifdef __cplusplus /* Закрываем C ABI только при включении из C++. */ +} /* Конец объявлений с C-соглашением о связывании. */ +#endif /* Общие защитные символы не зависят от языка порта. */ +#endif /* Завершаем защиту единственного интерфейса слотного профиля GAS. */ diff --git a/c/set-protocol/include/pcan_id.h b/c/set-protocol/include/pcan_id.h index dd88b9e..753639f 100644 --- a/c/set-protocol/include/pcan_id.h +++ b/c/set-protocol/include/pcan_id.h @@ -46,10 +46,8 @@ typedef enum { PCAN_MSG_DISCRETE = 0x1U, PCAN_MSG_ANALOG = 0x2U, PCAN_MSG_GAS = 0x3U, /**< общее адресное пространство */ - PCAN_MSG_MODBUS_COIL = 0x4U, - PCAN_MSG_MODBUS_DISCR = 0x5U, - PCAN_MSG_MODBUS_HOLDING = 0x6U, - PCAN_MSG_MODBUS_INPUT = 0x7U, + PCAN_MSG_GAS_SLOT = 0x4U, /**< Слотный GAS с маской слов; код 0x4 освобождён от Modbus Coil. */ + PCAN_MSG_MODBUS = 0x5U, /**< Единый Modbus; банк выбирается функцией 1…4 в MsgBody, коды 0x6/0x7 свободны. */ PCAN_MSG_ERROR = 0x8U, PCAN_MSG_PULSE = 0xFU } pcan_msgtype_t; @@ -57,11 +55,11 @@ typedef enum { /** Разобранный идентификатор. */ typedef struct { uint16_t msg_body; - uint8_t msg_type; /**< pcan_msgtype_t */ - uint8_t device_id; /**< 0..15 */ - uint8_t device_type; /**< 0..7 */ - uint8_t route; - uint8_t priority; + uint_least8_t msg_type; /**< pcan_msgtype_t */ /* На C28x хранит октет в доступном 16-битном типе; допустимые значения поля и host ABI остаются прежними. */ + uint_least8_t device_id; /**< 0..15 */ /* На C28x хранит октет в доступном 16-битном типе; допустимые значения поля и host ABI остаются прежними. */ + uint_least8_t device_type; /**< 0..7 */ /* На C28x хранит октет в доступном 16-битном типе; допустимые значения поля и host ABI остаются прежними. */ + uint_least8_t route; /* На C28x хранит октет в доступном 16-битном типе; допустимые значения поля и host ABI остаются прежними. */ + uint_least8_t priority; /* На C28x хранит октет в доступном 16-битном типе; допустимые значения поля и host ABI остаются прежними. */ } pcan_id_t; uint32_t pcan_id_pack(const pcan_id_t *id); @@ -70,25 +68,35 @@ void pcan_id_unpack(uint32_t raw, pcan_id_t *id); /* --- Раскладки MsgBody ----------------------------------------------------- */ /** BROADCAST: Type[15:4], Body[3:0]. */ -static inline uint16_t pcan_body_broadcast(uint16_t type, uint8_t body) +static inline uint16_t pcan_body_broadcast(uint16_t type, uint_least8_t body) /* На C28x хранит октет в доступном 16-битном типе; допустимые значения поля и host ABI остаются прежними. */ { return (uint16_t)(((type & 0x0FFFU) << 4) | (body & 0x0FU)); } /** DISCRETE / ANALOG: Type[15:12], Body[11:0]. */ -static inline uint16_t pcan_body_typed(uint8_t type, uint16_t body) +static inline uint16_t pcan_body_typed(uint_least8_t type, uint16_t body) /* На C28x хранит октет в доступном 16-битном типе; допустимые значения поля и host ABI остаются прежними. */ { return (uint16_t)(((uint16_t)(type & 0x0FU) << 12) | (body & 0x0FFFU)); } -/** MODBUS: StrAdr[15:4], RegCount[3:0]. */ -static inline uint16_t pcan_body_modbus(uint16_t addr, uint8_t count) -{ - return (uint16_t)(((addr & 0x0FFFU) << 4) | (count & 0x0FU)); -} +/** MODBUS: StrAdr[15:4], Function-1[3:2], RegCount-1[1:0]; вызывающий проверяет адрес 0…4095 и значения 1…4. */ +static inline uint16_t pcan_body_modbus(uint16_t addr, uint_least8_t count, uint_least8_t function) /* Два двухбитных поля кодируют четыре функции и четыре количества без потери 12-битного адреса. */ +{ /* Упаковка применяется после проверки диапазонов параметров на стороне клиента. */ + return (uint16_t)(((addr & 0x0FFFU) << 4) | (((function - 1U) & 3U) << 2) | ((count - 1U) & 3U)); /* 0xFFF ограничивает адрес 12 битами; смещение на единицу переводит значения 1…4 в wire-коды 0…3. */ +} /* Конец упаковки единого Modbus типа 0x5. */ + +static inline uint_least8_t pcan_modbus_count(uint16_t body) /* Возвращает физическое количество регистров или битов из двух младших битов Body. */ +{ /* Каждый двухбитный wire-код имеет допустимое значение. */ + return (uint_least8_t)((body & 3U) + 1U); /* Маска 3 выделяет биты 1:0; прибавление единицы восстанавливает диапазон 1…4. */ +} /* Конец извлечения количества. */ + +static inline uint_least8_t pcan_modbus_function(uint16_t body) /* Возвращает номер функции: Coil=1, Discrete=2, Holding=3, Input=4. */ +{ /* Функция занимает два бита между адресом и количеством. */ + return (uint_least8_t)(((body >> 2) & 3U) + 1U); /* Сдвиг выделяет биты 3:2; wire-коды 0…3 соответствуют функциям 1…4. */ +} /* Конец извлечения функции. */ /** ERROR: Info[15:8], Code[7:0]. */ -static inline uint16_t pcan_body_error(uint8_t info, uint8_t code) +static inline uint16_t pcan_body_error(uint_least8_t info, uint_least8_t code) /* На C28x хранит октет в доступном 16-битном типе; допустимые значения поля и host ABI остаются прежними. */ { return (uint16_t)(((uint16_t)info << 8) | code); } diff --git a/c/set-protocol/include/pcan_modbus_server.h b/c/set-protocol/include/pcan_modbus_server.h index 0552d22..088e43d 100644 --- a/c/set-protocol/include/pcan_modbus_server.h +++ b/c/set-protocol/include/pcan_modbus_server.h @@ -21,10 +21,10 @@ extern "C" { #endif typedef enum { - PCAN_MODBUS_COIL = 0x4U, - PCAN_MODBUS_DISCRETE = 0x5U, - PCAN_MODBUS_HOLDING = 0x6U, - PCAN_MODBUS_INPUT = 0x7U + PCAN_MODBUS_COIL = 1U, /* Функция 1 выбирает банк дискретных выходов. */ + PCAN_MODBUS_DISCRETE = 2U, /* Функция 2 выбирает банк дискретных входов. */ + PCAN_MODBUS_HOLDING = 3U, /* Функция 3 выбирает банк изменяемых 16-битных регистров. */ + PCAN_MODBUS_INPUT = 4U /* Функция 4 выбирает банк входных 16-битных регистров. */ } pcan_modbus_bank_t; typedef bool (*pcan_modbus_read_fn)(void *user, pcan_modbus_bank_t bank, @@ -54,7 +54,7 @@ bool pcan_modbus_server_init(pcan_modbus_server_t *server, pcan_modbus_read_fn read, pcan_modbus_write_fn write, void *user); -/** Zero DLC reads; data writes COIL/HOLDING. Register words are little-endian. */ +/** MsgType=0x5, функция/количество 1…4: DLC=0 читает банк; данные записывают COIL/HOLDING по правилам ProtoCAN. */ pcan_modbus_result_t pcan_modbus_server_handle(pcan_modbus_server_t *server, const pcan_frame_t *request, pcan_frame_t *response); diff --git a/c/set-protocol/include/protocan_transport.h b/c/set-protocol/include/protocan_transport.h index 34084ae..c07a0ec 100644 --- a/c/set-protocol/include/protocan_transport.h +++ b/c/set-protocol/include/protocan_transport.h @@ -27,6 +27,7 @@ #include "pcan_crc.h" #include "pcan_frame.h" #include "pcan_gas.h" +#include "pcan_gas_slot.h" /* Слотный тип 0x4 имеет маску Word0 и собственный обработчик, регистровый GAS 0x3 сохраняет отдельные адреса слов. */ #include "pcan_id.h" #include "pcan_link.h" #include "pcan_modbus_server.h" diff --git a/c/set-protocol/include/set_gas_watch.h b/c/set-protocol/include/set_gas_watch.h new file mode 100644 index 0000000..ccef471 --- /dev/null +++ b/c/set-protocol/include/set_gas_watch.h @@ -0,0 +1,65 @@ +/* GAS_WATCH2: проверяемый список GAS-слов и независимые от транспорта выборки; формат описан в docs/GAS_WATCH2.md. */ +#ifndef SET_GAS_WATCH_H /* Исключает повторные объявления при подключении ядра несколькими компонентами прошивки. */ +#define SET_GAS_WATCH_H /* Отмечает загрузку публичного контракта расширенной подписки. */ +#include /* Даёт булевы результаты операций без платформенной зависимости. */ +#include "pcan_abi.h" /* Предоставляет фиксированные типы, size_t и экспорт стабильных функций для ctypes/JNI. */ +#include "pcan_gas.h" /* Предоставляет карту 16-битных GAS-регистров и проверяемые операции чтения. */ +#ifdef __cplusplus /* Открывает C ABI для проектов, компилирующих публичный заголовок как C++. */ +extern "C" { /* Запрещает изменение имён экспортируемых функций компилятором C++. */ +#endif /* Завершает условие входа в совместимую с C область объявлений. */ + +#define SET_GAS_WATCH_VERSION 2U /* Версия payload; отличается от версии внешнего кадрирования GUI. */ +#define SET_GAS_WATCH_MAX 64U /* Максимум 16-битных слов в одном списке; многословный параметр занимает несколько позиций. */ +#define SET_GAS_WATCH_CONFIG_HEADER 12U /* Байты version:u16, period:u16, config_id:u32, count:u16, reserved:u16. */ +#define SET_GAS_WATCH_SAMPLE_HEADER 16U /* Байты version:u16, count:u16, config_id:u32, sequence:u32, timestamp_ms:u32. */ +#define SET_GAS_WATCH_CONFIG_MAX (SET_GAS_WATCH_CONFIG_HEADER + 2U * SET_GAS_WATCH_MAX) /* 140 байт с адресами 64 слов. */ +#define SET_GAS_WATCH_SAMPLE_MAX (SET_GAS_WATCH_SAMPLE_HEADER + 8U + 2U * SET_GAS_WATCH_MAX) /* 152 байта: заголовок, 64 бита достоверности и значения. */ + +typedef enum { /* Разделяет неверный payload, ошибки карты и конфликт поколений без строк или исключений. */ + SET_GAS_WATCH_OK = 0, /* Весь список применён либо подтверждён точный повтор действующей конфигурации. */ + SET_GAS_WATCH_INVALID = 1, /* Нарушены версия, длина, указатели, период, уникальность адресов или структура карты. */ + SET_GAS_WATCH_NO_REG = 2, /* Хотя бы один адрес отсутствует в корректной карте; действующий список сохранён. */ + SET_GAS_WATCH_ACCESS = 3, /* Хотя бы один регистр запрещён для чтения либо не имеет источника чтения. */ + SET_GAS_WATCH_CONFLICT = 4 /* Идентификатор устарел либо повторно использован с другим содержимым. */ +} set_gas_watch_result_t; /* Завершает публичный набор детерминированных результатов настройки. */ + +typedef struct { /* Состояние одного прибора и одного управляющего клиента; память принадлежит приложению. */ + uint32_t config_id; /* Ненулевое поколение; новые поколения сравниваются по модульной разности меньше 2^31. */ + uint32_t sequence; /* Номер следующей выборки; первая имеет номер 0, переполнение происходит по модулю 2^32. */ + uint32_t next_ms; /* Срок следующего захвата в миллисекундах локального 32-битного счётчика устройства. */ + uint16_t period_ms; /* Период захвата в миллисекундах; ноль вместе с пустым списком останавливает поток. */ + uint16_t count; /* Число выбранных 16-битных GAS-слов, от 0 до SET_GAS_WATCH_MAX. */ + uint16_t address[SET_GAS_WATCH_MAX]; /* Упорядоченные уникальные GAS-индексы, а не указатели на память MCU. */ + uint8_t scheduled; /* Ноль разрешает первую выборку сразу, единица включает проверку next_ms с переполнением. */ +} set_gas_watch_t; /* Внутренняя структура прошивки не передаётся через wire или языковую границу. */ + +typedef struct { /* Самодостаточная копия одного захвата, пригодная для графика, архива и повторной передачи. */ + uint32_t config_id; /* Связывает позиции значений с подтверждённым списком адресов. */ + uint32_t sequence; /* Номер захвата, позволяющий обнаружить потерю пакета при занятой линии. */ + uint32_t timestamp_ms; /* Время захвата на устройстве; задержка USB/UART не меняет эту метку. */ + uint16_t count; /* Число значений и признаков достоверности в используемой части массивов. */ + uint16_t values[SET_GAS_WATCH_MAX]; /* Сырые слова; при ошибке соответствующего источника сохраняется ноль. */ + uint8_t valid[SET_GAS_WATCH_MAX]; /* Единица означает успешное чтение слова, ноль отличает ошибку от реального нулевого значения. */ +} set_gas_watch_sample_t; /* Приложение хранит выборку до завершения её использования всеми потребителями. */ + +/* Все обращения к состоянию и захвату RAM приложение сериализует своим lock/IRQ-портом; ядро не управляет прерываниями. */ +void set_gas_watch_init(set_gas_watch_t *watch); /* Обнуляет состояние до первой команды; NULL допустим как пустая операция. */ +/* Проверяет весь payload и карту без вызовов источников; ошибка оставляет состояние неизменным. Повтор id+содержимое идемпотентен. */ +int set_gas_watch_apply(set_gas_watch_t *watch, const pcan_gas_map_t *map, const uint8_t *payload, size_t size); /* Пустой stop не требует карты. */ +size_t set_gas_watch_encode_ack(const set_gas_watch_t *watch, uint8_t *out, size_t capacity); /* Возвращает полное эхо применённой конфигурации или 0. */ +bool set_gas_watch_due(const set_gas_watch_t *watch, uint32_t now_ms); /* Проверяет срок с переполнением; период проверок должен быть меньше 2^31 мс. */ +/* Захватывает RAM по явному вызову, без проверки due; источники обязаны быть быстрыми и не выполнять I/O или ожидания. */ +bool set_gas_watch_capture(set_gas_watch_t *watch, const pcan_gas_map_t *map, uint32_t now_ms, set_gas_watch_sample_t *sample); /* Отказ источника отражается valid=0. */ +/* Кодирует только готовую выборку, без обращений к карте и без блокировки источников; приложение вызывает после снятия lock. */ +size_t set_gas_watch_encode_sample(const set_gas_watch_sample_t *sample, uint8_t *out, size_t capacity); /* Неверный аргумент не меняет выходной буфер. */ + +/* Экспортируемый ABI использует скаляры и буферы: ни один клиент не повторяет кодек payload на своём языке. */ +PCAN_ABI_API size_t set_gas_watch_request(uint32_t config_id, uint16_t period_ms, const uint16_t *addresses, size_t count, uint8_t *out, size_t capacity); /* 0 означает отказ без записи. */ +PCAN_ABI_API int set_gas_watch_ack(const uint8_t *payload, size_t size, uint32_t config_id, uint16_t period_ms, const uint16_t *addresses, size_t count); /* 1 подтверждает точное эхо всех адресов. */ +/* Возвращает число слов или -1; до полной проверки payload и ожидаемого поколения не меняет ни один выходной аргумент. */ +PCAN_ABI_API int set_gas_watch_decode(const uint8_t *payload, size_t size, uint32_t expected_config_id, size_t expected_count, uint32_t *sequence, uint32_t *timestamp_ms, uint16_t *values, uint8_t *valid, size_t capacity); /* Метаданные sequence/time могут быть NULL. */ + +#ifdef __cplusplus /* Закрывает только ту область linkage, которую открывали для C++ потребителя. */ +} /* Завершает объявления с C-именами функций. */ +#endif /* Завершает условное закрытие C++ linkage. */ +#endif /* SET_GAS_WATCH_H: завершает защиту публичного заголовка. */ diff --git a/c/set-protocol/include/set_igbt_realtime.h b/c/set-protocol/include/set_igbt_realtime.h new file mode 100644 index 0000000..6984c1d --- /dev/null +++ b/c/set-protocol/include/set_igbt_realtime.h @@ -0,0 +1,44 @@ +#ifndef SET_IGBT_REALTIME_H /* Исключает повторное объявление интерфейса аппаратного IGBT версии 4. */ +#define SET_IGBT_REALTIME_H /* Отделяет наносекундный протокол от прежней миллисекундной модели версии 3. */ +#include "set_regmap.h" /* Использует общие коды ошибок и ABI библиотеки регистров. */ +#ifdef __cplusplus /* Сохраняет совместимость общего C-интерфейса с потребителями C++. */ +extern "C" { /* Запрещает изменение имён экспортируемых функций компилятором C++. */ +#endif /* Завершает условное начало C ABI. */ +#define SET_IGBT_RT_CHANNELS 8u /* Число независимых входных и выходных трактов стенда. */ +#define SET_IGBT_RT_WORDS 112u /* Сохраняет размер окна: заголовок 16 слов и восемь каналов по 12 слов. */ +#define SET_IGBT_RT_MIN_NS 50u /* Минимальный программируемый интервал 50 нс оставляет запас относительно трёх тактов HRTIM при 160 МГц. */ +#define SET_IGBT_RT_MAX_NS 60000u /* Максимальные 60000 нс помещаются в 16-битный регистр протокола. */ +typedef struct { /* Задания одного канала; времена всегда выражены целыми наносекундами. */ + uint16_t flags, mode, on_delay, on_width, off_delay, off_width; /* Биты TX/RX/инверсии, режим ответа и времена начала/ширины ACK для двух фронтов. */ + uint16_t tx_width, edges, fault_width, compensation; /* Длительность физического TX, маска ON/OFF, длительность FAULT и измеренная компенсация входного тракта, нс. */ +} set_igbt_rt_channel; /* Независимый аппаратный канал не содержит миллисекундных счётчиков. */ +typedef struct { /* Полное задание применяется одной завершающей командой после записи полей. */ + uint16_t enabled, source, tx, fault; /* Разрешение выходов, 0=внешний Vin/ACK, 1=физический генератор TX, маски удержания TX и неисправностей. */ + set_igbt_rt_channel channel[SET_IGBT_RT_CHANNELS]; /* Восемь одинаковых настроек хранятся отдельно от работающего оборудования. */ +} set_igbt_rt_config; /* Подготовленные настройки не меняют уже работающие таймеры до применения. */ +typedef struct { /* Снимок получает фактические уровни и диагностические счётчики аппаратного порта. */ + uint8_t tx, rx, busy; /* Вход Vin/выход TX, выход ACK/вход Vstat и маска выполняемых одиночных импульсов. */ + uint16_t count[SET_IGBT_RT_CHANNELS], overrun[SET_IGBT_RT_CHANNELS]; /* Счётчики принятых фронтов и потерь захвата по каждому каналу, по модулю 65536. */ +} set_igbt_rt_snapshot; /* Чтение снимка не запускает импульсы и не сбрасывает накопленные события. */ +typedef struct { /* Аппаратный порт выполняет фронты таймерами; общий модуль только проверяет и маршрутизирует команды. */ + unsigned (*selected)(void *); /* Возвращает ненулевое значение только для подтверждённого режима IGBT платы. */ + unsigned (*apply)(void *, const set_igbt_rt_config *); /* Настраивает весь проверенный профиль; ошибка должна оставлять прежнее оборудование без изменения. */ + unsigned (*pulse)(void *, uint8_t); /* Одновременно проверяет и запускает выбранные биты физического TX; длительность отмеряет оборудование. */ + void (*levels)(void *, uint8_t); /* Выставляет постоянные уровни TX только после проверки отсутствия выполняемых импульсов. */ + void (*stop)(void *); /* Немедленно отключает аппаратные триггеры и переводит все восемь выходов в ноль. */ + void (*sample)(void *, set_igbt_rt_snapshot *); /* Снимает уровни, занятость и счётчики без формирования фронтов программными задержками. */ + void (*clear)(void *); /* Сбрасывает только счётчики диагностики, сохраняя настройки и работу таймеров. */ +} set_igbt_rt_port; /* Переносимый слой не зависит от HAL, ОС или частоты опроса GUI. */ +typedef struct { /* Единственный экземпляр сервиса принадлежит вызывающему аппаратному проекту. */ + set_igbt_rt_config staged, active; /* Подготовленный и реально применённый профили предотвращают изменение времён посреди записи регистров. */ + set_igbt_rt_port port; /* Копия таблицы callbacks живёт столько же, сколько сам сервис. */ + void *context; /* Непрозрачное состояние аппаратного порта передаётся каждому callback без владения памятью. */ +} set_igbt_rt; /* Сервис не выделяет динамическую память и не обслуживает наносекундные сроки из основного цикла. */ +PCAN_ABI_API void set_igbt_rt_init(set_igbt_rt *, const set_igbt_rt_port *, void *); /* Создаёт выключенный профиль 1SP: задержка 250 нс, ACK 700 нс, TX 10000 нс. */ +PCAN_ABI_API unsigned set_igbt_rt_validate(const set_igbt_rt_config *); /* Проверяет все восемь каналов до изменения оборудования. */ +PCAN_ABI_API unsigned set_igbt_rt_read(void *, uint16_t, uint16_t, uint16_t *); /* Читает окно версии 4; смещения и число слов заданы в 16-битных регистрах. */ +PCAN_ABI_API unsigned set_igbt_rt_write(void *, uint16_t, uint16_t); /* Записывает задание либо выполняет явную команду пуска, останова или сброса счётчиков. */ +#ifdef __cplusplus /* Закрывает C ABI только при компиляции заголовка как C++. */ +} /* Завершает блок внешних C-объявлений. */ +#endif /* Завершает условную поддержку C++. */ +#endif /* Завершает защиту заголовка аппаратного IGBT. */ diff --git a/c/set-protocol/include/set_invertor_gas.h b/c/set-protocol/include/set_invertor_gas.h new file mode 100644 index 0000000..d23a038 --- /dev/null +++ b/c/set-protocol/include/set_invertor_gas.h @@ -0,0 +1,32 @@ +#ifndef SET_INVERTOR_GAS_H /* Общий C-контракт связывает два вида GAS с одним источником значений инвертора. */ +#define SET_INVERTOR_GAS_H /* Защищаем объявления от повторного подключения прошивкой и host-клиентом. */ +#include "set_invertor_profile.h" /* Число слотов и пара DeviceType/DeviceID определены единственным профилем Templates. */ +#include "pcan_gas.h" /* Тип 0x3 использует существующую карту регистров и общий разбор Classic CAN. */ +#include "pcan_gas_slot.h" /* Тип 0x4 сохраняет маску Word0 и три выбранных значения. */ +#ifdef __cplusplus /* Клиенты C++ должны обращаться к обычным C-символам общей библиотеки. */ +extern "C" { /* Открываем совместимую область связывания без изменения wire-формата. */ +#endif /* Последующие объявления также доступны компилятору C99. */ +#define SET_INVERTOR_GAS_REGISTER_FIRST 0U /* В отдельном узле 7/E регистровая карта начинается с нуля независимо от PERIPH. */ +#define SET_INVERTOR_GAS_SLOT_FIRST 0U /* Выделенные 250 слотов отдельного инвертора имеют адреса 0x0000…0x00F9. */ +#define SET_INVERTOR_GAS_REGISTER_COUNT SET_INVERTOR_GAS_WORD_COUNT /* 750 регистров 0x0000…0x02ED хранят те же значения, что слоты типа 0x4. */ +#if SET_INVERTOR_GAS_WORDS_PER_SLOT != PCAN_GAS_SLOT_DATA_WORDS /* Геометрия профиля обязана совпадать с актуальным масочным кодеком Templates. */ +#error "Invertor GAS profile and slot codec disagree" /* При несовместимом изменении профиля прекращаем сборку вместо тихого смещения регистров. */ +#endif /* Проверка действует одинаково для host и STM32. */ +typedef int (*set_invertor_gas_read_fn)(void *context, uint16_t address, uint16_t *value); /* Ноль подтверждает одно достоверное значение; ошибка не подменяется успешным нулём. */ +typedef int (*set_invertor_gas_write_fn)(void *context, const uint16_t *addresses, const uint16_t *values, unsigned count); /* Provider проверяет все 1…4 адреса, права и значения до единственного согласованного применения. */ +typedef struct { /* Приложение владеет данными и отвечает за блокировку общего снимка на время одного вызова обработчика. */ + void *context; /* Контекст связывает регистровый и слотный доступ с одним состоянием изделия. */ + set_invertor_gas_read_fn read; /* NULL отключает чтение, сохраняя возможность явно разрешённой записи. */ + set_invertor_gas_write_fn write; /* NULL полностью запрещает запись, в том числе команды через регистры. */ +} set_invertor_gas_port_t; /* Структура не требует выделения массива из всех 750 слов или аппаратных заголовков. */ +PCAN_ABI_API int32_t set_invertor_gas_register(unsigned slot, unsigned word); /* Возвращает регистр для Word1…Word3 либо -1 для маски и координат за пределами 250 слотов. */ +PCAN_ABI_API int set_invertor_gas_coordinate(unsigned address, uint16_t *slot, uint16_t *word); /* Обратное отображение не изменяет выходы при ошибке; Word0 никогда не является значением. */ +PCAN_ABI_API uint32_t set_invertor_gas_request_id(unsigned message_type, unsigned address, unsigned route); /* Общий кодек строит только MsgType 0x3/0x4 узла 7/E с адресами внутри соответствующей карты. */ +PCAN_ABI_API int set_invertor_gas_handle(const set_invertor_gas_port_t *port, const pcan_frame_t *request, pcan_frame_t *response); /* Возвращает 1 для готового ответа, 0 для применённой записи, -1 при отказе; автоматического fallback нет. */ +PCAN_ABI_API unsigned set_invertor_gas_limit(unsigned message_type); /* Возвращает 750 регистров для 0x3, 250 слотов для 0x4 либо ноль для неизвестного типа. */ +PCAN_ABI_API int set_invertor_gas_build(unsigned message_type, unsigned address, const uint16_t *words, unsigned count, uint32_t *identifier, uint8_t data[8]); /* Тонкие языковые порты получают готовые ID и октеты: count=0 означает чтение, результат — DLC либо -1. */ +PCAN_ABI_API int set_invertor_gas_decode(uint32_t identifier, unsigned flags, const uint8_t *data, unsigned length, unsigned metadata[2], uint16_t words[4]); /* Проверяет ответ 7/E; metadata содержит тип и адрес, результат — число 16-битных wire-слов либо -1. */ +#ifdef __cplusplus /* Закрываем область C ABI только при использовании C++-компилятора. */ +} /* Завершаем публичные объявления общей библиотеки. */ +#endif /* Условие не меняет смысл C99-интерфейса. */ +#endif /* Конец контракта двух представлений одних данных инвертора. */ diff --git a/c/set-protocol/include/set_invertor_profile.h b/c/set-protocol/include/set_invertor_profile.h new file mode 100644 index 0000000..f95fb31 --- /dev/null +++ b/c/set-protocol/include/set_invertor_profile.h @@ -0,0 +1,8 @@ +#ifndef SET_INVERTOR_PROFILE_H /* Общий профиль адресации используется прошивкой и клиентами единственного C-ядра Templates. */ +#define SET_INVERTOR_PROFILE_H /* Предотвращаем повторное определение параметров нового устройства. */ +#define SET_INVERTOR_DEVICE_TYPE 7U /* DeviceType 0x7 выбран пользователем; поле ProtoCAN имеет ширину три бита. */ +#define SET_INVERTOR_DEVICE_ID 14U /* DeviceID 0xE свободен по аудиту 23.10.2026; G474 CANdle использует 0xF, F103 KONOR использует 0xD. */ +#define SET_INVERTOR_GAS_SLOT_COUNT 250U /* Пользователь выделил 250 слотов отдельному инвертору, сохранив существующую адресацию PERIPH. */ +#define SET_INVERTOR_GAS_WORDS_PER_SLOT 3U /* Тип 0x4 выделяет Word0 под маску и передаёт три независимых значения Word1…Word3. */ +#define SET_INVERTOR_GAS_WORD_COUNT (SET_INVERTOR_GAS_SLOT_COUNT * SET_INVERTOR_GAS_WORDS_PER_SLOT) /* Выделенные 250 слотов содержат 750 значений; служебная маска не является регистром. */ +#endif /* Этот заголовок задаёт назначение узла без нового кодека или изменения старых CAN ID. */ diff --git a/c/set-protocol/include/setprotocol.h b/c/set-protocol/include/setprotocol.h index 6cf501f..1e32880 100644 --- a/c/set-protocol/include/setprotocol.h +++ b/c/set-protocol/include/setprotocol.h @@ -11,6 +11,7 @@ #ifndef SETPROTOCOL_H #define SETPROTOCOL_H #include "set_regmap.h" +#include "set_invertor_gas.h" /* Предоставляет обе карты одного инвертора через единую точку подключения общей библиотеки. */ #include "set_emu_server.h" #include "balsam_can.h" @@ -31,5 +32,6 @@ #include "protocan_transport.h" #include "gui_frame.h" #include "gui_catalog.h" +#include "set_gas_watch.h" /* Предоставляет новую подписку и независимый захват GAS-слов через общую точку подключения ядра. */ #endif /* SETPROTOCOL_H */ diff --git a/c/set-protocol/include/setprotocol_abi.h b/c/set-protocol/include/setprotocol_abi.h index abb2bc1..c0ae0e2 100644 --- a/c/set-protocol/include/setprotocol_abi.h +++ b/c/set-protocol/include/setprotocol_abi.h @@ -15,6 +15,7 @@ #define SETPROTOCOL_ABI_H #include "pcan_abi.h" +#include "set_gas_watch.h" /* Подключает добавочные стабильные request/ack/decode символы без изменения существующего ABI v1. */ #define SETPROTOCOL_ABI_VERSION PCAN_ABI_VERSION diff --git a/c/set-protocol/ports/android/Android.mk b/c/set-protocol/ports/android/Android.mk index de1ba13..c221a7a 100644 --- a/c/set-protocol/ports/android/Android.mk +++ b/c/set-protocol/ports/android/Android.mk @@ -29,6 +29,10 @@ LOCAL_SRC_FILES := \ ../../src/pcan_ring.c \ ../../src/pcan_gas.c \ setprotocol_jni.c +LOCAL_SRC_FILES += ../../src/set_gas_watch.c # Включает общий GAS_WATCH2 в NDK-библиотеку для новых тонких JNI-вызовов. +LOCAL_SRC_FILES += ../../src/pcan_gas_slot.c gas_slots_jni.c # Android собирает общий слотный кодек и тонкую JNI-границу без второго алгоритма. +LOCAL_SRC_FILES += ../../src/set_invertor_gas.c # Android получает ту же C-реализацию нового профиля без копирования алгоритмов. LOCAL_CFLAGS := -std=c99 -Wall -Wextra -Wpedantic -fvisibility=hidden LOCAL_LDLIBS := -llog -lm +LOCAL_SRC_FILES += ../../src/deif_xdi.c set_deif_jni.c # Общий DEIF и тонкий JNI без второй реализации. include $(BUILD_SHARED_LIBRARY) diff --git a/c/set-protocol/ports/android/gas_slots_jni.c b/c/set-protocol/ports/android/gas_slots_jni.c new file mode 100644 index 0000000..fde83cd --- /dev/null +++ b/c/set-protocol/ports/android/gas_slots_jni.c @@ -0,0 +1,42 @@ +#include /* Единственная ответственность JNI — преобразование массивов и скалярных типов JVM. */ +#include "pcan_gas_slot.h" /* Формат ID, слотов и payload реализуется общим C-ядром. */ +JNIEXPORT jlong JNICALL Java_ru_setcorp_setprotocol_GasSlots_nativeRequestId(JNIEnv *env,jobject self,jint mode,jint local,jint route) /* Kotlin и host JVM вызывают одинаковый native-метод. */ +{ /* Начинаем преобразование адресных координат. */ + (void)env;(void)self;if(mode<0 || local<0 || route<0)return 0; /* Не сужаем отрицательные Java-числа в адреса устройств. */ + return (jlong)pcan_gas_slot_request_id((unsigned)mode,(unsigned)local,(unsigned)route); /* Все формулы и пределы проверяются C. */ +} /* Конец построения Extended ID. */ +JNIEXPORT jbyteArray JNICALL Java_ru_setcorp_setprotocol_GasSlots_nativeEncode(JNIEnv *env,jobject self,jintArray input) /* Кодируем Word0-маску и три значения без второго endian-алгоритма на JVM. */ +{ /* NULL означает payload запроса чтения, массив — значения слота. */ + jint source[4];uint16_t words[4];uint_least8_t bytes[8];int i,n; jbyteArray out;(void)self; /* Все буферы имеют фиксированную вместимость одного кадра. */ + if(input==NULL)return (*env)->NewByteArray(env,0); /* Для запроса чтения payload пуст и не требует фиктивных регистров. */ + if((*env)->GetArrayLength(env,input)!=4)return NULL; /* Фиксированные позиции маски и трёх значений требуют четырёх wire-слов даже при частичной записи. */ + (*env)->GetIntArrayRegion(env,input,0,4,source);if((*env)->ExceptionCheck(env))return NULL; /* Не продолжаем JNI-вызовы после ошибки копирования массива. */ + for(i=0;i<4;i++){if(source[i]<0 || source[i]>65535)return NULL;words[i]=(uint16_t)source[i];} /* Сохраняем границы беззнакового 16-битного регистра. */ + n=pcan_gas_slot_encode(words,4U,bytes);if(n<0)return NULL; /* Общий кодек проверяет маску Word0 и формирует восемь wire-октетов. */ + out=(*env)->NewByteArray(env,n);if(out!=NULL)(*env)->SetByteArrayRegion(env,out,0,n,(const jbyte *)bytes);return out; /* Возвращаем готовый payload транспорта JVM/Android. */ +} /* Конец тонкого адаптера записи. */ +JNIEXPORT jintArray JNICALL Java_ru_setcorp_setprotocol_GasSlots_nativeDecode(JNIEnv *env,jobject self,jlong id,jint flags,jbyteArray input) /* Декодирование возвращает mode, локальный слот и четыре слова. */ +{ /* Заголовок и содержимое проверяются до создания модели JVM. */ + uint_least8_t bytes[8];uint16_t words[4];unsigned mode,slot;int n,i;jsize length;jint values[6];jintArray out;(void)self; /* Ограниченные массивы не требуют heap внутри ядра. */ + if(id<0 || id>0xFFFFFFFFLL || flags<0 || input==NULL)return NULL; /* Не допускаем сужения 64-битного Long до другого действующего ID. */ + length=(*env)->GetArrayLength(env,input);if(length>8)return NULL; /* Extended Classic CAN не принимает payload CAN FD. */ + if(length>0)(*env)->GetByteArrayRegion(env,input,0,length,(jbyte *)bytes);if((*env)->ExceptionCheck(env))return NULL; /* Передаём исходные октеты C без ручной интерпретации. */ + n=pcan_gas_slot_decode((uint32_t)id,(unsigned)flags,bytes,(unsigned)length,&mode,&slot,words);if(n<0)return NULL; /* Проверяем адрес узла, страницу слота, DLC и направление общей реализацией. */ + values[0]=(jint)mode;values[1]=(jint)slot;for(i=0;iNewIntArray(env,n+2);if(out!=NULL)(*env)->SetIntArrayRegion(env,out,0,n+2,values);return out; /* JVM получает только проверенные скалярные значения. */ +} /* Конец JNI-декодирования без резервной реализации протокола. */ +JNIEXPORT jlong JNICALL Java_ru_setcorp_setprotocol_GasSlots_nativeAddressId(JNIEnv *env, jobject self, jint device_type, jint device_id, jint address, jint route) /* Создаём слотный ID любого узла, не только PERIPH. */ +{ /* JNI проверяет представимость, а ширину полей и номер типа проверяет C. */ + (void)env; (void)self; if (device_type < 0 || device_id < 0 || address < 0 || route < 0) return 0; /* Отрицательные Java Int не превращаются в действительные unsigned-адреса. */ + return (jlong)pcan_gas_slot_id((unsigned)device_type, (unsigned)device_id, (unsigned)address, (unsigned)route); /* Один общий построитель формирует MsgType=0x4 и полный адрес 0…65535. */ +} /* Конец адресного адаптера. */ +JNIEXPORT jintArray JNICALL Java_ru_setcorp_setprotocol_GasSlots_nativeDecodeWords(JNIEnv *env, jobject self, jlong id, jint flags, jbyteArray input) /* Возвращаем проверенные wire-слова любого слотного узла. */ +{ /* В этой границе отсутствуют собственные правила маски или порядка октетов. */ + uint_least8_t bytes[8]; uint16_t words[4]; jint values[4]; jsize length; jintArray out; int count, i; (void)self; /* Все буферы ограничены одним classic CAN кадром. */ + if (id < 0 || id > 0xFFFFFFFFLL || flags < 0 || input == NULL) return NULL; /* Проверяем представимость Long и наличие входа до JNI-копирования. */ + length = (*env)->GetArrayLength(env, input); if (length > 8) return NULL; /* Не усекаем данные CAN FD до classic CAN. */ + if (length > 0) (*env)->GetByteArrayRegion(env, input, 0, length, (jbyte *)bytes); if ((*env)->ExceptionCheck(env)) return NULL; /* Сохраняем точные wire-октеты и прекращаем работу при исключении JVM. */ + count = pcan_gas_slot_decode_words((uint32_t)id, (unsigned)flags, bytes, (unsigned)length, words); if (count < 0) return NULL; /* Тип 0x4, маску, DLC и направление проверяет общее C-ядро. */ + for (i = 0; i < count; ++i) values[i] = (jint)words[i]; /* Расширяем проверенные u16 слова без изменения знака или смысла маски. */ + out = (*env)->NewIntArray(env, count); if (out != NULL) (*env)->SetIntArrayRegion(env, out, 0, count, values); return out; /* Публикуем готовый результат, пустой только для корректного запроса чтения. */ +} /* Конец общего JNI-декодера. */ diff --git a/c/set-protocol/ports/android/kotlin/ru/setcorp/setflash/core/ProtoCanCatalog.kt b/c/set-protocol/ports/android/kotlin/ru/setcorp/setflash/core/ProtoCanCatalog.kt index 00dc1ab..74fb702 100644 --- a/c/set-protocol/ports/android/kotlin/ru/setcorp/setflash/core/ProtoCanCatalog.kt +++ b/c/set-protocol/ports/android/kotlin/ru/setcorp/setflash/core/ProtoCanCatalog.kt @@ -11,10 +11,8 @@ enum class ProtoCanMessageType(val code: Int, val title: String) { DISCRETE(0x1, "Discrete"), ANALOG(0x2, "Analog"), GENERAL_ADDRESS_SPACE(0x3, "General Address Space"), - MODBUS_COIL(0x4, "Modbus Coil"), - MODBUS_DISCRETE(0x5, "Modbus Discrete"), - MODBUS_HOLDING(0x6, "Modbus Holding"), - MODBUS_INPUT(0x7, "Modbus Input"), + GAS_SLOT(0x4, "GAS Slot"), // Код 0x4 выбирает слотный GAS с маской, регистровый GAS сохраняет собственный код 0x3. + MODBUS(0x5, "Modbus"), // Функции 1…4 в Body выбирают банк; номера типов 0x6 и 0x7 освобождены. ERROR(0x8, "Error"), BOOT_CONTROL(0x9, "Boot Control"), BOOT_DATA_A(0xA, "Boot Data A"), @@ -63,8 +61,10 @@ object ProtoCanBody { fun typed(type: Int, body: Int): Int = ((type and 0xF) shl 12) or (body and 0xFFF) - fun modbus(address: Int, registerCount: Int): Int = - ((address and 0xFFF) shl 4) or (registerCount and 0xF) + fun modbus(address: Int, registerCount: Int, function: Int): Int { // Явная функция 1…4 выбирает Coil, Discrete, Holding или Input. + require(address in 0..0xFFF && registerCount in 1..4 && function in 1..4 && address + registerCount <= 0x1000) // Проверяем 12-битное окно и два поля без молчаливого усечения. + return (address shl 4) or ((function - 1) shl 2) or (registerCount - 1) // Биты 3:2 содержат функцию минус один, биты 1:0 — количество минус один. + } // Конец упаковки единого Modbus типа 0x5. fun error(info: Int, code: Int): Int = ((info and 0xFF) shl 8) or (code and 0xFF) diff --git a/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/GasSlots.kt b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/GasSlots.kt new file mode 100644 index 0000000..c3167b5 --- /dev/null +++ b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/GasSlots.kt @@ -0,0 +1,10 @@ +package ru.setcorp.setprotocol // Размещаем слотный профиль рядом с существующим native-ядром приложения. + +object GasSlots { // Объект не вычисляет адреса и endian самостоятельно, сохраняя единый C-контракт. + init { System.loadLibrary("setprotocol") } // Отсутствие нового ядра проявляется явной ошибкой загрузки. + external fun nativeRequestId(mode: Int, localSlot: Int, route: Int): Long // Ноль означает неверные координаты; допустимый ID формирует C. + external fun nativeEncode(words: IntArray?): ByteArray? // Word0 — непустая маска битов 1…3, Word1…Word3 — значения; null запрашивает чтение. + external fun nativeDecode(canId: Long, flags: Int, payload: ByteArray): IntArray? // Результат PERIPH: mode, слот, маска и три значения; null означает отказ. + external fun nativeAddressId(deviceType: Int, deviceId: Int, address: Int, route: Int): Long // Общий C-построитель поддерживает любой узел и все адреса слота 0…65535. + external fun nativeDecodeWords(canId: Long, flags: Int, payload: ByteArray): IntArray? // Общий C-декодер возвращает маску и три значения любого узла либо пустой массив запроса. +} // Завершаем тонкую привязку без Kotlin-копии wire-протокола. diff --git a/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/NativeSetProtocol.kt b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/NativeSetProtocol.kt index cab62ec..9e050d9 100644 --- a/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/NativeSetProtocol.kt +++ b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/NativeSetProtocol.kt @@ -33,6 +33,9 @@ object NativeSetProtocol { external fun nativeTrendWatchValues(input: ByteArray): IntArray? /** {unsigned timestampMs, word0, ...}. */ external fun nativeTrendWatchDecode(input: ByteArray): LongArray? + external fun nativeGasWatchRequest(configId: Long, period: Int, addresses: IntArray): ByteArray? // Передаёт идентификатор конфигурации u32, период в миллисекундах и адреса u16 общему C-кодеку GAS_WATCH2. + external fun nativeGasWatchAck(input: ByteArray, configId: Long, period: Int, addresses: IntArray): Boolean // Проверяет C-кодеком полное эхо конфигурации, включая порядок всех адресов, до переключения активной подписки. + external fun nativeGasWatchDecode(input: ByteArray, configId: Long, count: Int): LongArray? // Возвращает проверенные C-кодеком sequence и время как положительные u32 в Long, затем слова либо −1 для невалидных каналов. external fun nativePackId( priority: Int, route: Int, diff --git a/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/deif/DeifWorkspace.kt b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/deif/DeifWorkspace.kt new file mode 100644 index 0000000..d2833f7 --- /dev/null +++ b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/deif/DeifWorkspace.kt @@ -0,0 +1,134 @@ +package ru.setcorp.setprotocol.deif // Общий контроллер UI находится в templates и использует единственный C-кодек через JNI. +import java.io.StringReader // Текст пользовательского профиля читается без Android Context и доступа к файловой системе. +import java.io.StringWriter // Профиль возвращается вызывающему GUI для сохранения в его собственном хранилище. +import java.util.Properties // Стандартный формат JVM хранит настройки без дополнительной зависимости от JSON-библиотеки. +import kotlin.math.roundToInt // Округление относится к переводу жеста интерфейса в заданный пользователем масштаб управления. + +data class DeifBinding(val field: Int, val selector: String, val scale: Double) // Привязка содержит непрозрачный HEX-селектор и пользовательский множитель индикации. +data class DeifSelectorInfo(val node: Int, val index: Int, val subindex: Int, val dam: Boolean) // Метаданные текущего селектора получены из C и не раскрывают wire-разметку приложению. +data class DeifCommands(val power: Double = 0.0, val rpm: Double = 0.0, val angle: Double = 0.0) // POWER и RPM задаются процентом шкалы, угол — градусами. +data class DeifTraffic(val master: List = emptyList(), val slave: List = emptyList()) // Раздельные маршруты не позволяют командам MASTER выдать себя за ответы SLAVE. +data class DeifSettings( // Сохраняемые параметры независимы от временного запуска сервера и циклической передачи. + val node: Int = 13, val source: Int = 1, val xdi: Boolean = true, val automatic: Boolean = true, // Собственный адрес SLAVE и источник SAM имеют независимый смысл. + val pdo: Int = 2, val group: Int = 1, val monitorId: Long = 0, val bindings: List = emptyList(), // RPDO, группа экрана и ручные привязки передаются непосредственно C-профилю. + val masterNode: Int = 1, val masterId: Long = 0x201, val masterDam: Boolean = false, // Адресация MASTER не изменяется при выборе собственного узла SLAVE. + val periodMs: Int = 100, val heartbeat: Boolean = false, val heartbeatNode: Int = 1, // Период цикла в миллисекундах независим от штатного heartbeat каждые 500 мс. + val selected: List = List(5) { true }, // Порядок соответствует публичному ABI цикла MASTER: угол, RPM, RPM%, POWER и POWER%. + val powerFull: Double = 1000.0, val rpmFull: Double = 1000.0, val angleFactor: Double = 10.0, val powerPercentFactor: Double = 10.0, // Калибровки интерфейса: POWER RAW при 100%, rpm при 100%, RAW/градус и RAW/процент. + val powerUnit: String = "RAW", // Неподтверждённая физическая единица мощности не подменяется автоматически киловаттами. +) { // Конструктор данных не загружает JNI при запуске приложения с другим протоколом. + init { require(selected.size == 5) { "Профиль MASTER должен содержать пять флажков отправки" } } // Повреждённый текст настроек не должен приводить к выходу за границы списка в интерфейсе. + fun readdressed(previousNode: Int, previousSource: Int): DeifSettings { // Изменение адресов переносит только связанные с прежним узлом привязки, сохраняя независимые источники. + return copy(bindings = bindings.map { binding -> // Каждое поле сохраняет собственный индекс, подиндекс и физический масштаб. + val info = DeifXdi.selectorInfo(binding.selector) // Адрес и SAM/DAM сообщает общий C-декодер без масок и endian-копии в Kotlin. + val target = if (info?.dam == true && info.node == previousNode) node else if (info?.dam == false && info.node == previousSource) source else null // DAM следует физическому получателю, SAM — выбранному источнику рассылки. + if (target != null) binding.copy(selector = DeifXdi.readdress(binding.selector, target)) else binding // Независимые ручные источники и отключённые поля остаются прежними. + }) // Применение возвращает один полный профиль для последующей общей проверки. + } // Смена SAM-источника не должна оставлять стандартные поля подписанными на старый Node-ID. + fun model(services: Boolean = false): DeifXdi { // Оба GUI-режима получают профиль единственного переносимого автомата. + val result = DeifXdi(node, source, xdi, automatic, pdo, group, services, monitorId) // Все сетевые диапазоны и исходные привязки проверяет C-конструктор. + try { bindings.forEach { result.bind(it) } } catch (error: Exception) { result.close(); throw error } // Неверная ручная привязка не оставляет частично настроенный сервер. + return result // Владение контекстом и его закрытием получает контроллер сеанса. + } // Создание пассивного профиля ничего не отправляет в CAN. + fun validate() { // Перед применением проверяются и сетевой профиль, и настройки управления интерфейсом. + require(periodMs >= 0 && selected.size == 5 && group in 1..9) { "Проверьте период, группу экрана и выбор объектов DEIF" } // Размер списка закреплён публичным ABI MASTER, номер группы выбирается явно. + require(listOf(powerFull, rpmFull, angleFactor, powerPercentFactor).all { it.isFinite() && it > 0 }) { "Масштабы управления должны быть положительными числами" } // Нулевой либо бесконечный множитель не должен создавать недостоверные задания. + require(bindings.map { it.field }.distinct().size == bindings.size && bindings.all { it.field in 0..4 }) { "Привязки пяти показаний должны быть уникальными" } // Угол задания автоматически обслуживается C-привязкой фактического азимута. + model(true).close() // Самый строгий серверный профиль проверяет RPDO, протокол и оба адреса до изменения UI. + DeifXdi.master(masterNode, IntArray(5), masterId, masterDam) // Общий builder проверяет точный COB-ID и адресацию передатчика. + DeifXdi.service(false, heartbeatNode, 5) // Допустимость адреса heartbeat также проверяет существующий C-builder. + } // Ошибка оставляет прежний работающий профиль без изменений. + fun encode(): String { // Хранилище приложения получает только текст настроек без состояния работающих таймеров. + val p = Properties() // Стандартные ключи JVM сохраняют совместимость Android и host-тестов. + listOf("node" to node, "source" to source, "xdi" to xdi, "automatic" to automatic, "pdo" to pdo, "group" to group, "monitorId" to monitorId, "masterNode" to masterNode, "masterId" to masterId, "masterDam" to masterDam, "periodMs" to periodMs, "heartbeat" to heartbeat, "heartbeatNode" to heartbeatNode, "powerFull" to powerFull, "rpmFull" to rpmFull, "angleFactor" to angleFactor, "powerPercentFactor" to powerPercentFactor, "powerUnit" to powerUnit).forEach { (key, value) -> p.setProperty(key, value.toString()) } // Сохраняются только явные настройки, без флагов запуска SLAVE и MASTER. + p.setProperty("selected", selected.joinToString(",")) // Включение отдельных объектов восстанавливается независимо от значений заданий. + bindings.forEach { p.setProperty("binding.${it.field}", "${it.scale}|${it.selector}") } // HEX хранится непрозрачно, индекс и endian в Kotlin не вычисляются. + return StringWriter().also { p.store(it, "DEIF") }.toString() // Запись в SharedPreferences или файл остаётся задачей платформенного слоя. + } // Сериализация не вызывает CAN-транспорт или системные часы протокола. + companion object { // Загрузка профиля не требует Android API и не запускает нативный сервер. + fun decode(text: String): DeifSettings { // Старый либо отсутствующий профиль получает исходные значения DEIF. + val p = Properties().apply { load(StringReader(text)) } // Properties снимает только текстовое экранирование формата хранения. + fun value(key: String, default: Any) = p.getProperty(key, default.toString()) // Каждый новый параметр имеет явное совместимое исходное значение. + val defaults = DeifSettings() // Единый набор исходных параметров не дублируется в приложении Android. + return DeifSettings(node = value("node", defaults.node).toInt(), source = value("source", defaults.source).toInt(), xdi = value("xdi", true).toBooleanStrict(), automatic = value("automatic", true).toBooleanStrict(), // Адреса и профиль восстанавливаются без объявления узла на CAN-шине. + pdo = value("pdo", 2).toInt(), group = value("group", 1).toInt(), monitorId = value("monitorId", 0).toLong(), bindings = (0..4).mapNotNull { field -> p.getProperty("binding.$field")?.split('|', limit = 2)?.let { DeifBinding(field, it[1], it[0].toDouble()) } }, // Список ручных привязок сохраняет индивидуальные масштабы и отключённые поля. + masterNode = value("masterNode", 1).toInt(), masterId = value("masterId", defaults.masterId).toLong(), masterDam = value("masterDam", false).toBooleanStrict(), // Собственный MASTER остаётся независимым от адреса получателя SLAVE. + periodMs = value("periodMs", 100).toInt(), heartbeat = value("heartbeat", false).toBooleanStrict(), heartbeatNode = value("heartbeatNode", 1).toInt(), selected = value("selected", "true,true,true,true,true").split(',').map { it.toBooleanStrict() }, // Восстанавливаем выбор объектов без автоматического запуска циклической отправки. + powerFull = value("powerFull", 1000).toDouble(), rpmFull = value("rpmFull", 1000).toDouble(), angleFactor = value("angleFactor", 10).toDouble(), powerPercentFactor = value("powerPercentFactor", 10).toDouble(), powerUnit = value("powerUnit", "RAW")) // Калибровки и единицы относятся к интерфейсу конкретной библиотеки прибора. + } // Ошибку повреждённого текста вызывающий GUI показывает либо заменяет безопасными исходными настройками. + } // Конструктор не содержит скрытого алгоритмического fallback вместо C. +} // Один профиль используется локальным стендом, пассивным наблюдателем и физическим сервером. + +class DeifWorkspace(val settings: DeifSettings, val local: Boolean) : AutoCloseable { // Общий контроллер управляет маршрутом, а протокольный автомат остаётся в C. + private var model = settings.model() // Исходный пассивный наблюдатель не производит исходящих кадров. + private val values = IntArray(5) // Значения MASTER хранятся отдельно от принятых измерений модели SLAVE. + var slaveEnabled = false; private set // Запуск сервера всегда требует отдельного явного действия пользователя. + var masterRunning = false; private set // Открытие экрана и восстановление настроек не запускают передачу. + var sent = 0L; private set // Счётчик показывает число переданных маршруту кадров без обещания физической доставки. + var lastService: DeifFrame? = null; private set // Последний служебный кадр помогает диагностировать NMT, heartbeat и SDO. + var lastRpm: DeifFrame? = null; private set // Последний выбранный кадр RPM доступен диагностике без повторной распаковки в GUI. + var cycleGapMs: Long? = null; private set // Интервал между вызовами рабочего цикла измеряется в переданных порту монотонных миллисекундах. + var maxCycleGapMs = 0L; private set // Максимальный интервал выявляет паузы интерфейса, не подтверждая доставку CAN-кадра. + private var lastCycleAt: Long? = null // До первого цикла не показывается выдуманное измерение интервала отправки. + private var nextCycle = 0L; private var nextHeartbeat = 0L // Дедлайны порта используют переданные монотонные миллисекунды без чтения часов в библиотеке. + val commands: DeifCommands get() = DeifCommands(values[3] / settings.powerFull * 100, values[1] / 10.0 / settings.rpmFull * 100, values[0] / settings.angleFactor) // Жёлтые маркеры строятся из фактически ограниченных INT16 заданий. + fun setControl(key: String, value: Double) { // Жест меняет только черновик MASTER и никогда сам не выполняет отправку. + require(value.isFinite()) { "Задание DEIF должно быть конечным числом" } // Некорректная координата интерфейса не попадает в конструктор CAN-кадра. + fun raw(number: Double) = number.coerceIn(-32767.0, 32765.0).roundToInt() // Рабочий диапазон I16 исключает три служебных значения протокола при управлении мышью или касанием. + when (key) { // Ключи описывают визуальные элементы, а не индексы wire-объектов. + "angle" -> values[0] = raw(value * settings.angleFactor) // Градусы переводятся по пользовательской калибровке RAW на градус. + "power" -> { values[3] = raw(value / 100 * settings.powerFull); values[4] = raw(values[3] / settings.powerFull * 100 * settings.powerPercentFactor) } // Процент мощности согласуется с фактически ограниченным абсолютным заданием. + "rpm" -> { values[1] = raw(value / 100 * settings.rpmFull * 10); values[2] = raw(values[1] / 10.0 / settings.rpmFull * 1000) } // Обороты и их процент используют ту же визуальную калибровку, что Desktop. + else -> error("Неизвестный регулятор DEIF") // Ошибка UI не должна молча менять другую физическую величину. + } // Никакие байты CAN здесь не формируются. + } // Последующая разовая либо циклическая отправка использует единый набор значений. + fun startSlave(enabled: Boolean, now: Long) { // Локальный стенд и физический сервер различаются только маршрутом готовых кадров. + stopMaster() // Предыдущий MASTER не должен продолжить отправку после переключения роли. + model.close(); model = settings.model(enabled); slaveEnabled = enabled // Новый профиль не наследует старые измерения и незавершённые служебные события. + if (enabled) model.start(now) // Boot-up, self-start и NMT-состояние создаются C-ядром. + } // События выдаются через tick, а физическую отправку выполняет платформа. + fun startMaster(enabled: Boolean, now: Long) { // Таймер MASTER включается независимо от таймера служебного heartbeat SLAVE. + require(!enabled || !local || slaveEnabled) { "Для локального обмена сначала запустите симуляцию SLAVE" } // Отказ маршрута происходит до изменения флага запуска, а не на первом тике таймера. + require(!enabled || !slaveEnabled || local) { "В режиме CAN-SLAVE передаёт внешний MASTER" } // Физический сервер не конкурирует со встроенным передатчиком приложения. + masterRunning = enabled; nextCycle = now; nextHeartbeat = now; lastCycleAt = null; cycleGapMs = null; maxCycleGapMs = 0 // Новый сеанс начинает отсчёт периодов и статистики с явного запуска. + } // При periodMs=0 порт передаёт не более одного цикла за очередной вызов tick. + fun stopMaster() { masterRunning = false } // Остановка не изменяет принятые физические показания SLAVE. + private fun events(now: Long): List { // Доставка очереди C выполняется также при отсутствии новых входящих кадров. + val frames = model.poll(now); frames.lastOrNull()?.let { lastService = it } // Сохраняем последний готовый сервисный кадр без повторного разбора payload. + return if (local && slaveEnabled) emptyList() else frames // На локальном стенде Boot-up, SDO и heartbeat не выходят в физический адаптер. + } // Один poll извлекает каждый кадр из очереди только один раз. + private fun route(frames: List, now: Long): DeifTraffic { // Решение о локальном маршруте относится к порту, а не к wire-протоколу. + require(!local || slaveEnabled) { "Для локального обмена сначала запустите симуляцию SLAVE" } // Выбранный локальный режим никогда не перенаправляется в физический CAN при остановленном сервере. + sent += frames.size // Счётчик не является подтверждением приёма физическим прибором. + if (local && slaveEnabled) { frames.forEach { model.accept(it.canId, it.data, nowMs = now) }; events(now); return DeifTraffic() } // Внутренний стенд принимает точные C-байты без вызова транспорта. + return DeifTraffic(master = frames) // Внешний маршрут возвращает кадры вызывающему приложению с отдельной проверкой MASTER. + } // Черновик задания не подменяет физический RX-снимок. + fun cycle(now: Long): DeifTraffic { // Один цикл использует C-каталог пяти объектов и отдельного задания азимута. + require(!local || slaveEnabled) { "Для локального обмена сначала запустите симуляцию SLAVE" } // Прямой вызов разового цикла не обходит выбор автономного маршрута пользователя. + require(!slaveEnabled || local) { "В режиме CAN-SLAVE передаёт внешний MASTER" } // Прямой вызов кнопки также не обходит ограничения физического сервера. + val service = events(now) // Сначала учитываем self-start и доставляем ранее накопленные служебные ответы. + val built = DeifXdi.master(settings.masterNode, values, settings.masterId, settings.masterDam) // Проверенный C-builder формирует полный цикл до выбора отправляемых объектов. + cycleGapMs = lastCycleAt?.let { (now - it).coerceAtLeast(0) }; maxCycleGapMs = maxOf(maxCycleGapMs, cycleGapMs ?: 0); lastCycleAt = now // Отмечается интервал вызовов порта, а не сетевой ACK либо срок Data lost. + lastRpm = if (settings.selected[1]) built[1] else null // Семантическая позиция RPM закреплена публичным контрактом цикла MASTER, payload не разбирается. + val frames = built.filterIndexed { index, _ -> settings.selected[if (index < 5) index else 0] } // Отдельный set-point следует выбору общего объекта угла. + return route(frames, now).copy(slave = service) // Все выбранные кадры получают единый локальный либо физический маршрут. + } // Частично собранный цикл не возвращается при ошибке builder ядра. + fun tick(now: Long): DeifTraffic { // Android поставляет время, а сроки self-start и Data lost вычисляет C. + var traffic = DeifTraffic(slave = events(now)) // Служебный таймер обслуживается независимо от передачи MASTER. + if (masterRunning && now >= nextCycle) { val cycle = cycle(now); traffic = DeifTraffic(traffic.master + cycle.master, traffic.slave + cycle.slave); nextCycle = now + settings.periodMs.coerceAtLeast(1) } // Один вызов не создаёт пачку просроченных повторов после паузы GUI. + if (masterRunning && settings.heartbeat && now >= nextHeartbeat) { val heartbeat = route(listOf(DeifXdi.service(false, settings.heartbeatNode, 5)), now); traffic = DeifTraffic(traffic.master + heartbeat.master, traffic.slave + heartbeat.slave); nextHeartbeat = now + 500 } // Штатный Operational heartbeat MASTER имеет независимый период 500 миллисекунд. + return traffic // Порт физического транспорта получает только готовые кадры с сохранёнными ролями. + } // Все действия повторяемы при одних и тех же переданных монотонных часах. + fun accept(frame: DeifFrame, extended: Boolean, remote: Boolean, now: Long) { // Внешний RX не должен изменять внутренний локальный стенд. + if (!local || !slaveEnabled) model.accept(frame.canId, frame.data, extended, remote, now) // STD, RTR, адреса и известные объекты проверяет общий C-код. + } // TX-эхо и ошибки адаптера отфильтровывает платформенный слой. + fun nmt(command: Int, now: Long) { // Локальное управление NMT сохраняет то же ограничение, что Desktop. + require(local && slaveEnabled) { "NMT доступен только в локальной симуляции SLAVE" } // Команды управления сетью не отправляются физическому MASTER. + val frame = DeifXdi.service(true, settings.node, command); model.accept(frame.canId, frame.data, nowMs = now); events(now) // Адресный двухбайтный NMT строится и обрабатывается только C-ядром. + } // Выбор пункта меню сам по себе не вызывает этот метод. + fun display(palette: Boolean, value: Int, now: Long, group: Int = settings.group): DeifTraffic { // Подтверждение фиксирует группу отдельно от ещё не сохранённого черновика остальных настроек. + return route(listOf(DeifXdi.make(if (palette) 7 else 6, settings.masterNode, group, value, settings.masterId, settings.masterDam)), now) // Выбранная группа, U8 яркости и Day/Night/Dusk проверяются общим C-builder. + } // Команды яркости и палитры не включаются в циклическую отправку MASTER. + fun snapshot(now: Long): DeifSnapshot = model.snapshot(now) // Числа, статусы, угол и Data lost поступают из единственного C-автомата. + override fun close() { stopMaster(); model.close(); slaveEnabled = false } // Закрытие владельца прекращает и циклические команды, и служебную очередь SLAVE. +} // Контроллер не содержит Android, Compose, системных часов, USB и второго CAN-кодека. diff --git a/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/deif/DeifXdi.kt b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/deif/DeifXdi.kt new file mode 100644 index 0000000..e98daa6 --- /dev/null +++ b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/deif/DeifXdi.kt @@ -0,0 +1,111 @@ +package ru.setcorp.setprotocol.deif // Общий Android/JVM-порт находится в templates, без зависимости от приложения. +import java.nio.ByteBuffer // Caller-owned direct buffer обеспечивает выравнивание и управляемое JVM время жизни. +import ru.setcorp.setprotocol.NativeSetProtocol // Загрузку общей нативной библиотеки выполняет существующий порт. + +internal object NativeDeifBridge { // Только JNI-объявления; здесь нет второго кодека или автомата. + external fun size(): Int // Размер private C-состояния сообщает само ядро. + external fun initialize(state: ByteBuffer, node: Int, source: Int, xdi: Boolean, automatic: Boolean, pdo: Int, group: Int, services: Boolean, monitorId: Long): Boolean // Профиль проверяет C. + external fun start(state: ByteBuffer, nowMs: Long, reset: Boolean): Boolean // Время передаётся явно для воспроизводимых тестов. + external fun stop(state: ByteBuffer) // Выключенный сервер не производит heartbeat. + external fun accept(state: ByteBuffer, id: Long, data: ByteArray, flags: Int, nowMs: Long): Boolean // Байты обрабатывает общий C-код. + external fun poll(state: ByteBuffer, nowMs: Long): IntArray // Готовые события возвращаются скалярами id, dlc, data[8]. + external fun snapshot(state: ByteBuffer, nowMs: Long, expiryMs: Int): DoubleArray // Числа, статусы и сроки уже вычислены в C. + external fun master(node: Int, values: IntArray, id: Long, dam: Boolean): IntArray // Все пять MPDO и отдельное задание строятся общим C-каталогом. + external fun make(field: Int, node: Int, instance: Int, value: Int, id: Long, dam: Boolean): IntArray // Яркость, палитра и измерения возвращаются готовым кадром. + external fun service(nmt: Boolean, node: Int, value: Int): IntArray // C формирует собственный heartbeat либо адресную локальную NMT-команду. + external fun selector(field: Int, node: Int, instance: Int, dam: Boolean): ByteArray // Каталожный селектор возвращается непрозрачным четырёхбайтным результатом. + external fun bind(state: ByteBuffer, field: Int, selector: ByteArray, scale: Double): Boolean // Явные привязки и масштабы проверяет нативный профиль. + external fun binding(state: ByteBuffer, field: Int): DoubleArray // Исходные коэффициенты читаются из C вместо второй таблицы GUI. + external fun validate(id: Long, data: ByteArray, slave: Int): Boolean // Роли MASTER и серверного SLAVE проверяются одним переносимым списком разрешений. + external fun selectorInfo(selector: ByteArray): IntArray // Редактор получает Node, индекс, подиндекс и режим из общего C-декодера. + external fun readdress(selector: ByteArray, node: Int): ByteArray // C меняет только адрес, сохраняя пользовательский объект и режим SAM/DAM. + external fun inspect(id: Long, data: ByteArray, flags: Int): IntArray // Журнал получает единый результат декодирования. +} // ABI не раскрывает Kotlin layout внутренних структур. +data class DeifFrame(val canId: Long, val data: ByteArray) // Готовый STD data frame передаётся существующему CAN-транспорту приложения. +data class DeifSnapshot( // Неизменяемая модель пригодна для Compose, другого GUI и JVM-тестов. + val active: Boolean, val nmt: Int, val accepted: Int, // Жизненный цикл и число действительно принятых MPDO. + val brightness: Int, val palette: Int, // Значения текущего профиля подсветки. + val angle: Double?, val angleIsSetpoint: Boolean, // Фактический угол отделён от явно помеченного принятого задания. + val values: List, val statuses: List, val lostFields: Set, // Порядок полей задаёт общий ABI C, недействительные числа не подменяются нулями. +) // Снимок не содержит указателя на состояние C. +class DeifXdi(node: Int = 13, source: Int = 1, xdi: Boolean = true, automatic: Boolean = true, pdo: Int = 2, group: Int = 1, private val services: Boolean = false, monitorId: Long = 0) : AutoCloseable { // Один независимый прибор на экземпляр. + private val state: ByteBuffer // Память остаётся управляемой JVM, C не использует malloc. + init { // Отсутствующее ядро является явной ошибкой сборки, fallback на Kotlin запрещён. + check(NativeSetProtocol.available) { "Не загружено общее C-ядро DEIF" } // Приложение не должно молча использовать иной алгоритм. + state = ByteBuffer.allocateDirect(NativeDeifBridge.size()) // Размер и выравнивание не дублируют private C-структуру. + require(NativeDeifBridge.initialize(state, node, source, xdi, automatic, pdo, group, services, monitorId)) { "DEIF: неверный Node-ID, источник или RPDO" } // Ограничения XDi-net проверяет C. + } // Создание пассивного наблюдателя ничего не отправляет. + @Synchronized fun start(nowMs: Long, resetValues: Boolean = true) { // NMT и таймеры безопасны при приёме и тиках из разных потоков. + check(NativeDeifBridge.start(state, nowMs, resetValues)) { "Не удалось запустить DEIF" } // Boot-up создаётся только в C-сервере. + } // Физическую отправку выбирает приложение по результату poll. + @Synchronized fun accept(id: Long, data: ByteArray, extended: Boolean = false, remote: Boolean = false, nowMs: Long): Boolean { // Имя транспорта фильтруется приложением до этого вызова. + return NativeDeifBridge.accept(state, id, data, (if (extended) 1 else 0) or (if (remote) 2 else 0), nowMs) // Флаги описывают тип CAN, payload не разбирается в Kotlin. + } // C различает NMT, MPDO, heartbeat и SDO. + @Synchronized fun poll(nowMs: Long): List { // События выдаются один раз, даже если экран журнала стоит на паузе. + return NativeDeifBridge.poll(state, nowMs).asList().chunked(10).map { row -> DeifFrame(row[0].toLong(), ByteArray(row[1]) { row[it + 2].toByte() }) } // Это раскладка скалярного ABI JNI, а не CAN-кодек. + } // Готовые byte arrays не меняются в транспортном слое. + @Synchronized fun snapshot(nowMs: Long): DeifSnapshot { // Тайм-аут наблюдателя сохраняет совместимость Desktop; сервер хранит число при Data lost. + val raw = NativeDeifBridge.snapshot(state, nowMs, if (services) 0 else 5000) // Правило выбора и свежести вычисляет C. + return DeifSnapshot(raw[0] != 0.0, raw[1].toInt(), raw[5].toInt(), raw[7].toInt(), raw[8].toInt(), if (raw[34] != 0.0) raw[35] else null, raw[34] == 2.0, // Метаданные профиля и готовый азимут. + List(6) { field -> val flags = raw[13 + field * 4].toInt(); if (flags and 2 != 0 && flags and 4 == 0) raw[10 + field * 4] else null }, // Порт отображает valid/stale-флаги, не повторяя таймеры. + List(6) { raw[12 + it * 4].toInt() }, (0..5).filter { raw[36].toInt() and (1 shl it) != 0 }.toSet()) // Имена и цвета ошибок остаются ответственностью GUI. + } // Снимок можно использовать в UI без обращения к байтам протокола. + @Synchronized fun bind(binding: DeifBinding) { // Пользовательский профиль передаёт селектор без разбора адресного байта в Kotlin. + val bytes = selectorBytes(binding.selector) // Снимается только текстовое HEX-кодирование пользовательского поля. + require(NativeDeifBridge.bind(state, binding.field, bytes, binding.scale)) { "Неверная привязка либо масштаб DEIF" } // Нативный профиль проверяет номер поля и конечность коэффициента. + } // Изменение привязки сбрасывает только связанные с ней измерения по правилам C. + @Synchronized fun binding(field: Int): DeifBinding { // GUI получает текущий каталожный либо пользовательский профиль. + val raw = NativeDeifBridge.binding(state, field); require(raw.size == 6) { "Неизвестное поле DEIF" } // Шесть скаляров являются границей JNI, а не смещениями CAN-пакета. + return DeifBinding(field, if (raw[5] == 0.0) "" else (0..3).joinToString(" ") { "%02X".format(raw[it].toInt()) }, raw[4]) // Непрозрачные байты форматируются для сохранения и ручного редактирования. + } // Исходные масштабы не дублируются в приложении Android. + @Synchronized override fun close() { NativeDeifBridge.stop(state) } // Жизненный цикл отменяет heartbeat и очередь до закрытия адаптера. + companion object { // Диагностическое представление не содержит второго парсера. + private fun frames(raw: IntArray): List { // Все builders возвращают единый скалярный формат JNI. + require(raw.isNotEmpty() && raw.size % 10 == 0) { "Неверные параметры команды DEIF" } // Пустой результат C означает отказ вместо частично сформированного кадра. + return raw.asList().chunked(10).map { row -> DeifFrame(row[0].toLong(), ByteArray(row[1]) { row[it + 2].toByte() }) } // Копирование готовых байтов не интерпретирует wire-поля. + } // Упаковка JNI одинакова для данных MASTER, диммера и служебных команд. + private fun available() { check(NativeSetProtocol.available) { "Не загружено общее C-ядро DEIF" } } // Нативная ошибка не заменяется алгоритмом Kotlin. + private fun selectorBytes(text: String): ByteArray { // Текст HEX является форматом пользовательских настроек, а не вторым кодеком протокола. + val hex = text.filterNot { it.isWhitespace() }; require(hex.isEmpty() || hex.length == 8) { "Селектор DEIF должен содержать четыре HEX-байта либо быть пустым" } // Размер ограничивает доступ JNI к четырёхбайтному селектору. + return hex.chunked(2).map { it.toInt(16).toByte() }.toByteArray() // Порядок байтов сохраняется буквально и интерпретируется только C-ядром. + } // Одинаковая текстовая обработка применяется к привязкам и миграции их адресов. + fun selectorInfo(selector: String): DeifSelectorInfo? { // Редактор сравнивает смысл адреса, не извлекая маски CANopen в Kotlin. + available(); val bytes = selectorBytes(selector); if (bytes.isEmpty()) return null // Отключённое поле остаётся без адреса и не участвует в миграции. + val raw = NativeDeifBridge.selectorInfo(bytes); require(raw.size == 4) { "Неверный селектор DEIF" } // Все четыре семантических поля возвращает существующий C-декодер. + return DeifSelectorInfo(raw[0], raw[1], raw[2], raw[3] != 0) // Именованная модель исключает номера ABI-позиций из Compose. + } // Произвольный пользовательский индекс не заменяется стандартным объектом из базы. + fun readdress(selector: String, node: Int): String { // Перенос адреса сохраняет ручные привязки и режим SAM/DAM. + available(); val bytes = selectorBytes(selector); if (bytes.isEmpty()) return "" // Явно отключённое поле не включается при смене адресов. + val result = NativeDeifBridge.readdress(bytes, node); require(result.size == 4) { "Неверный Node-ID DEIF" } // Новый адрес проверяет и применяет только переносимое C-ядро. + return result.joinToString(" ") { "%02X".format(it.toInt() and 255) } // HEX остаётся прозрачным форматом хранения непрозрачных байтов. + } // Сетевая формула адресного байта не дублируется в порту. + fun master(node: Int, values: IntArray, id: Long, dam: Boolean): List { // Порядок пяти объектов и отдельный азимут задаёт только C-каталог. + available(); return frames(NativeDeifBridge.master(node, values, id, dam)) // Адреса и диапазон I16 проверяются до передачи результата. + } // GUI выбирает нужные готовые кадры без повторного построения payload. + fun make(field: Int, node: Int, instance: Int, value: Int, id: Long, dam: Boolean): DeifFrame { // Единый builder поддерживает команды экрана и измерительные данные. + available(); return frames(NativeDeifBridge.make(field, node, instance, value, id, dam)).single() // Ошибка C становится явным отказом API. + } // Формулы индексов, COB-ID и endian остаются в переносимом ядре. + fun service(nmt: Boolean, node: Int, value: Int): DeifFrame { // Локальное NMT отделено от физической валидации MASTER. + available(); return frames(NativeDeifBridge.service(nmt, node, value)).single() // Готовый служебный кадр создаётся существующим C-builder. + } // Порт не собирает двухбайтовую команду вручную. + fun selector(field: Int, node: Int, instance: Int = 1, dam: Boolean = false): ByteArray { // Каталожный редактор может выбирать экземпляр и режим SAM либо DAM. + available(); return NativeDeifBridge.selector(field, node, instance, dam).also { require(it.size == 4) { "Неверный объект, экземпляр или адрес DEIF" } } // Неверный каталог не подменяется произвольным селектором. + } // Преобразование в HEX при отображении остаётся ответственностью GUI. + fun validate(frame: DeifFrame, slave: Int = 0): Boolean { // Перед физической отправкой проверяется роль владельца кадра. + available(); return NativeDeifBridge.validate(frame.canId, frame.data, slave) // MASTER и ответы собственного SLAVE используют тот же C-список разрешений, что Desktop. + } // Произвольные NMT и SDO не открываются через измерительный маршрут MASTER. + fun inspect(id: Long, data: ByteArray, extended: Boolean = false, remote: Boolean = false): IntArray { // Приложение передаёт целый транспортный кадр. + check(NativeSetProtocol.available) { "Не загружено общее C-ядро DEIF" } // Без C-декодера никакого угадывания формата нет. + return NativeDeifBridge.inspect(id, data, (if (extended) 1 else 0) or (if (remote) 2 else 0)) // Индексы результата закреплены ABI deif_xdi.h. + } // Один и тот же вход даёт одинаковые поля в Python и Android. + fun summary(id: Long, data: ByteArray, extended: Boolean = false, remote: Boolean = false): String { // Только локализованный текст поверх метаданных C. + val m = inspect(id, data, extended, remote) // Никакого endian-разбора в Kotlin. + return when (m[0]) { // Код результата сообщает общий декодер. + 2 -> "Heartbeat/Boot-up · Node ${m[2]} · NMT ${m[11]}" // Состояние относится к узлу, а не к подтверждению показаний. + 1 -> "DEIF Node ${m[2]} · 0x%04X:%02X · RAW %d".format(m[3], m[4], m[5]) // Физические единицы показывает отдельный снимок модели. + 3 -> "DEIF · яркость/Color · ${m[5]}" // U8 подсветки не получает масштаб RPM. + else -> "DEIF: кадр не принят, код ${m[0]}" // Неизвестный объект не интерпретируется заново портом. + } // Текст не влияет на протокольное принятие. + } // Журнал и индикатор используют один C-каталог. + } // Общий порт не зависит от конкретного Android-приложения. +} // Контекст освобождается JVM после закрытия владельца. diff --git a/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/trends/GuiGasWatch2.kt b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/trends/GuiGasWatch2.kt new file mode 100644 index 0000000..c086fa4 --- /dev/null +++ b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/trends/GuiGasWatch2.kt @@ -0,0 +1,73 @@ +package ru.setcorp.setprotocol.trends // Размещает независимый от Android UI фасад подписок рядом с существующей поддержкой трендов. + +import java.util.Collections // Предоставляет неизменяемую оболочку коллекций, которую нельзя обойти приведением List к MutableList. +import ru.setcorp.setprotocol.NativeSetProtocol // Подключает единственный C-кодек через тонкие JNI-преобразования без повторного разбора wire-формата в Kotlin. + +object GuiGasWatch2 { // Объединяет проверяемые операции GAS_WATCH2 и модель состояния отдельного подключения. + const val SET = 0x14 // Идентификатор сообщения установки GAS_WATCH2 по согласованному GUI-контракту; содержимое payload формирует только C. + const val DATA = 0x15 // Идентификатор сообщения снимка GAS_WATCH2 по согласованному GUI-контракту; содержимое payload проверяет только C. + + class Config(val configId: Long, val periodMs: Int, addresses: List) { // Хранит неизменяемую конфигурацию: ненулевой u32 идентификатор, период в миллисекундах и упорядоченные адреса слов. + val addresses: List = Collections.unmodifiableList(ArrayList(addresses)) // Копирует внешний список и запрещает последующее изменение уже ожидаемой или активной конфигурации. + init { // Проверяет только границы преобразования JVM-чисел в C-типы; правила количества, дублей и остановки остаются в C-кодеке. + require(configId in 1L..0xFFFFFFFFL) { "Идентификатор конфигурации должен быть ненулевым u32" } // Не допускает потери старших битов или отрицательного Long при передаче идентификатора в uint32_t. + require(periodMs in 0..0xFFFF) { "Период должен помещаться в u16 миллисекунд" } // Сохраняет значение периода без усечения при преобразовании Int в uint16_t. + require(this.addresses.all { it in 0..0xFFFF }) { "Адрес GAS должен помещаться в u16" } // Проверяет каждый адрес до преобразования массива Int в массив 16-битных слов на JNI-границе. + } // Завершает проверки числового представления без добавления собственного кодека. + override fun equals(other: Any?): Boolean = other is Config && configId == other.configId && periodMs == other.periodMs && addresses == other.addresses // Сравнивает полную конфигурацию, чтобы запоздалое подтверждение не подошло другому порядку адресов. + override fun hashCode(): Int = 31 * (31 * configId.hashCode() + periodMs) + addresses.hashCode() // Согласует хеш с теми же тремя полями; множитель 31 служит обычным смешиванием хеша и не относится к протоколу. + } // Завершает модель конфигурации, общую для кодека и состояния подключения. + + class Sample(val configId: Long, val sequence: Long, val timestampMs: Long, values: List) { // Представляет один проверенный снимок с приборным временем в миллисекундах и положительным u32 номером последовательности. + val values: List = Collections.unmodifiableList(ArrayList(values)) // Фиксирует порядок слов активной конфигурации; null явно сохраняет признак невалидного канала вместо подстановки нуля. + } // Завершает неизменяемый снимок, пригодный для графика и записи без дополнительного разбора payload. + + fun request(config: Config): ByteArray { // Формирует payload установки или остановки подписки исключительно общим C-кодеком. + check(NativeSetProtocol.available) { "Общая библиотека SETProtocol недоступна" } // Не допускает скрытого перехода на другой кодек при отсутствии JNI-библиотеки. + return requireNotNull(NativeSetProtocol.nativeGasWatchRequest(config.configId, config.periodMs, config.addresses.toIntArray())) { "Некорректная конфигурация GAS_WATCH2" } // Делегирует C проверку лимита, дублей и согласованности нулевого периода с пустым списком. + } // Возвращает готовые байты без изменения состояния какого-либо подключения. + + fun validateAck(payload: ByteArray, config: Config) { // Проверяет полное эхо ожидаемой конфигурации, не делая выводов по одному количеству каналов. + check(NativeSetProtocol.available) { "Общая библиотека SETProtocol недоступна" } // Требует тот же C-кодек, который сформировал запрос. + require(NativeSetProtocol.nativeGasWatchAck(payload, config.configId, config.periodMs, config.addresses.toIntArray())) { "Подтверждение GAS_WATCH2 не соответствует конфигурации" } // C сравнивает идентификатор, период, число и точную последовательность адресов с ожидаемыми. + } // Завершает проверку ACK без самовольного переключения конфигурации. + + fun decode(payload: ByteArray, config: Config): Sample { // Преобразует только результат C-декодера; схема бинарного пакета в Kotlin отсутствует. + check(NativeSetProtocol.available) { "Общая библиотека SETProtocol недоступна" } // Сохраняет единый источник правил валидации снимков. + val decoded = requireNotNull(NativeSetProtocol.nativeGasWatchDecode(payload, config.configId, config.addresses.size)) { "Снимок GAS_WATCH2 не соответствует активной конфигурации" } // C отклоняет чужой идентификатор, неверное количество, длину, маску валидности и повреждённые поля. + return Sample(config.configId, decoded[0], decoded[1], decoded.drop(2).map { if (it < 0L) null else it.toInt() }) // Два первых элемента JNI-результата содержат sequence и время; −1 остальных элементов переводится в null без повторного wire-декодирования. + } // Возвращает снимок только после успешной проверки общей библиотекой. + + class Session { // Изолирует подтверждённую и ожидающую подписки одного подключения, чтобы разные приборы не делили состояние. + @Volatile var active: Config? = null // Публикует только подтверждённую конфигурацию; volatile обеспечивает видимость чтения с другого потока JVM. + private set // Запрещает внешнему коду обходить проверку полного ACK при изменении активной конфигурации. + @Volatile var pending: Config? = null // Хранит последний успешно построенный запрос отдельно от действующей подписки. + private set // Не позволяет потребителю подменить ожидаемую конфигурацию без вызова request. + + @Synchronized fun request(config: Config): ByteArray { // Сериализует формирование запросов и подтверждения, сохраняя атомарность переходов состояния. + require(active?.let { it.configId != config.configId || it == config } != false) { "Активный идентификатор GAS_WATCH2 уже связан с другой конфигурацией" } // Запрещает присвоить действующему идентификатору иной период или список, сохраняя допустимость идентичного повтора. + require(pending?.let { it.configId != config.configId || it == config } != false) { "Ожидающий идентификатор GAS_WATCH2 уже связан с другой конфигурацией" } // Не допускает неоднозначности одинаковых идентификаторов у двух различающихся ожидающих запросов. + val payload = GuiGasWatch2.request(config) // Сначала получает успешно проверенный C-кодеком payload; ошибка оставляет обе конфигурации неизменными. + pending = config // Запоминает именно последний запрос и оставляет active действующей до получения полного ACK. + return payload // Передаёт вызывающему коду готовый payload для отправки выбранным транспортом. + } // Завершает атомарную постановку ожидающей конфигурации. + + @Synchronized fun validateAck(payload: ByteArray, config: Config) { // Применяет подтверждение только к конфигурации последнего запроса этого подключения. + require(pending == config) { "Получено запоздалое или незапрошенное подтверждение GAS_WATCH2" } // Даже корректный старый ACK не может вернуть уже заменённый ожидающий список. + GuiGasWatch2.validateAck(payload, config) // Проверяет в C полное эхо до каких-либо изменений active или pending. + active = config // Атомарно переключает декодирование входящих снимков на подтверждённый список адресов. + pending = null // Убирает завершённый запрос, чтобы повторный ACK не считался новым подтверждением. + } // Завершает переход к новой активной подписке только после двух проверок ACK. + + @Synchronized fun sample(payload: ByteArray): Sample { // Декодирует снимок по стабильному активному списку даже во время ожидания нового ACK. + val config = checkNotNull(active) { "Нет подтверждённой конфигурации GAS_WATCH2" } // Отклоняет данные до первого подтверждения вместо угадывания адресов по ожидающему запросу. + check(config.periodMs != 0) { "Подписка GAS_WATCH2 остановлена" } // Не принимает запоздалые данные после подтверждённой остановки потока. + return GuiGasWatch2.decode(payload, config) // Делегирует C проверку активного идентификатора и количества каналов вместе с форматом снимка. + } // Возвращает только снимки подтверждённой работающей подписки. + + @Synchronized fun reset() { // Сбрасывает состояние при разрыве связи до повторной настройки нового подключения. + active = null // Не позволяет принять пакет предыдущего соединения до нового подтверждения конфигурации. + pending = null // Не позволяет запоздалому ACK прежнего соединения активировать старый список. + } // Завершает согласованный сброс обоих состояний подключения. + } // Завершает диспетчер одного подключения, не привязанный к UI или конкретному транспорту. +} // Завершает Android-фасад GAS_WATCH2, использующий единственный C-кодек. diff --git a/c/set-protocol/ports/android/set_deif_jni.c b/c/set-protocol/ports/android/set_deif_jni.c new file mode 100644 index 0000000..f77f6a0 --- /dev/null +++ b/c/set-protocol/ports/android/set_deif_jni.c @@ -0,0 +1,85 @@ +#include /* JNI здесь преобразует только контейнеры Java и указатели C. */ +#include "deif_xdi.h" /* Все правила DEIF принадлежат общему переносимому ядру. */ +static void *deif_context(JNIEnv *e,jobject b) { /* Direct ByteBuffer владеет памятью состояния и освобождается JVM. */ + if(!b || (*e)->GetDirectBufferCapacity(e,b)<(jlong)setp_deif_state_size()) return NULL; return (*e)->GetDirectBufferAddress(e,b); /* Не допускаем короткий либо недиректный буфер. */ +} /* JNI не копирует private-layout структуры. */ +static int deif_input(JNIEnv *e,jbyteArray a,uint8_t *d) { /* Classic CAN ограничен восемью байтами. */ + jsize n; if(!a) return -1; n=(*e)->GetArrayLength(e,a); if(n>8) return -1; (*e)->GetByteArrayRegion(e,a,0,n,(jbyte *)d); return (int)n; /* Буфер локален текущему вызову JNI. */ +} /* Время жизни Java-указателей не пересекает вызов. */ +JNIEXPORT jint JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_size(JNIEnv *e,jobject self) { (void)e; (void)self; return (jint)setp_deif_state_size(); } /* Kotlin выделяет точно нужный объём без heap в C. */ +JNIEXPORT jboolean JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_initialize(JNIEnv *e,jobject self,jobject b,jint node,jint source,jboolean xdi,jboolean automatic,jint pdo,jint group,jboolean services,jlong id) { /* Параметры профиля передаются без повторения правил. */ + void *s=deif_context(e,b); (void)self; if(!s || id<0 || id>0x1FFFFFFF) return JNI_FALSE; return setp_deif_init(s,setp_deif_state_size(),(unsigned)node,(unsigned)source,xdi!=0,automatic!=0,(unsigned)pdo,(unsigned)group,services!=0,(uint32_t)id)?JNI_TRUE:JNI_FALSE; /* Сервисный Node и RPDO проверяет C. */ +} /* Источником исходных привязок остаётся C-каталог. */ +JNIEXPORT jboolean JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_start(JNIEnv *e,jobject self,jobject b,jlong now,jboolean reset) { (void)self; return now>=0 && setp_deif_start(deif_context(e,b),(uint64_t)now,reset!=0)?JNI_TRUE:JNI_FALSE; } /* Часы Android передаются в монотонных миллисекундах. */ +JNIEXPORT void JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_stop(JNIEnv *e,jobject self,jobject b) { (void)self; setp_deif_stop(deif_context(e,b)); } /* Закрытие сервера прекращает очередь событий. */ +JNIEXPORT jboolean JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_accept(JNIEnv *e,jobject self,jobject b,jlong id,jbyteArray a,jint flags,jlong now) { /* Принимается готовый транспортом CAN-кадр. */ + uint8_t d[8]; int n=deif_input(e,a,d); (void)self; if(n<0 || id<0 || id>0x1FFFFFFF || now<0) return JNI_FALSE; return setp_deif_accept(deif_context(e,b),(uint32_t)id,d,(size_t)n,(unsigned)flags,(uint64_t)now)?JNI_TRUE:JNI_FALSE; /* JNI не разбирает индекс, подиндекс или signed I16. */ +} /* C обслуживает адресацию, NMT и SDO одинаково для Desktop и Android. */ +JNIEXPORT jintArray JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_poll(JNIEnv *e,jobject self,jobject b,jlong now) { /* Очередь возвращается массивом скаляров ABI, а не вторым CAN-пакетом. */ + setp_deif_frame_t frames[16]; jint values[160]; size_t n,i,j; jintArray result; (void)self; if(now<0) return NULL; n=setp_deif_poll(deif_context(e,b),(uint64_t)now,frames,16); /* Все исходящие байты уже сформированы C-ядром. */ + for(i=0;iNewIntArray(e,(jsize)(n*10)); if(result) (*e)->SetIntArrayRegion(e,result,0,(jsize)(n*10),values); return result; /* Владение результатом передаётся JVM. */ +} /* JNI не создаёт фиктивного ответного PDO. */ +JNIEXPORT jdoubleArray JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_snapshot(JNIEnv *e,jobject self,jobject b,jlong now,jint expiry) { /* Универсальный скалярный снимок пригоден без Compose. */ + void *s=deif_context(e,b); int64_t meta[10],m[4]; jdouble values[37]; double v; unsigned i; jdoubleArray result; (void)self; if(now<0 || expiry<0 || !setp_deif_meta(s,meta)) return NULL; /* Layout состояния не дублируется в Kotlin. */ + for(i=0;i<10;i++) values[i]=(double)meta[i]; for(i=0;i<6;i++) { setp_deif_read(s,i,(uint64_t)now,(unsigned)expiry,&v,m); values[10+i*4]=v; values[11+i*4]=(double)m[0]; values[12+i*4]=(double)m[2]; values[13+i*4]=(double)m[3]; } /* Масштабы, статусы и свежесть вычислены C. */ + values[34]=(double)setp_deif_angle(s,(uint64_t)now,(unsigned)expiry,&v); values[35]=v; values[36]=setp_deif_lost(s,(uint64_t)now); /* Факт, задание и Data lost определяются общим алгоритмом. */ + result=(*e)->NewDoubleArray(e,37); if(result) (*e)->SetDoubleArrayRegion(e,result,0,37,values); return result; /* Java получает независимый неизменяемый снимок. */ +} /* Здесь нет системных часов и транспортного ввода-вывода. */ +JNIEXPORT jintArray JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_inspect(JNIEnv *e,jobject self,jlong id,jbyteArray a,jint flags) { /* Общий декодер доступен также журналу Android. */ + uint8_t d[8]; int32_t m[12]={0}; jint values[13]; int n=deif_input(e,a,d),code; unsigned i; jintArray result; (void)self; code=n<0 || id<0 || id>0x1FFFFFFF?-1:setp_deif_inspect((uint32_t)id,d,(size_t)n,(unsigned)flags,m); /* Только C знает wire-формат DEIF. */ + values[0]=code; for(i=0;i<12;i++) values[i+1]=m[i]; result=(*e)->NewIntArray(e,13); if(result) (*e)->SetIntArrayRegion(e,result,0,13,values); return result; /* Метаданные индексируются по ABI, не по смещениям CAN-data. */ +} /* Локализованные подписи формирует Kotlin. */ + +static jintArray deif_frames_java(JNIEnv *e,const setp_deif_frame_t *frames,size_t count) { /* Единая упаковка ABI возвращает готовые кадры, не интерпретируя их payload. */ + jint values[60]; size_t i,j; jintArray result; /* Пять объектов MASTER и отдельное задание азимута занимают не более шести записей по десять скаляров. */ + if(count>6U) count=0; /* Неверное число записей не должно выходить за пределы локального JNI-буфера. */ + for(i=0;iNewIntArray(e,(jsize)(count*10)); if(result && count) (*e)->SetIntArrayRegion(e,result,0,(jsize)(count*10),values); return result; /* Результатом владеет JVM, указатели C не сохраняются. */ +} /* Общий конвертер не является вторым кодеком CANopen. */ +JNIEXPORT jintArray JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_master(JNIEnv *e,jobject self,jint node,jintArray input,jlong id,jboolean dam) { /* Порядок объектов и отдельный set-point берутся из публичного C ABI. */ + jint raw[5]; int32_t values[5]; setp_deif_frame_t frames[6]; unsigned i; (void)self; /* Локальные буферы имеют фиксированные размеры контракта MASTER. */ + if(!input || (*e)->GetArrayLength(e,input)!=5 || id<0 || id>0x7FF) return deif_frames_java(e,NULL,0); /* Проверяем размеры Java-массива и отсутствие усечения идентификатора до вызова C. */ + (*e)->GetIntArrayRegion(e,input,0,5,raw); for(i=0;i<5;i++) values[i]=(int32_t)raw[i]; /* JNI преобразует скаляры без извлечения полей протокола. */ + if(setp_deif_master((unsigned)node,values,(uint32_t)id,dam!=0,2,frames)!=5 || !setp_deif_angle_command(frames,frames+5)) return deif_frames_java(e,NULL,0); /* Фактический угол и отдельное задание строит то же ядро, что Desktop. */ + return deif_frames_java(e,frames,6); /* Потребитель выбирает разрешённые объекты, сохраняя готовые байты каждого кадра. */ +} /* Неверная конфигурация не возвращает частично сформированный цикл. */ +JNIEXPORT jintArray JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_make(JNIEnv *e,jobject self,jint field,jint node,jint instance,jint value,jlong id,jboolean dam) { /* Общая операция покрывает измерения, яркость и палитру. */ + setp_deif_frame_t frame; (void)self; /* Возвращаемая структура заполняется только проверенным builder ядра. */ + if(id<0 || id>0x7FF || !setp_deif_make((unsigned)field,(unsigned)node,(unsigned)instance,(int32_t)value,(uint32_t)id,dam!=0,&frame)) return deif_frames_java(e,NULL,0); /* Диапазоны параметров и CAN-адресацию проверяет общий C-код. */ + return deif_frames_java(e,&frame,1); /* Kotlin получает один готовый STD data frame. */ +} /* UI не знает индексы диммера и расположение I16 в кадре. */ +JNIEXPORT jintArray JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_service(JNIEnv *e,jobject self,jboolean nmt,jint node,jint value) { /* Формирует heartbeat или локальный NMT через существующий C builder. */ + setp_deif_frame_t frame; (void)self; /* Буфер служебной команды ограничен одним Classic CAN кадром. */ + if(!setp_deif_service(nmt!=0,(unsigned)node,(unsigned)value,&frame)) return deif_frames_java(e,NULL,0); /* Адрес, команда и допустимое NMT-состояние проверяются C. */ + return deif_frames_java(e,&frame,1); /* Физический либо локальный маршрут выбирается приложением отдельно. */ +} /* NMT не попадает в физический маршрут MASTER автоматически. */ +JNIEXPORT jbyteArray JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_selector(JNIEnv *e,jobject self,jint field,jint node,jint instance,jboolean dam) { /* Каталожные привязки формирует единый переносимый справочник. */ + uint8_t selector[4]; jbyteArray result; int ok; (void)self; /* Селектор является непрозрачным четырёхбайтовым результатом C. */ + ok=setp_deif_selector((unsigned)field,(unsigned)node,(unsigned)instance,dam!=0,selector); result=(*e)->NewByteArray(e,ok?4:0); /* Неизвестный объект возвращает пустой результат для явной ошибки Kotlin. */ + if(result && ok) (*e)->SetByteArrayRegion(e,result,0,4,(jbyte *)selector); return result; /* JNI копирует массив без endian-преобразований. */ +} /* Android и Desktop используют один каталог объектов DEIF. */ +JNIEXPORT jboolean JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_bind(JNIEnv *e,jobject self,jobject buffer,jint field,jbyteArray input,jdouble scale) { /* Ручная привязка передаётся ядру как непрозрачные байты и масштаб. */ + uint8_t selector[8]={0}; int count=deif_input(e,input,selector); (void)self; /* Общий копирующий адаптер ограничивает доступ к Java-массиву. */ + if(count!=0 && count!=4) return JNI_FALSE; return setp_deif_bind(deif_context(e,buffer),(unsigned)field,count?selector:NULL,(double)scale)?JNI_TRUE:JNI_FALSE; /* Пустая привязка отключает поле; допустимость масштаба проверяет C. */ +} /* Обновление привязок не требует знания private-layout контекста. */ +JNIEXPORT jdoubleArray JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_binding(JNIEnv *e,jobject self,jobject buffer,jint field) { /* Чтение текущей привязки исключает вторую таблицу исходных коэффициентов в GUI. */ + uint8_t selector[4]={0}; double scale=0; jdouble values[6]; jdoubleArray result; int bound; unsigned i; (void)self; /* Четыре байта, масштаб и флаг активности составляют скалярный JNI-контракт. */ + if(field<0 || field>5 || !deif_context(e,buffer)) return (*e)->NewDoubleArray(e,0); bound=setp_deif_get_binding(deif_context(e,buffer),(unsigned)field,selector,&scale); /* Недопустимый номер не должен возвращать выдуманную привязку. */ + for(i=0;i<4;i++) values[i]=selector[i]; values[4]=scale; values[5]=bound; result=(*e)->NewDoubleArray(e,6); /* Байты сохраняются скалярами без интерпретации адресного бита или индекса. */ + if(result) (*e)->SetDoubleArrayRegion(e,result,0,6,values); return result; /* JVM владеет неизменяемой копией настроек. */ +} /* Пользовательский HEX является только форматом хранения профиля. */ +JNIEXPORT jboolean JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_validate(JNIEnv *e,jobject self,jlong id,jbyteArray input,jint slave) { /* Последний рубеж различает разрешённые команды MASTER и ответы собственного SLAVE. */ + uint8_t data[8]; int count=deif_input(e,input,data); (void)self; /* Payload остаётся ограниченным размером Classic CAN. */ + return count>=0 && id>=0 && id<=0x7FF && setp_deif_validate((uint32_t)id,data,(size_t)count,0,(unsigned)slave)?JNI_TRUE:JNI_FALSE; /* Все списки допустимых объектов и служебных кадров находятся в C-ядре. */ +} /* NMT и произвольный SDO не могут пройти в физический маршрут MASTER. */ +JNIEXPORT jintArray JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_selectorInfo(JNIEnv *e,jobject self,jbyteArray input) { /* Редактор получает семантические поля селектора через существующий C-декодер. */ + uint8_t selector[8]; int32_t metadata[4]; jint values[4]; jintArray result; unsigned i; int ok; (void)self; /* Четыре скаляра описывают Node-ID, индекс, подиндекс и признак DAM. */ + ok=deif_input(e,input,selector)==4 && setp_deif_selector_info(selector,metadata); result=(*e)->NewIntArray(e,ok?4:0); /* Порт не извлекает адресные маски либо little-endian индекс повторно. */ + if(result && ok) { for(i=0;i<4;i++) values[i]=(jint)metadata[i]; (*e)->SetIntArrayRegion(e,result,0,4,values); } return result; /* Контейнер результата принадлежит JVM. */ +} /* Неизвестная ручная библиотечная переменная сохраняет исходный индекс. */ +JNIEXPORT jbyteArray JNICALL Java_ru_setcorp_setprotocol_deif_NativeDeifBridge_readdress(JNIEnv *e,jobject self,jbyteArray input,jint node) { /* Смена адреса сохраняет пользовательский объект и режим SAM/DAM. */ + uint8_t selector[8],output[4]; jbyteArray result; int ok; (void)self; /* Размеры ограничены публичным четырёхбайтным контрактом привязки. */ + ok=deif_input(e,input,selector)==4 && setp_deif_readdress(selector,(unsigned)node,2,output); result=(*e)->NewByteArray(e,ok?4:0); /* Режим 2 существующего C ABI оставляет выбранный ранее SAM либо DAM. */ + if(result && ok) (*e)->SetByteArrayRegion(e,result,0,4,(jbyte *)output); return result; /* Kotlin получает непрозрачный новый селектор без самостоятельной сборки адресного байта. */ +} /* Автоматическая миграция адресов использует те же операции, что Desktop. */ diff --git a/c/set-protocol/ports/android/setprotocol_jni.c b/c/set-protocol/ports/android/setprotocol_jni.c index 1d9c264..1cd7f44 100644 --- a/c/set-protocol/ports/android/setprotocol_jni.c +++ b/c/set-protocol/ports/android/setprotocol_jni.c @@ -11,6 +11,7 @@ #include "setprotocol_abi.h" #include "set_trends.h" +#include "set_gas_watch.h" /* Подключает единственный кодек GAS_WATCH2 и общие лимиты буферов, чтобы JNI не воспроизводил wire-формат. */ #include "set_spectrum.h" #include "balsam_can.h" #include "periph28335.h" @@ -547,6 +548,77 @@ Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeTrendWatchDecode( return result; } +static int gas_watch_copy_addresses(JNIEnv *env, jintArray input, uint16_t *addresses, jsize *count) /* Преобразует JVM IntArray в u16-массив без усечения; протокольные правила проверяет только C-кодек. */ +{ /* Начинает общий для запроса и ACK ограниченный переход между представлениями JNI и C. */ + if (input == NULL) return 0; /* Отклоняет отсутствующий массив до обращения к GetArrayLength, исключая исключение JNI из-за null. */ + *count = (*env)->GetArrayLength(env, input); /* Получает фактическое число адресов из JVM-массива, не доверяя внешнему счётчику. */ + if (*count > (jsize)SET_GAS_WATCH_MAX) return 0; /* Ограничивает копирование общим лимитом 64 слов до заполнения стековых массивов. */ + jint source[SET_GAS_WATCH_MAX]; /* Резервирует исходные знаковые JVM-числа по единственному лимиту из C-заголовка. */ + (*env)->GetIntArrayRegion(env, input, 0, *count, source); /* Копирует JVM-адреса без удержания указателей на управляемую память. */ + if ((*env)->ExceptionCheck(env)) return 0; /* Не использует частично скопированный массив, если JVM сообщила исключение доступа к массиву. */ + for (jsize index = 0; index < *count; ++index) { /* Проверяет каждое число до приведения к беззнаковому 16-битному адресу. */ + if (source[index] < 0 || source[index] > UINT16_MAX) return 0; /* Не позволяет отрицательному или слишком большому Int превратиться в другой действительный GAS-адрес. */ + addresses[index] = (uint16_t)source[index]; /* Сохраняет проверенный адрес без потери битов; порядок остаётся равным порядку конфигурации. */ + } /* Завершает безопасное преобразование адресов без сортировки, удаления дублей или иной протокольной логики. */ + return 1; /* Сообщает вызывающей JNI-функции, что массив готов для проверки общим C-кодеком. */ +} /* Завершает вспомогательное преобразование числовых типов JNI. */ + +JNIEXPORT jbyteArray JNICALL /* Экспортирует JNI-метод, возвращающий готовые байты конфигурации GAS_WATCH2 либо null при отказе. */ +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeGasWatchRequest( /* Связывает метод с объявлением NativeSetProtocol.nativeGasWatchRequest без регистрации второго кодека. */ + JNIEnv *env, jobject self, jlong config_id, jint period, jintArray input) /* Принимает u32 id в положительном Long, период в миллисекундах и JVM-массив адресов u16. */ +{ /* Начинает тонкий адаптер формирования запроса через общее C-ядро. */ + (void)self; /* Объект Kotlin не содержит данных, необходимых переносимому C-кодеку. */ + if (config_id <= 0 || (uint64_t)config_id > UINT32_MAX || period < 0 || period > UINT16_MAX) return NULL; /* Проверяет границы до приведения Long и Int, исключая потерю битов идентификатора или периода. */ + jsize count = 0; /* Получит число адресов только после проверки фактического JVM-массива. */ + uint16_t addresses[SET_GAS_WATCH_MAX]; /* Выделяет адреса на стеке по общему C-лимиту подписки без динамических выделений. */ + uint8_t output[SET_GAS_WATCH_CONFIG_MAX]; /* Выделяет максимально допустимый payload по C-константе вместо повторного расчёта wire-размеров в адаптере. */ + if (!gas_watch_copy_addresses(env, input, addresses, &count)) return NULL; /* Не передаёт C-кодеку адреса, которые нельзя точно представить как u16. */ + size_t size = set_gas_watch_request((uint32_t)config_id, (uint16_t)period, addresses, (size_t)count, output, sizeof output); /* Единственный C builder проверяет геометрию и создаёт канонический payload конфигурации. */ + return tms_result(env, output, size); /* Копирует результат в ByteArray существующим общим JNI-помощником; нулевая длина C-отказа превращается в null. */ +} /* Завершает запрос без хранения или изменения состояния подписки на JNI-стороне. */ + +JNIEXPORT jboolean JNICALL /* Экспортирует JNI-проверку полного подтверждения конфигурации GAS_WATCH2. */ +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeGasWatchAck( /* Связывает метод с NativeSetProtocol.nativeGasWatchAck для проверки точного эхо-ответа. */ + JNIEnv *env, jobject self, jbyteArray input, jlong config_id, jint period, jintArray expected) /* Принимает payload ACK и исходные ожидаемые параметры без извлечения полей в JNI. */ +{ /* Начинает адаптер проверки ACK, делегирующий правила общему C-кодеку. */ + (void)self; /* Kotlin-объект служит только точкой вызова и не участвует в сравнении wire-полей. */ + if (input == NULL || config_id <= 0 || (uint64_t)config_id > UINT32_MAX || period < 0 || period > UINT16_MAX) return JNI_FALSE; /* Отбрасывает null и числа, которые были бы усечены при переходе к C-типам. */ + jsize count = 0; /* Получит проверенное количество исходных адресов для полного сравнения ACK в C. */ + uint16_t addresses[SET_GAS_WATCH_MAX]; /* Хранит ожидаемые адреса в том же исходном порядке, которым определяются позиции значений снимка. */ + if (!gas_watch_copy_addresses(env, expected, addresses, &count)) return JNI_FALSE; /* Не сравнивает ACK с недопустимым JVM-массивом или усечёнными адресами. */ + jsize size = (*env)->GetArrayLength(env, input); /* Получает длину ACK для безопасного копирования ограниченного буфера. */ + if (size > (jsize)SET_GAS_WATCH_CONFIG_MAX) return JNI_FALSE; /* Отбрасывает превышение общего максимума до копирования на стек. */ + jbyte payload[SET_GAS_WATCH_CONFIG_MAX]; /* Резервирует payload по общей C-константе; проверка точной длины остаётся в set_gas_watch_ack. */ + (*env)->GetByteArrayRegion(env, input, 0, size, payload); /* Копирует байты ACK без ручного разбора их полей или порядка байтов. */ + if ((*env)->ExceptionCheck(env)) return JNI_FALSE; /* Не вызывает C-кодек, если JVM не смогла полностью скопировать входной массив. */ + return set_gas_watch_ack((const uint8_t *)payload, (size_t)size, (uint32_t)config_id, (uint16_t)period, addresses, (size_t)count) ? JNI_TRUE : JNI_FALSE; /* Проверяет C-кодеком весь echo, включая версию, id, период, количество, reserved и порядок адресов. */ +} /* Завершает проверку ACK без изменения активной или ожидающей конфигурации. */ + +JNIEXPORT jlongArray JNICALL /* Экспортирует JNI-декодер снимка с положительными u32 счётчиками и отдельным маркером невалидного слова. */ +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeGasWatchDecode( /* Связывает метод с NativeSetProtocol.nativeGasWatchDecode и единственным C-декодером GAS_WATCH2. */ + JNIEnv *env, jobject self, jbyteArray input, jlong config_id, jint expected_count) /* Принимает payload и параметры подтверждённой конфигурации, а не предполагаемые параметры из самого пакета. */ +{ /* Начинает ограниченное преобразование готового C-результата в JVM-массив. */ + (void)self; /* Все параметры ожидаемой подписки переданы явно; объект Kotlin не участвует в C-декодировании. */ + if (input == NULL || config_id <= 0 || (uint64_t)config_id > UINT32_MAX || expected_count < 0 || expected_count > (jint)SET_GAS_WATCH_MAX) return NULL; /* Проверяет null, u32 id и ограниченный count до приведения к C-типам и обращения к стековым буферам. */ + jsize size = (*env)->GetArrayLength(env, input); /* Получает длину входного JVM-массива без чтения каких-либо wire-полей. */ + if (size > (jsize)SET_GAS_WATCH_SAMPLE_MAX) return NULL; /* Гарантирует, что вход помещается в стековый буфер общего максимального размера снимка. */ + jbyte payload[SET_GAS_WATCH_SAMPLE_MAX]; /* Хранит исходный payload до завершения C-проверки версии, длины, id, count и bitmap. */ + uint16_t words[SET_GAS_WATCH_MAX]; /* Принимает от C сырые слова GAS без изменения знакового представления пользовательского параметра. */ + uint8_t valid[SET_GAS_WATCH_MAX]; /* Принимает от C уже проверенные признаки валидности по одному элементу на канал вместо повторного разбора bitmap. */ + uint32_t sequence = 0U, timestamp_ms = 0U; /* Принимает номер снимка и приборное время в миллисекундах как u32 без промежуточного знакового Int. */ + (*env)->GetByteArrayRegion(env, input, 0, size, payload); /* Копирует вход без удержания JVM-памяти и без воспроизведения протокольных смещений в адаптере. */ + if ((*env)->ExceptionCheck(env)) return NULL; /* Не использует частичный вход при исключении копирования JVM-массива. */ + int count = set_gas_watch_decode((const uint8_t *)payload, (size_t)size, (uint32_t)config_id, (size_t)expected_count, &sequence, ×tamp_ms, words, valid, SET_GAS_WATCH_MAX); /* C проверяет принадлежность снимка активной конфигурации и каноничность всего payload, возвращая число слов или −1. */ + if (count < 0) return NULL; /* Не публикует частично заполненные выходные данные после любой ошибки C-декодера. */ + jlong values[2U + SET_GAS_WATCH_MAX]; /* Два первых JVM-элемента принадлежат sequence и времени; остальные ограничены общим максимумом адресов. */ + values[0] = (jlong)sequence; /* Расширяет u32 номер снимка напрямую в положительный Long, включая значения с установленным bit31. */ + values[1] = (jlong)timestamp_ms; /* Расширяет u32 приборное время напрямую в положительный Long без потери старшего бита. */ + for (int index = 0; index < count; ++index) values[index + 2] = valid[index] ? (jlong)words[index] : -1; /* Передаёт валидное u16 слово как 0..65535, а невалидный канал как −1, которое Kotlin преобразует в null. */ + jlongArray result = (*env)->NewLongArray(env, count + 2); /* Создаёт ровно два элемента метаданных и по одному элементу на каждый проверенный канал снимка. */ + if (result != NULL) (*env)->SetLongArrayRegion(env, result, 0, count + 2, values); /* Копирует завершённый результат в управляемую память только после успешной C-проверки. */ + return result; /* Возвращает null при отказе JVM выделить массив и корректный LongArray во всех успешных случаях. */ +} /* Завершает JNI-декодер без второго протокольного алгоритма или собственной таблицы адресов. */ + typedef struct { uint8_t *storage; size_t storage_size; diff --git a/c/set-protocol/ports/android/tests/ru/setcorp/setflash/core/ProtoCanCatalogTest.kt b/c/set-protocol/ports/android/tests/ru/setcorp/setflash/core/ProtoCanCatalogTest.kt index 4cbc58e..5f032b6 100644 --- a/c/set-protocol/ports/android/tests/ru/setcorp/setflash/core/ProtoCanCatalogTest.kt +++ b/c/set-protocol/ports/android/tests/ru/setcorp/setflash/core/ProtoCanCatalogTest.kt @@ -14,14 +14,14 @@ class ProtoCanCatalogTest { fun bodyLayoutsMatchSetGuiBuilder() { assertEquals(0x1234, ProtoCanBody.broadcast(0x123, 0x4)) assertEquals(0x2001, ProtoCanBody.typed(ProtoCanAnalogType.U.code, 1)) - assertEquals(0x1234, ProtoCanBody.modbus(0x123, 4)) + assertEquals(0x123B, ProtoCanBody.modbus(0x123, 4, 3)) // Holding=3 и четыре регистра кодируются младшим полубайтом 1011. assertEquals(0xABCD, ProtoCanBody.error(0xAB, 0xCD)) assertEquals(0xFF01, ProtoCanBody.settings(0xFF, 0x01)) } @Test - fun messageRegistryCoversAllFourBitValues() { - assertEquals((0..0xF).toList(), ProtoCanMessageType.entries.map { it.code }) + fun messageRegistryReservesFormerModbusTypes() { // После объединения Modbus два кода остаются свободными, остальные сохраняют назначение. + assertEquals((0..0xF).filter { it != 6 && it != 7 }, ProtoCanMessageType.entries.map { it.code }) // Освобождённые MsgType 0x6/0x7 отсутствуют в каталоге после объединения Modbus. assertEquals("Settings", ProtoCanId.parse(0x17FE1234).messageTypeName) } } diff --git a/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/GasSlotsTest.kt b/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/GasSlotsTest.kt new file mode 100644 index 0000000..94e2563 --- /dev/null +++ b/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/GasSlotsTest.kt @@ -0,0 +1,34 @@ +package ru.setcorp.setprotocol // Проверяем тонкую Kotlin/JNI-границу общего C-кодека. +import org.junit.Assert.* // Сопоставляем точные CAN ID, wire-октеты и результаты отказа. +import org.junit.Test // Включаем проверки в существующий набор Android host tests. + +class GasSlotsTest { // Номер типа и маска проверяются настоящей shared-библиотекой. + @Test fun identifiersAndMask() { // Проверяем два адресных класса PERIPH и порядок Word0-маски. + val modes = intArrayOf(5, 6, 7, 8, 16, 31) // Номера совпадают с общими нормативными примерами. + val ids = longArrayOf(0x11540500L, 0x11640600L, 0x11740700L, 0x11840800L, 0x12041000L, 0x12F41F41L) // Тип 0x4 заменяет старый Coil без изменения адресов узлов. + val words = intArrayOf(14, 0x1234, 0xABCD, 0xFFFF) // Первое слово является маской, следующие три — независимыми значениями. + val payload = GasSlots.nativeEncode(words)!! // Только C-кодек формирует октеты и проверяет разрешённые биты маски. + assertArrayEquals(byteArrayOf(14, 0, 0x34, 0x12, 0xCD.toByte(), 0xAB.toByte(), 0xFF.toByte(), 0xFF.toByte()), payload) // Проверяем little-endian Word0 и всех трёх значений. + modes.forEachIndexed { index, mode -> // Дополнительно проверяем переход DeviceType после шестнадцати mode. + val slot = if (index == 5) 65 else 0 // Последний полный слот имеет индекс 65, неполный — 66. + assertEquals(ids[index], GasSlots.nativeRequestId(mode, slot, 0)) // Формула и номер типа находятся только в C. + val reply = GasSlots.nativeRequestId(mode, slot, 1) // Направление ответа задаётся явно. + assertArrayEquals(intArrayOf(mode, slot, 14, 0x1234, 0xABCD, 0xFFFF), GasSlots.nativeDecode(reply, 1, payload)) // Результат содержит маску отдельно от трёх значений. + } // Завершаем проверку независимых идентификаторов. + assertEquals(0x17E4FFFFL, GasSlots.nativeAddressId(7, 14, 65535, 0)) // Общий слотный API поддерживает независимый узел и максимальный адрес. + assertArrayEquals(words, GasSlots.nativeDecodeWords(0x1FE4FFFFL, 1, payload)) // Общий декодер не ограничен страницами PERIPH. + } // Конец проверки готовых кадров. + @Test fun invalidFrames() { // Ошибочный слот или маска не должны становиться другой командой. + assertEquals(0L, GasSlots.nativeRequestId(5, 67, 0)) // Значения за последним слотом 66 относятся к резерву. + assertEquals(0L, GasSlots.nativeAddressId(7, 14, 65536, 0)) // Полный адрес проверяется до сужения. + assertNull(GasSlots.nativeEncode(intArrayOf(1, 2, 3))) // Неполный payload не дополняется нулями. + assertNull(GasSlots.nativeEncode(intArrayOf(0, 1, 2, 3))) // Пустая маска запрещена. + assertNull(GasSlots.nativeEncode(intArrayOf(1, 1, 2, 3))) // Бит служебного Word0 не является битом значения. + assertNull(GasSlots.nativeEncode(intArrayOf(14, 1, 2, 65536))) // Число за пределами u16 не усекается. + val payload = GasSlots.nativeEncode(intArrayOf(14, 1, 2, 3))!! // Корректный кадр позволяет отдельно проверить адрес и флаги. + assertNull(GasSlots.nativeDecode(0x19540600L, 1, payload)) // Прибор 5 не обслуживает страницу mode 6. + assertNull(GasSlots.nativeDecode(0x19540500L, 3, payload)) // RTR не является ответом с данными. + assertNull(GasSlots.nativeDecode(0x19540542L, 1, payload)) // Последний слот не содержит Word3. + assertNull(GasSlots.nativeDecodeWords(0x19530500L, 1, payload)) // Тип 0x3 не принимается за слот при совпадении payload. + } // Конец отрицательных и граничных случаев. +} // Конец регрессионной проверки JNI. diff --git a/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/deif/DeifWorkspaceTest.kt b/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/deif/DeifWorkspaceTest.kt new file mode 100644 index 0000000..c56cfbd --- /dev/null +++ b/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/deif/DeifWorkspaceTest.kt @@ -0,0 +1,72 @@ +package ru.setcorp.setprotocol.deif // Тесты вызывают тот же общий контроллер и C-библиотеку, что Android GUI. +import org.junit.Assert.* // Проверяются точные кадры, маршруты и принятые физические значения. +import org.junit.Test // Обычные JVM-тесты не требуют запущенного Android-устройства. + +class DeifWorkspaceTest { // Здесь отсутствует резервная реализация кодека или автомата CANopen. + private fun hex(frame: DeifFrame) = frame.data.joinToString("") { "%02X".format(it.toInt() and 255) } // HEX служит только удобным форматом сравнения готового результата. + @Test fun masterAndDisplayBuildersUseSharedBytes() { // Расширенный JNI-порт должен совпадать с известными C- и Python-векторами. + val frames = DeifXdi.master(11, intArrayOf(900, -967, -509, -2098, -300), 0x30B, true) // DAM-получатель Node 11 использует RPDO2. + assertEquals(6, frames.size); assertTrue(frames.all { it.canId == 0x30BL && DeifXdi.validate(it) }) // Пять рабочих объектов и отдельное задание азимута проходят общую проверку MASTER. + assertEquals("8B01300284030000", hex(frames[0])); assertEquals("8B81300239FC0000", hex(frames[1])) // Угол и отрицательные обороты сохраняют опубликованный I16 LE формат. + assertEquals("8B01300784030000", hex(frames[5])) // Отдельная уставка не подменяет фактический объект угла. + assertEquals("8B0335024B000000", hex(DeifXdi.make(6, 11, 3, 75, 0x30B, true))) // Яркость 75% группы 3 остаётся U8 без масштаба RPM. + assertEquals("8B03350301000000", hex(DeifXdi.make(7, 11, 3, 1, 0x30B, true))) // Палитра Night передаётся отдельным объектом той же группы. + assertFalse(DeifXdi.validate(DeifXdi.service(true, 11, 1))) // Физический маршрут MASTER не разрешает локальную NMT-команду. + } // Числовые ожидания здесь являются эталонными тестовыми данными, а не кодеком порта. + @Test fun offlineSimulatorReceivesInteractiveCommandsWithoutTransport() { // Полный автономный сценарий должен работать без адаптера и исходящих физических кадров. + DeifWorkspace(DeifSettings(node = 11), true).use { session -> // Локальный SLAVE использует такой же Node-ID, как исходная desktop-пара. + assertTrue(runCatching { session.cycle(0) }.isFailure); assertTrue(runCatching { session.display(false, 75, 0) }.isFailure) // Выбранный локальный маршрут не возвращает физические кадры даже до запуска либо после остановки внутреннего SLAVE. + assertTrue(runCatching { session.startMaster(true, 0) }.isFailure); assertFalse(session.masterRunning) // Ошибочный локальный запуск не оставляет активный цикл, ожидающий будущего изменения маршрута. + session.startSlave(true, 0); assertTrue(session.tick(0).slave.isEmpty()) // Boot-up остаётся внутри локального стенда. + session.nmt(1, 0); session.setControl("angle", 37.1); session.setControl("rpm", 40.32); session.setControl("power", 63.9) // Касания воспроизводят задания со снимка пользователя. + val traffic = session.cycle(1); val snapshot = session.snapshot(1) // Передача проходит реальный C-builder и автомат приёма SLAVE. + assertTrue(traffic.master.isEmpty() && traffic.slave.isEmpty()); assertEquals(6, snapshot.accepted) // Локальный маршрут не вызывает внешний транспорт даже для heartbeat. + assertEquals(37.1, snapshot.angle!!, 0.001); assertEquals(403.2, snapshot.values[1]!!, 0.001); assertEquals(63.9, snapshot.values[3]!!, 0.001) // Угол, rpm и процент мощности сохраняют правильные масштабы. + session.display(false, 75, 2); session.display(true, 1, 2) // Яркость и Color также доступны без оборудования. + assertEquals(75, session.snapshot(2).brightness); assertEquals(1, session.snapshot(2).palette) // Проверяется применение в нативной модели, а не только изменение UI. + session.nmt(2, 3); session.setControl("rpm", 80.0); session.cycle(4) // NMT Stop прекращает обработку новых PDO. + assertEquals(403.2, session.snapshot(4).values[1]!!, 0.001); assertEquals(4, session.snapshot(4).nmt) // Прежнее принятое значение не подменяется новым жёлтым заданием MASTER. + } // Закрытие владельца прекращает таймеры и очередь C. + } // Тест не содержит USB, COM и Android Context. + @Test fun physicalSlaveCannotBecomeMasterOrSendNmt() { // Собственный узел на физической шине должен иметь отдельный ограниченный маршрут. + DeifWorkspace(DeifSettings(node = 13), false).use { session -> // Контроллер возвращает реальные серверные кадры платформенному передатчику. + session.startSlave(true, 0); val boot = session.tick(0).slave.single() // Boot-up должен быть выдан ровно один раз. + assertEquals(0x70DL, boot.canId); assertEquals("00", hex(boot)); assertTrue(DeifXdi.validate(boot, 13)) // Ответ разрешён только от собственного Node-ID. + assertTrue(runCatching { session.cycle(1) }.isFailure); assertTrue(runCatching { session.startMaster(true, 1) }.isFailure) // Кнопка и прямой программный вызов одинаково запрещают конкурирующий MASTER. + assertTrue(runCatching { session.nmt(1, 1) }.isFailure); assertTrue(session.tick(1).slave.isEmpty()) // Локальный NMT не отправляется физическому узлу ни при каком выборе меню. + } // Сервер закрывается до освобождения транспортного подключения приложения. + } // Внешний MASTER управляет жизненным циклом этого SLAVE через обычный RX. + @Test fun settingsAndManualBindingsSurvivePersistence() { // Сохранение должно охватывать профиль, калибровки, выбор объектов и явные привязки. + val selector = DeifXdi.selector(2, 3).joinToString(" ") { "%02X".format(it.toInt() and 255) } // Тест получает каталожный объект без ручной сборки селектора. + val original = DeifSettings(source = 3, xdi = false, automatic = false, pdo = 4, group = 9, powerFull = 2500.0, selected = listOf(true, false, true, true, false), bindings = listOf(DeifBinding(2, selector, 0.25))) // Несовпадающие значения обнаруживают пропущенные поля сериализации. + val restored = DeifSettings.decode(original.encode()); assertEquals(original, restored); restored.validate() // Профиль восстанавливается без автоматического запуска сервера. + restored.model().use { model -> assertEquals(original.bindings.single(), model.binding(2)) } // Ручной масштаб и объект действительно применяются к C-состоянию. + assertTrue(runCatching { restored.copy(xdi = true, pdo = 1).validate() }.isFailure) // C-профиль запрещает занятый SAM RPDO1 для XDi-net. + assertTrue(runCatching { restored.copy(angleFactor = 0.0).validate() }.isFailure) // Нулевой масштаб не должен давать фиктивный угол управления. + } // Проверяется реальное восстановление общего профиля, а не зеркальная копия реализации тестом. + @Test fun periodicMasterHasIndependentHeartbeatAndNoCatchupBurst() { // Пауза GUI не должна создавать лавину просроченных повторов. + DeifWorkspace(DeifSettings(periodMs = 100, heartbeat = true), false).use { session -> // Два периода принадлежат общему контроллеру порта. + session.startMaster(true, 0); assertEquals(7, session.tick(0).master.size) // На старте выдаются шесть рабочих кадров и один Operational heartbeat. + assertTrue(session.tick(20).master.isEmpty()); assertEquals(6, session.tick(100).master.size) // Ранний тик ничего не отправляет, рабочий цикл наступает через 100 миллисекунд. + assertEquals(7, session.tick(2000).master.size); assertTrue(session.tick(2001).master.isEmpty()) // После двухсекундной паузы выдаётся один цикл вместо очереди устаревших повторов. + session.stopMaster(); assertTrue(session.tick(3000).master.isEmpty()) // Остановка прекращает также независимый heartbeat MASTER. + } // Пассивный наблюдатель не принимает исходящие задания за физические измерения. + } // Монотонное время задаётся явно, без задержек и нестабильных тестовых таймеров. + @Test fun addressChangesPreserveObjectsAndIndependentSources() { // Перенос профиля должен менять только связанный адрес, сохраняя пользовательские объекты и масштабы. + fun selector(field: Int, node: Int, dam: Boolean = false) = DeifXdi.selector(field, node, 2, dam).joinToString(" ") { "%02X".format(it.toInt() and 255) } // Эталонные селекторы создаёт общий каталог с явно выбранным экземпляром 2. + val profile = DeifSettings(node = 13, source = 1, bindings = listOf(DeifBinding(0, selector(0, 1), 0.5), DeifBinding(1, selector(1, 13, true), -0.1), DeifBinding(2, selector(2, 7), 0.25), DeifBinding(3, "", 0.1))) // Включены SAM, собственный DAM, независимый источник и отключённое поле. + val moved = profile.copy(node = 14, source = 3).readdressed(13, 1) // Новый профиль переносит только адреса прежнего собственного узла и выбранного SAM-источника. + assertEquals(selector(0, 3), moved.bindings[0].selector); assertEquals(selector(1, 14, true), moved.bindings[1].selector) // SAM и DAM следуют разным пользовательским адресам. + assertEquals(profile.bindings[2], moved.bindings[2]); assertEquals(profile.bindings[3], moved.bindings[3]) // Независимый источник и явное отключение не меняются. + assertEquals(0.5, moved.bindings[0].scale, 0.0); assertEquals(-0.1, moved.bindings[1].scale, 0.0) // Перенос адреса не сбрасывает индивидуальную калибровку либо инверсию. + assertTrue(DeifXdi.selectorInfo(moved.bindings[1].selector)!!.dam); assertEquals(14, DeifXdi.selectorInfo(moved.bindings[1].selector)!!.node) // Семантический разбор режима и узла выполняется тем же C API. + } // Отдельная привязка азимута продолжает управлять приоритетом факта и set-point в C. + @Test fun invalidNativeCommandsAndProfileShapesFailExplicitly() { // Ошибочные параметры JNI должны давать явный отказ без усечения и Kotlin fallback. + assertTrue(runCatching { DeifXdi.master(1, intArrayOf(0), 0x201, false) }.isFailure) // Неполный цикл не превращается в частичную отправку пяти объектов. + assertTrue(runCatching { DeifXdi.master(1, IntArray(5), 0x100000201L, false) }.isFailure) // Идентификатор не должен молча усекаться до допустимого STD CAN ID. + assertTrue(runCatching { DeifXdi.make(6, 1, 1, 101, 0x201, false) }.isFailure); assertTrue(runCatching { DeifXdi.make(7, 1, 1, 3, 0x201, false) }.isFailure) // Диапазон яркости и палитры проверяет существующий C-builder. + assertTrue(runCatching { DeifXdi.readdress("01 81 30 02", 128) }.isFailure); assertTrue(runCatching { DeifXdi.selectorInfo("01 81") }.isFailure) // Неверный Node-ID и короткий селектор не проходят границу JNI. + assertTrue(runCatching { DeifSettings.decode("selected=true,false") }.isFailure) // Повреждённый сохранённый профиль не должен давать выход за границы списка в Compose. + DeifSettings().model().use { model -> assertTrue(runCatching { model.bind(DeifBinding(1, "01 81 30 02", Double.NaN)) }.isFailure) } // Неконечный масштаб не попадает в показания нативной модели. + } // Ошибки проверяются через публичные методы того же порта, которым пользуется Android GUI. +} // Этот же набор тестов подключается к sourceSets Android из templates. diff --git a/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/deif/DeifXdiTest.kt b/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/deif/DeifXdiTest.kt new file mode 100644 index 0000000..c43038d --- /dev/null +++ b/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/deif/DeifXdiTest.kt @@ -0,0 +1,34 @@ +package ru.setcorp.setprotocol.deif // JVM-тест использует тот же пакет и JNI-порт, что Android GUI. +import org.junit.Assert.* // Сверяются значения, тип индикации и точные служебные байты. +import org.junit.Test // Обычный локальный JUnit запускает нативную host-библиотеку. +class DeifXdiTest { // В тесте отсутствует Kotlin-копия протокола. + private fun bytes(hex: String) = hex.chunked(2).map { it.toInt(16).toByte() }.toByteArray() // Конвертируется только текст тестовой fixture. + @Test fun sameVectorsAsCAndPython() { // Общий TSV фиксирует межъязыковую совместимость кодека. + val lines = javaClass.getResourceAsStream("/deif-xdi-v1.tsv")!!.bufferedReader().use { it.readLines() } // Fixture поставляется тем же submodule templates. + lines.filter { it.isNotBlank() && !it.startsWith("#") }.forEach { line -> // Комментарии не являются тестовыми пакетами. + val row = line.trim().split(Regex("\\s+")) // Столбцы описывают ожидаемый результат независимо от реализации C. + val flags = row[2].toInt() // Метаданные теста задают STD/EXT/RTR. + val result = DeifXdi.inspect(row[0].toLong(16), bytes(row[1]), flags and 1 != 0, flags and 2 != 0) // JNI вызывает единственный C-декодер. + assertEquals(line, row[3].toInt(), result[0]); assertEquals(line, row[4].toInt(), result[5]) // Сверяем тип принятия и знаковый RAW. + assertEquals(line, row[5].toInt(16), result[3]); assertEquals(line, row[6].toInt(16), result[4]) // Индекс и подиндекс не декодируются повторно в Kotlin. + } // Каждый ошибочный формат проверяется тем же контрактом. + } // Тест не зависит от Android Runtime. + @Test fun passiveNinetyDegreesDoesNotRequireSimulation() { // Воспроизводит выключенный флаг симуляции на снимке пользователя. + DeifXdi().use { model -> // Пассивный наблюдатель не создаёт heartbeat. + assertTrue(model.accept(0x201, bytes("0101300784030000"), nowMs = 10000)) // MASTER Node 1 передаёт сетевое задание RAW 900. + assertEquals(90.0, model.snapshot(10000).angle!!, 0.0); assertTrue(model.snapshot(10000).angleIsSetpoint) // 90° видны с честной пометкой задания. + assertTrue(model.poll(10000).isEmpty()) // Показание не требует физической отправки или включённого SLAVE-сервера. + assertTrue(model.accept(0x201, bytes("01013002E5010000"), nowMs = 10100)) // Отдельное фактическое сообщение передаёт 48,5°. + assertEquals(48.5, model.snapshot(10100).angle!!, 0.0); assertFalse(model.snapshot(10100).angleIsSetpoint) // Угол и тип отображения совпадают с C- и Python-тестами. + } // Close освобождает протокольный сеанс, память direct buffer управляется JVM. + } // Черновика MASTER в API общего ядра вообще нет. + @Test fun slaveOnlySendsHeartbeatForNormalMpdo() { // Обычный приём рассылки не должен создавать ответный PDO. + DeifXdi(node = 13, services = true).use { model -> // Сервисный режим использует адрес Node 13. + model.start(0); val boot = model.poll(0).single() // Boot-up должен быть выдан ровно один раз. + assertEquals(0x70DL, boot.canId); assertArrayEquals(byteArrayOf(0), boot.data) // COB-ID и DLC совпадают с физическим DEIF-профилем. + assertArrayEquals(byteArrayOf(5), model.poll(1000).single().data) // Self-start завершается через 1000 мс. + assertTrue(model.accept(0x201, bytes("0101300784030000"), nowMs = 1000)) // Измерение принимается через общий C-автомат. + assertTrue(model.poll(1000).isEmpty()); assertEquals(90.0, model.snapshot(1000).angle!!, 0.0) // Есть обновлённое показание, но отсутствует выдуманный ACK-PDO. + } // Нативная очередь останавливается при закрытии владельца. + } // Все события проверены на точных монотонных сроках. +} // Этот же класс теста подключается к Android sourceSets из templates. diff --git a/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/trends/GuiGasWatch2Test.kt b/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/trends/GuiGasWatch2Test.kt new file mode 100644 index 0000000..630bc14 --- /dev/null +++ b/c/set-protocol/ports/android/tests/ru/setcorp/setprotocol/trends/GuiGasWatch2Test.kt @@ -0,0 +1,122 @@ +package ru.setcorp.setprotocol.trends // Размещает проверки Android-фасада рядом с тестами существующих трендов и GAS_WATCH. + +import org.junit.Assert.* // Подключает стандартные утверждения JUnit для проверки состояния, значений и эталонных байтов. +import org.junit.Test // Помечает независимые сценарии, запускаемые на JVM с настоящей JNI-библиотекой. +import ru.setcorp.setprotocol.NativeSetProtocol // Позволяет отдельно проверить защиту числовых преобразований непосредственно на JNI-границе. + +class GuiGasWatch2Test { // Проверяет общий C-кодек через Kotlin/JNI и переходы ожидающей и активной подписок без второго кодека. + private val config = GuiGasWatch2.Config(0x12345678L, 100, listOf(0, 1, 0xFF01)) // Повторяет конфигурацию общего fixture gas-watch-v2.json: три GAS-слова и период 100 миллисекунд. + private val request = hex("0200640078563412030000000000010001ff") // Содержит эталонный payload конфигурации из общего C/Python/Kotlin fixture, включая полный список адресов. + private val payload = hex("0200030078563412fffffffff0ffffff037b00feff0000") // Содержит эталонный снимок: sequence u32 maximum, время 0xFFFFFFF0 мс, два валидных слова и один невалидный канал. + + private fun hex(text: String): ByteArray = text.chunked(2).map { it.toInt(16).toByte() }.toByteArray() // Переводит текст эталонных байтов в массив без знания полей или порядка байтов самого протокола. + private fun fails(action: () -> Unit) = assertTrue(runCatching(action).isFailure) // Проверяет отказ операции независимо от текста локализованной ошибки и не подменяет JNI-результат. + + @Test fun requestAndAckMatchSharedFixture() { // Фиксирует одинаковый wire-контракт Android-порта и общего C fixture. + assertArrayEquals(request, GuiGasWatch2.request(config)) // Сравнивает C-сформированный запрос побайтно с независимым эталоном. + GuiGasWatch2.validateAck(request, config) // Принимает точное полное эхо конфигурации в качестве ACK. + assertEquals(0x14, GuiGasWatch2.SET) // Фиксирует новый идентификатор установки, не затрагивая legacy GAS_WATCH_SET 0x12. + assertEquals(0x15, GuiGasWatch2.DATA) // Фиксирует новый идентификатор данных, не затрагивая legacy GAS_WATCH_DATA 0x13. + } // Завершает проверку эталонного запроса и допустимого подтверждения. + + @Test fun copiedAddressesCannotChangeOutstandingConfiguration() { // Проверяет, что изменение исходного UI-списка не меняет смысл уже сформированного запроса. + val source = mutableListOf(0, 1, 0xFF01) // Создаёт изменяемый список как типичный результат выбора строк таблицы. + val copied = GuiGasWatch2.Config(config.configId, config.periodMs, source) // Сохраняет конфигурацию с защитным копированием списка адресов. + source[0] = 25 // Моделирует последующее редактирование UI после постановки запроса. + assertEquals(config, copied) // Подтверждает неизменность полной конфигурации несмотря на изменение внешнего списка. + assertArrayEquals(request, GuiGasWatch2.request(copied)) // Подтверждает, что C по-прежнему получает исходные адреса fixture. + fails { (copied.addresses as MutableList)[0] = 25 } // Проверяет защиту от обхода read-only List приведением типа во время исполнения JVM. + } // Завершает проверку неизменяемости конфигурации, используемой для сопоставления ACK и данных. + + @Test fun requestRejectsInvalidGeometryWithoutTruncation() { // Проверяет диапазоны JNI и протокольные ограничения через единый C builder. + fails { GuiGasWatch2.Config(0L, 100, listOf(1)) } // Нулевой идентификатор запрещён, чтобы не смешивать неинициализированное состояние с конфигурацией. + fails { GuiGasWatch2.Config(0x100000000L, 100, listOf(1)) } // Значение за пределами u32 не должно усекаться до другого идентификатора. + fails { GuiGasWatch2.Config(1L, -1, listOf(1)) } // Отрицательный период не должен превращаться в большой unsigned u16. + fails { GuiGasWatch2.Config(1L, 100, listOf(0x10000)) } // Адрес за пределами u16 не должен превращаться в адрес ноль. + fails { GuiGasWatch2.request(GuiGasWatch2.Config(1L, 100, listOf(1, 1))) } // Проверяет отказ C от дублирующихся адресов, даже если список помещается в лимит. + fails { GuiGasWatch2.request(GuiGasWatch2.Config(1L, 100, (0..64).toList())) } // Проверяет отказ C от 65 слов при максимуме 64 слова на подписку. + fails { GuiGasWatch2.request(GuiGasWatch2.Config(1L, 0, listOf(1))) } // Остановка с непустым списком должна отклоняться вместо неоднозначного поведения прибора. + fails { GuiGasWatch2.request(GuiGasWatch2.Config(1L, 100, emptyList())) } // Пустая подписка с ненулевым периодом также нарушает общий контракт. + val maximum = GuiGasWatch2.Config(0xFFFFFFFFL, 0xFFFF, (0..63).toList()) // Покрывает допустимые максимальные u32 идентификатор, u16 период и 64 адреса без переполнения JNI. + GuiGasWatch2.validateAck(GuiGasWatch2.request(maximum), maximum) // Проверяет, что предельная допустимая конфигурация проходит C builder и exact ACK. + assertNull(NativeSetProtocol.nativeGasWatchRequest(-1L, 100, intArrayOf(1))) // Проверяет защиту JNI от отрицательного Long даже при обходе Kotlin Config. + assertNull(NativeSetProtocol.nativeGasWatchRequest(0x100000000L, 100, intArrayOf(1))) // Проверяет защиту JNI от усечения старших битов идентификатора. + assertNull(NativeSetProtocol.nativeGasWatchRequest(1L, 0x10000, intArrayOf(1))) // Проверяет защиту JNI от усечения периода при прямом вызове native-метода. + assertNull(NativeSetProtocol.nativeGasWatchRequest(1L, 100, intArrayOf(-1))) // Проверяет защиту JNI от преобразования отрицательного адреса в 0xFFFF. + } // Завершает проверки границ и протокольной геометрии без воспроизведения C-алгоритма. + + @Test fun ackRequiresIdentifierPeriodAndOrderedAddresses() { // Проверяет защиту от ACK чужой подписки с тем же количеством слов. + fails { GuiGasWatch2.validateAck(request, GuiGasWatch2.Config(0x12345679L, 100, config.addresses)) } // Другой идентификатор конфигурации не должен подтверждать ожидаемый запрос. + fails { GuiGasWatch2.validateAck(request, GuiGasWatch2.Config(config.configId, 101, config.addresses)) } // Совпадающие адреса не компенсируют расхождение периода в миллисекундах. + fails { GuiGasWatch2.validateAck(request, GuiGasWatch2.Config(config.configId, 100, listOf(1, 0, 0xFF01))) } // Перестановка адресов при том же количестве должна отклоняться, иначе значения будут подписаны чужими именами. + fails { GuiGasWatch2.validateAck(request.copyOf(request.size - 1), config) } // Усечённое эхо не должно применяться частично. + fails { GuiGasWatch2.validateAck(request + byteArrayOf(0), config) } // Лишний байт должен отклоняться как нарушение точной длины ACK. + } // Завершает проверку полного, а не сокращённого подтверждения. + + @Test fun decodePreservesUnsignedCountersAndInvalidValues() { // Проверяет преобразование C-результата в удобную для графика неизменяемую модель Kotlin. + val sample = GuiGasWatch2.decode(payload, config) // Декодирует реальный fixture через JNI и общее C-ядро. + assertEquals(config.configId, sample.configId) // Сохраняет идентификатор, по которому C проверил принадлежность снимка активной конфигурации. + assertEquals(0xFFFFFFFFL, sample.sequence) // Значение u32 maximum должно остаться положительным Long, а не −1 после знакового Int. + assertEquals(0xFFFFFFF0L, sample.timestampMs) // Приборное время с установленным старшим битом также должно остаться положительным. + assertEquals(listOf(123, 65534, null), sample.values) // Сырые u16 слова сохраняются без потери знака, а невалидный третий канал явно представлен null. + fails { (sample.values as MutableList)[0] = 5 } // Не позволяет потребителю переписать уже переданный другим обработчикам снимок. + } // Завершает проверку JNI-представления счётчиков, слов и валидности. + + @Test fun decodeRejectsStaleAndMalformedPackets() { // Проверяет, что JNI действительно передаёт все проверки формата и конфигурации общему C-декодеру. + fails { GuiGasWatch2.decode(payload, GuiGasWatch2.Config(config.configId + 1L, 100, config.addresses)) } // Старый пакет с прежним id нельзя принять в новую подписку того же размера. + fails { GuiGasWatch2.decode(payload, GuiGasWatch2.Config(config.configId, 100, listOf(0, 1))) } // Совпадающий id не разрешает принять иное количество значений. + fails { GuiGasWatch2.decode(payload.copyOf(payload.size - 1), config) } // Усечённое последнее слово не должно давать частичный снимок. + fails { GuiGasWatch2.decode(payload + byteArrayOf(0), config) } // Лишний байт не должен молча игнорироваться после допустимого пакета. + val dirtyInvalid = payload.copyOf().also { it[it.lastIndex] = 1 } // Нарушает fixture: у невалидного третьего канала wire-значение обязано оставаться нулём. + fails { GuiGasWatch2.decode(dirtyInvalid, config) } // Проверяет C-отказ от неканонического невалидного слова, чтобы не скрывать повреждение payload. + val dirtyPadding = payload.copyOf().also { it[16] = 0x83.toByte() } // Устанавливает bit7 единственного байта bitmap fixture при трёх каналах; этот padding-бит не относится ни к одному слову. + fails { GuiGasWatch2.decode(dirtyPadding, config) } // Проверяет C-отказ от ненулевых неиспользуемых битов валидности. + val wrongVersion = payload.copyOf().also { it[0] = 1 } // Меняет эталонную версию 2 на legacy-значение 1, не меняя остальные байты. + fails { GuiGasWatch2.decode(wrongVersion, config) } // Не позволяет принять другой контракт только из-за совпадения длины пакета. + assertNull(NativeSetProtocol.nativeGasWatchDecode(payload, config.configId, -1)) // Прямой JNI-вызов не должен превращать отрицательный count в большое size_t. + assertNull(NativeSetProtocol.nativeGasWatchDecode(payload, config.configId, 65)) // JNI ограничивает размеры своих стековых массивов до обращения к C-декодеру. + } // Завершает проверку чужих конфигураций, повреждения длины и канонического bitmap. + + @Test fun pendingChangePreservesActiveUntilExactAck() { // Моделирует смену адресов во время продолжающегося потока старой подписки. + val session = GuiGasWatch2.Session() // Создаёт состояние отдельного подключения без заранее активной конфигурации. + fails { session.sample(payload) } // До первого ACK клиент обязан отклонять данные, даже если их формат корректен. + assertArrayEquals(request, session.request(config)) // Ставит первый успешно построенный запрос в pending. + assertNull(session.active) // Один отправленный запрос ещё не означает, что прибор применил подписку. + assertEquals(config, session.pending) // Ожидающая конфигурация точно соответствует выданным байтам запроса. + session.validateAck(request, config) // Активирует первую подписку только после полного ACK. + val next = GuiGasWatch2.Config(config.configId + 1L, 100, listOf(2, 3, 0xFF01)) // Создаёт другую конфигурацию той же ширины для обнаружения ошибки позиционного сопоставления. + val nextRequest = session.request(next) // Ставит новую конфигурацию в pending, не заменяя подтверждённый список. + assertEquals(config, session.active) // До нового ACK продолжает действовать предыдущая подписка. + assertEquals(123, session.sample(payload).values[0]) // Старый корректный пакет продолжает декодироваться по старым адресам во время ожидания. + fails { session.validateAck(request, config) } // Запоздалый ACK первой конфигурации не может подтвердить последний запрос. + fails { session.validateAck(request, next) } // Подстановка ожидаемого объекта не позволяет выдать чужое полное эхо за новый ACK. + assertEquals(config, session.active) // Ошибочные подтверждения не должны сбросить действующую подписку. + assertEquals(next, session.pending) // Ошибочные подтверждения также не должны потерять последний ожидающий запрос. + session.validateAck(nextRequest, next) // Только точное эхо нового запроса переключает активную конфигурацию. + assertEquals(next, session.active) // Подтверждает переход к новому списку адресов. + assertNull(session.pending) // Успешное подтверждение завершает ожидающий запрос. + fails { session.sample(payload) } // Старый пакет того же размера после переключения должен отклоняться по id в C. + fails { session.validateAck(nextRequest, next) } // Повтор уже завершённого ACK не считается новым подтверждением. + } // Завершает проверку согласованного переключения и защиты от запоздалых пакетов. + + @Test fun failedRequestReusedIdStopAndResetKeepStateConsistent() { // Проверяет отказ запросов, идемпотентный повтор, остановку и границу переподключения. + val session = GuiGasWatch2.Session() // Создаёт независимое состояние для сценария ошибок и завершения подписки. + session.request(config) // Готовит первый запрос, который далее будет подтверждён настоящим C-валидатором. + session.validateAck(request, config) // Устанавливает известную действующую конфигурацию. + session.request(config) // Разрешает идентичный повтор запроса с тем же id как идемпотентную операцию. + fails { session.request(GuiGasWatch2.Config(config.configId, 101, config.addresses)) } // Запрещает переиспользовать active или pending id с другим периодом. + fails { session.request(GuiGasWatch2.Config(config.configId + 1L, 100, listOf(1, 1))) } // Ошибка C builder не должна заменить ожидающую конфигурацию некорректным списком. + assertEquals(config, session.active) // После обеих ошибок сохраняется подтверждённая подписка. + assertEquals(config, session.pending) // После обеих ошибок сохраняется последний успешно построенный запрос. + session.validateAck(request, config) // Завершает идемпотентный повтор до отдельного запроса остановки. + val stop = GuiGasWatch2.Config(config.configId + 1L, 0, emptyList()) // Остановка представляется новой конфигурацией с нулевым периодом и пустым списком согласно C-контракту. + val stopRequest = session.request(stop) // Готовит остановку, пока старая подписка ещё активна до ACK. + assertEquals(123, session.sample(payload).values[0]) // Старый поток остаётся допустимым до фактического подтверждения остановки. + session.validateAck(stopRequest, stop) // Применяет остановку только после полного подтверждения прибора. + fails { session.sample(payload) } // После подтверждённой остановки данные не должны попадать в график. + session.reset() // Моделирует разрыв связи, очищая оба состояния перед следующим подключением. + assertNull(session.active) // Следующее соединение не наследует подтверждённый id предыдущего прибора. + assertNull(session.pending) // Следующее соединение не наследует ожидающий ACK предыдущего прибора. + fails { session.validateAck(stopRequest, stop) } // Запоздалое подтверждение до разрыва не может активировать конфигурацию после reset. + } // Завершает сценарий отказов и границы жизненного цикла подключения. +} // Завершает JVM/JNI-проверки общего GAS_WATCH2 без UI-зависимостей. diff --git a/c/set-protocol/ports/stm32-bxcan/README.md b/c/set-protocol/ports/stm32-bxcan/README.md index 5f1dd42..537bfdf 100644 --- a/c/set-protocol/ports/stm32-bxcan/README.md +++ b/c/set-protocol/ports/stm32-bxcan/README.md @@ -34,7 +34,7 @@ c/set-protocol/ Модуль зависит от файлов `main.h` и `can.h`, сгенерированных STM32CubeMX, а также от HAL-драйверов CAN, RTC и TIM. В сборку добавляются -`c/set-protocol/ports/stm32-bxcan/protocan.c` и `c/set-protocol/src/pcan_id.c`. +`c/set-protocol/ports/stm32-bxcan/protocan.c`, `c/set-protocol/src/pcan_id.c` и `c/set-protocol/src/pcan_gas_slot.c`. В include paths добавляются `c/set-protocol/ports/stm32-bxcan`, `c/set-protocol/include` и каталог CubeMX с `main.h`/`can.h`. Если прошивка уже собирает общее ядро SETProtocol, второй раз добавлять @@ -80,10 +80,9 @@ c/set-protocol/ | `0x1` | дискретное (`DISCRETE`) | | `0x2` | аналоговое (`ANALOG`) | | `0x3` | общее адресное пространство | -| `0x4` | Modbus Coil | -| `0x5` | Modbus Discrete | -| `0x6` | Modbus Holding | -| `0x7` | Modbus Input | +| `0x4` | GAS SLOT: Word0-маска и три значения | +| `0x5` | Modbus: функции 1…4, количество 1…4 | +| `0x6…0x7` | Резерв | | `0x8` | ошибка | | `0x9` | управление загрузчиком (`BOOT_CONTROL`, зарезервировано) | | `0xA` | данные прошивки, слот A (`BOOT_DATA_A`, зарезервировано) | @@ -98,7 +97,7 @@ c/set-protocol/ - broadcast: младшие 4 бита — дополнительное поле, старшие 12 бит — команда; - discrete: младшие 12 бит — данные/адрес, старшие 4 бита — подтип; - analog: младшие 12 бит — ID датчика, старшие 4 бита — тип величины; -- Modbus: младшие 4 бита — количество регистров, старшие 12 бит — начальный адрес; +- Modbus: адрес `[15:4]`, функция минус один `[3:2]`, количество минус один `[1:0]`; функция и количество 1…4; - SETTINGS: старший байт — номер сборки `Z`, младший байт — позиция `Y`; - error: младший байт — код ошибки, старший байт — дополнительная информация. @@ -264,7 +263,7 @@ PROTOCAN_StatusTypeDef ProtoCanMsgToAnalogTSens(struct RXMsg msg) - `ProtoCanMsgToAnalog...()` — универсальные данные, настройки, U/I/T; - `ProtoCanMsgToSettings()` — GET/WRITE/CLEAR привязки ROM к локации; - `ProtoCanMsgToGeneralAddressSpace()`; -- `ProtoCanMsgToModbus...()`; +- `ProtoCanMsgToModbus()`; - `PROTOCAN_RequestError()`. Стандартные слабые обработчики в основном являются демонстрационными: часть возвращает `PROTOCAN_OK` без действий, часть отправляет текстовые ответы вроде `TS0001` или `GAS-0001`. Для рабочего изделия их обычно нужно переопределить. @@ -373,7 +372,7 @@ tx.ErrorData.Info = 0x34; (void)PROTOCAN_SEND(id, tx); ``` -Для `BROADCAST`, `DISCRETE` и `ANALOG` используется `tx.CoreData`; для Modbus-типов — `tx.ModbusData`, для `SETTINGS` — `tx.SettingsData`. Для успешных ответов и ошибок SETTINGS удобнее использовать готовые функции `PROTOCAN_SEND_SETTINGS_RESPONSE()` и `PROTOCAN_SEND_SETTINGS_ERROR()`. Если количество передаваемых элементов больше нуля, соответствующий указатель `Data` должен быть валиден до завершения вызова. +Для `BROADCAST`, `DISCRETE` и `ANALOG` используется `tx.CoreData`; для единого Modbus — `tx.ModbusData` с полями `Function` и `RegCount` 1…4, для `SETTINGS` — `tx.SettingsData`. Для успешных ответов и ошибок SETTINGS удобнее использовать готовые функции `PROTOCAN_SEND_SETTINGS_RESPONSE()` и `PROTOCAN_SEND_SETTINGS_ERROR()`. Если количество передаваемых элементов больше нуля, соответствующий указатель `Data` должен быть валиден до завершения вызова. ## Пульс устройства @@ -600,3 +599,9 @@ CRC32 обнаруживает случайное повреждение, но 7. При необходимости подключить HAL-callback’и вручную. 8. Переопределить нужные `__weak`-обработчики. 9. Вызывать `PROTOCAN_ProcessAllRxMsgs()` в основном цикле. + +## GAS: регистры 0x3 и слоты 0x4 + +[Адресация GAS](../../docs/GAS_SLOT.md): `0x3` — отдельные 16-битные регистры `0…65535`, запись 1…4 слов. `0x4` — слот с Word0-маской и тремя значениями; PERIPH сохраняет 200 слов в 67 слотах `0xMM00…0xMM42`. Формат определяется MsgType, без настройки профиля. + +`PROTOCAN_GAS_SLOT_BIND(&port)` подключает provider типа 0x4 до обработки очереди. `ProtoCanMsgToGasSlot()` вызывает общий адресный обработчик, `PROTOCAN_SEND_GAS_SLOT()` кодирует Word0-маску и три значения. Неподключённый provider возвращает ошибку. Единый Modbus использует MsgType 0x5; коды 0x6/0x7 свободны. `ProtoCanMsgToModbus()` заменяет три прежних weak-обработчика; функция и количество извлекаются через `pcan_modbus_function()` и `pcan_modbus_count()`. `PROTOCAN_SEND_MODBUS()` отправляет одно окно 1…4; `Data=NULL` означает запрос чтения, битовые банки используют маску в `Data[0]`. Неподключённая карта отвечает штатной ошибкой, без демонстрационных ASCII-значений. diff --git a/c/set-protocol/ports/stm32-bxcan/protocan.c b/c/set-protocol/ports/stm32-bxcan/protocan.c index eef7c68..3f67d63 100644 --- a/c/set-protocol/ports/stm32-bxcan/protocan.c +++ b/c/set-protocol/ports/stm32-bxcan/protocan.c @@ -170,14 +170,15 @@ void PROTOCAN_LoopProcessRxMsgs(void) { ProtoCanMsgToGeneralAddressSpace(rxMsg[CurrentStep]); } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_GAS_SLOT) /* Независимый тип 0x4 не должен попадать в обработчик Modbus. */ + { /* Передаём маску и значения общему слотному кодеку из основного цикла. */ + ProtoCanMsgToGasSlot(rxMsg[CurrentStep]); /* ISR только ставит кадр в очередь; provider вызывается здесь. */ + } /* Завершаем обработку слотного сообщения. */ else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_SETTINGS) { PROTOCAN_SettingsProcessing(rxMsg[CurrentStep]); } - else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_COIL || - rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_DISCRETE || - rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_HOLDING || - rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_INPUT) + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS) /* Единый MsgType 0x5 передаёт функцию 1…4 в Body; 0x6/0x7 больше не относятся к Modbus. */ { PROTOCAN_ModbusProcessing(rxMsg[CurrentStep]); } @@ -226,14 +227,15 @@ PROTOCAN_StatusTypeDef PROTOCAN_ProcessAllRxMsgs(void) { result = ProtoCanMsgToGeneralAddressSpace(rxMsg[CurrentStep]); } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_GAS_SLOT) /* Независимый тип 0x4 не должен попадать в обработчик Modbus. */ + { /* Передаём маску и значения общему слотному кодеку из основного цикла. */ + result = ProtoCanMsgToGasSlot(rxMsg[CurrentStep]); /* ISR только ставит кадр в очередь; provider вызывается здесь. */ + } /* Завершаем обработку слотного сообщения. */ else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_SETTINGS) { result = PROTOCAN_SettingsProcessing(rxMsg[CurrentStep]); } - else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_COIL || - rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_DISCRETE || - rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_HOLDING || - rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_INPUT) + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS) /* Единый MsgType 0x5 передаёт функцию 1…4 в Body; 0x6/0x7 больше не относятся к Modbus. */ { result = PROTOCAN_ModbusProcessing(rxMsg[CurrentStep]); } @@ -283,14 +285,15 @@ PROTOCAN_StatusTypeDef PROTOCAN_ProcessSingleRxMsg(void) { result = ProtoCanMsgToGeneralAddressSpace(rxMsg[CurrentStep]); } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_GAS_SLOT) /* Независимый тип 0x4 не должен попадать в обработчик Modbus. */ + { /* Передаём маску и значения общему слотному кодеку из основного цикла. */ + result = ProtoCanMsgToGasSlot(rxMsg[CurrentStep]); /* ISR только ставит кадр в очередь; provider вызывается здесь. */ + } /* Завершаем обработку слотного сообщения. */ else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_SETTINGS) { result = PROTOCAN_SettingsProcessing(rxMsg[CurrentStep]); } - else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_COIL || - rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_DISCRETE || - rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_HOLDING || - rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_INPUT) + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS) /* Единый MsgType 0x5 передаёт функцию 1…4 в Body; 0x6/0x7 больше не относятся к Modbus. */ { result = PROTOCAN_ModbusProcessing(rxMsg[CurrentStep]); } @@ -1112,258 +1115,78 @@ PROTOCAN_StatusTypeDef PROTOCAN_SEND_GENERAL_ADDRESS_SPACE(ProtoCanId_t id, uint return (PROTOCAN_StatusTypeDef)HAL_OK; } -/** -* @brief Обработка запроса на основе типа Modbus. -* В зависимости от типа сообщения, вызывает соответствующую функцию -* для отправки Modbus-запроса по CAN-шине. -* @param _rxMsg Структура входящего сообщения RXMsg. -* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка). -*/ -PROTOCAN_StatusTypeDef PROTOCAN_ModbusProcessing(struct RXMsg _rxMsg) -{ - switch(_rxMsg.eID.Fields.MsgType) - { - case PROTOCAN_MSGTYPE_MODBUS_COIL: - { - return ProtoCanMsgToModbusCoil(_rxMsg); - break; - } - case PROTOCAN_MSGTYPE_MODBUS_DISCRETE: - { - return ProtoCanMsgToModbusDiscrete(_rxMsg); - break; - } - case PROTOCAN_MSGTYPE_MODBUS_HOLDING: - { - return ProtoCanMsgToModbusHolding(_rxMsg); - break; - } - case PROTOCAN_MSGTYPE_MODBUS_INPUT: - { - return ProtoCanMsgToModbusInput(_rxMsg); - break; - } - default: - //ERROR - return PROTOCAN_ERROR; - break; - } - return PROTOCAN_ERROR; -} +PROTOCAN_StatusTypeDef PROTOCAN_ModbusProcessing(struct RXMsg message) /* Проверяем общий контракт перед передачей единому обработчику приложения. */ +{ /* Битовая функция и количество извлекаются переносимыми помощниками, без зависимости от C bitfields. */ + unsigned count = pcan_modbus_count((uint16_t)message.eID.Fields.MsgBody); /* Wire-код 0…3 преобразуется в физическое количество 1…4. */ + unsigned function = pcan_modbus_function((uint16_t)message.eID.Fields.MsgBody); /* Функции 1/2 выбирают биты, 3/4 — 16-битные регистры. */ + unsigned expected = function <= 2U ? 1U : count * 2U; /* Битовому банку нужен один октет, регистровому — два октета на слово. */ + if (message.eID.Fields.MsgType != PROTOCAN_MSGTYPE_MODBUS || !message.info.EXT || message.info.RTR || (message.eID.Fields.MsgBody >> 4U) + count > 0x1000U) return PROTOCAN_ERROR; /* Отвергаем чужой формат и выход окна за 12-битное адресное пространство. */ + if (message.DLC != 0U && message.DLC != expected) return PROTOCAN_ERROR; /* Непустой payload должен точно соответствовать функции и количеству. */ + if (message.DLC != 0U && function <= 2U && (message.Data[0] >> count) != 0U) return PROTOCAN_ERROR; /* За пределами запрошенных 1…4 битов нет значащих данных. */ + return ProtoCanMsgToModbus(message); /* Приложение получает единый тип сообщения и само выбирает карту по функции. */ +} /* Конец проверки и диспетчеризации единого Modbus. */ -/** -* @brief __weak Функция отправки ответа на запрос Coil Modbus по CAN. -* Формирует CAN ответ на запрос Coil Modbus и отправляет его. -* @param _rxMsg Структура входящего сообщения RXMsg. -* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка). -*/ -__weak PROTOCAN_StatusTypeDef ProtoCanMsgToModbusCoil(struct RXMsg _rxMsg) -{ - CAN_TxHeaderTypeDef TxHeader; - uint32_t TxMailBox = 0; - uint8_t data[8]; - TxHeader.IDE = CAN_ID_EXT; - TxHeader.TransmitGlobalTime = DISABLE; - TxHeader.RTR = CAN_RTR_DATA; - ProtoCanId_t tmp_eID; - tmp_eID.BitAll = _rxMsg.eID.BitAll; - tmp_eID.Fields.Route = PROTOCAN_ROUTE_FROM_DEVICE; - TxHeader.ExtId = PROTOCAN_IdPack(&tmp_eID); - TxHeader.DLC = 8; - msgBodyModbusType msg; - msg.Body = _rxMsg.eID.Fields.MsgBody; - data[0] = 'M'; - data[1] = 'C'; - data[2] = ' '; - data[3] = 'S'; - data[4] = msg.Fields.StrAdr; - data[5] = ' '; - data[6] = 'C'; - data[7] = msg.Fields.RegCount; - return (PROTOCAN_StatusTypeDef)HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox); -} +static const pcan_gas_slot_port_t *gas_slot_port; /* Provider принадлежит приложению; NULL означает, что слотный сервис ещё не подключён. */ +void PROTOCAN_GAS_SLOT_BIND(const pcan_gas_slot_port_t *port) /* Вызывать при инициализации до обработки очереди CAN. */ +{ /* Срок жизни структуры provider должен покрывать всё время работы порта. */ + gas_slot_port = port; /* NULL явно отключает сервис без подстановки фиктивных данных. */ +} /* Конец подключения аппаратно-независимого provider. */ +PROTOCAN_StatusTypeDef PROTOCAN_SEND_GAS_SLOT(ProtoCanId_t id, uint16_t address, const uint16_t *words, unsigned count) /* Отправляем маску и три значения единственным C-кодеком. */ +{ /* Нулевой count обозначает чтение, четыре wire-слова — масочную запись или ответ. */ + CAN_TxHeaderTypeDef header = {0}; uint32_t mailbox = 0U; uint_least8_t bytes[8]; uint16_t checked[4]; uint8_t data[8] = {0}; int length; unsigned i; /* HAL получает восемь октетов независимо от внутреннего представления общего ядра. */ + id.Fields.MsgType = PROTOCAN_MSGTYPE_GAS_SLOT; id.Fields.MsgBody = address; /* Тип 0x4 и полный 16-битный адрес слота задаются отдельно от карты регистров 0x3. */ + length = pcan_gas_slot_encode(words, count, bytes); /* Проверяем маску Word0 до формирования отправляемого HAL-заголовка. */ + if (_HCAN == NULL || length < 0 || pcan_gas_slot_decode_words(PROTOCAN_IdPack(&id), PCAN_GAS_SLOT_FLAG_IDE, bytes, (unsigned)length, checked) < 0) return PROTOCAN_ERROR; /* Не отправляем неверную маску, пустой ответ или кадр без подготовленного CAN. */ + for (i = 0U; i < (unsigned)length; ++i) data[i] = (uint8_t)bytes[i]; /* Переносим уже закодированные октеты без повторного endian-алгоритма. */ + header.IDE = CAN_ID_EXT; header.ExtId = PROTOCAN_IdPack(&id); header.RTR = CAN_RTR_DATA; header.DLC = (uint32_t)length; header.TransmitGlobalTime = DISABLE; /* Используем extended data frame с DLC ровно 0 либо 8. */ + return (PROTOCAN_StatusTypeDef)HAL_CAN_AddTxMessage(_HCAN, &header, data, &mailbox); /* Возвращаем фактический результат постановки кадра в аппаратный TX mailbox. */ +} /* Конец отправки слота через действующий HAL-порт. */ +__weak PROTOCAN_StatusTypeDef ProtoCanMsgToGasSlot(struct RXMsg message) /* При необходимости приложение может переопределить адаптер, сохранив общий wire-контракт. */ +{ /* По умолчанию подключённый provider обрабатывается переносимым C-ядром. */ + pcan_gas_slot_frame_t request = {0}, response; unsigned i; int result; /* Ограничиваем вход одним CAN-кадром и не используем динамическую память. */ + if (gas_slot_port == NULL || message.DLC > 8U) return PROTOCAN_ERROR; /* Не имитируем успешный сервис без реального provider устройства. */ + request.id = PROTOCAN_IdPack(&message.eID); request.dlc = message.DLC; request.flags = (message.info.EXT ? PCAN_GAS_SLOT_FLAG_IDE : 0U) | (message.info.RTR ? PCAN_GAS_SLOT_FLAG_RTR : 0U); /* Сохраняем фактические флаги приёма для проверки общим декодером. */ + for (i = 0U; i < message.DLC; ++i) request.data[i] = message.Data[i]; /* Передаём исходные wire-октеты без извлечения маски в HAL-адаптере. */ + result = pcan_gas_slot_handle_address(CURRENT_TYPE_DEVICE, CURRENT_ID_DEVICE, gas_slot_port, &request, &response); /* Проверяем тип 0x4, адрес своего узла, направление и маску до вызова provider. */ + if (result < 0) return PROTOCAN_ERROR; /* Неверный слот или запрещённая запись не переходят в Modbus или GAS 0x3. */ + if (result == 0) return PROTOCAN_OK; /* Базовый слотный протокол не формирует отдельный ACK записи. */ + message.eID.BitAll = response.id; /* Ответ общего ядра сохраняет адрес узла и меняет Route на FROM_DEVICE. */ + { /* Проверенный ответ переводится в HAL тем же публичным методом отправки. */ + uint16_t words[4]; /* Маска и значения возвращаются общим декодером без второго wire-алгоритма. */ + if (pcan_gas_slot_decode_words(response.id, response.flags, response.data, response.dlc, words) < 0) return PROTOCAN_ERROR; /* Проверяем сформированный ответ перед публикацией в транспорт. */ + return PROTOCAN_SEND_GAS_SLOT(message.eID, (uint16_t)(response.id & 0xFFFFU), words, 4U); /* Отправляем один полный восьмибайтовый слот с маской достоверных значений. */ + } /* Завершаем отправку сформированного ответа. */ +} /* Конец стандартного адаптера слотного GAS. */ -/** -* @brief __weak Функция отправки ответа на запрос Discrete Modbus по CAN. -* Формирует CAN ответ на запрос Discrete Modbus и отправляет его. -* @param _rxMsg Структура входящего сообщения RXMsg. -* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка). -*/ -__weak PROTOCAN_StatusTypeDef ProtoCanMsgToModbusDiscrete(struct RXMsg _rxMsg) -{ - CAN_TxHeaderTypeDef TxHeader; - uint32_t TxMailBox = 0; - uint8_t data[8]; - TxHeader.IDE = CAN_ID_EXT; - TxHeader.TransmitGlobalTime = DISABLE; - TxHeader.RTR = CAN_RTR_DATA; - ProtoCanId_t tmp_eID; - tmp_eID.BitAll = _rxMsg.eID.BitAll; - tmp_eID.Fields.Route = PROTOCAN_ROUTE_FROM_DEVICE; - TxHeader.ExtId = PROTOCAN_IdPack(&tmp_eID); - TxHeader.DLC = 8; - msgBodyModbusType msg; - msg.Body = _rxMsg.eID.Fields.MsgBody; - data[0] = 'M'; - data[1] = 'D'; - data[2] = ' '; - data[3] = 'S'; - data[4] = msg.Fields.StrAdr; - data[5] = ' '; - data[6] = 'C'; - data[7] = msg.Fields.RegCount; - return (PROTOCAN_StatusTypeDef)HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox); -} +__weak PROTOCAN_StatusTypeDef ProtoCanMsgToModbus(struct RXMsg message) /* Приложение переопределяет одну точку для функций 1…4. */ +{ /* Без прикладной карты регистров возвращаем штатную ошибку необработанного запроса. */ + return PROTOCAN_RequestError(message); /* Не публикуем демонстрационные ASCII-байты как реальные значения Modbus. */ +} /* Конец стандартного обработчика неподключённой карты. */ -/** -* @brief __weak Функция отправки ответа на запрос Holding Modbus по CAN. -* Формирует CAN ответ на запрос Holding Modbus и отправляет его. -* @param _rxMsg Структура входящего сообщения RXMsg. -* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка). -*/ -__weak PROTOCAN_StatusTypeDef ProtoCanMsgToModbusHolding(struct RXMsg _rxMsg) -{ - CAN_TxHeaderTypeDef TxHeader; - uint32_t TxMailBox = 0; - uint8_t data[8]; - TxHeader.IDE = CAN_ID_EXT; - TxHeader.TransmitGlobalTime = DISABLE; - TxHeader.RTR = CAN_RTR_DATA; - ProtoCanId_t tmp_eID; - tmp_eID.BitAll = _rxMsg.eID.BitAll; - tmp_eID.Fields.Route = PROTOCAN_ROUTE_FROM_DEVICE; - TxHeader.ExtId = PROTOCAN_IdPack(&tmp_eID); - TxHeader.DLC = 8; - msgBodyModbusType msg; - msg.Body = _rxMsg.eID.Fields.MsgBody; - data[0] = 'M'; - data[1] = 'H'; - data[2] = ' '; - data[3] = 'S'; - data[4] = msg.Fields.StrAdr; - data[5] = ' '; - data[6] = 'C'; - data[7] = msg.Fields.RegCount; - return (PROTOCAN_StatusTypeDef)HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox); -} - -/** -* @brief __weak Функция отправки ответа на запрос Input Modbus по CAN. -* Формирует CAN ответ на запрос Input Modbus и отправляет его. -* @param _rxMsg Структура входящего сообщения RXMsg. -* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка). -*/ -__weak PROTOCAN_StatusTypeDef ProtoCanMsgToModbusInput(struct RXMsg _rxMsg) -{ - CAN_TxHeaderTypeDef TxHeader; - uint32_t TxMailBox = 0; - uint8_t data[8]; - TxHeader.IDE = CAN_ID_EXT; - TxHeader.TransmitGlobalTime = DISABLE; - TxHeader.RTR = CAN_RTR_DATA; - ProtoCanId_t tmp_eID; - tmp_eID.BitAll = _rxMsg.eID.BitAll; - tmp_eID.Fields.Route = PROTOCAN_ROUTE_FROM_DEVICE; - TxHeader.ExtId = PROTOCAN_IdPack(&tmp_eID); - TxHeader.DLC = 8; - msgBodyModbusType msg; - msg.Body = _rxMsg.eID.Fields.MsgBody; - data[0] = 'M'; - data[1] = 'I'; - data[2] = ' '; - data[3] = 'S'; - data[4] = msg.Fields.StrAdr; - data[5] = ' '; - data[6] = 'C'; - data[7] = msg.Fields.RegCount; - return (PROTOCAN_StatusTypeDef)HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox); -} - -/** - * @brief Отправляет данные Modbus через CAN-шину в соответствии с типом сообщения. - * Эта функция формирует и отправляет Modbus-данные по CAN-шине, поддерживая - * различные типы сообщений: Coil, Discrete, Holding Register и Input Register. - * Для сообщений, превышающих 4 регистров, данные отправляются пакетами. - * @param id Идентификатор сообщения, содержащий тип сообщения и другую информацию. - * @param modbusData Структура с данными Modbus: адрес, количество регистров и сами данные. - * @return PROTOCAN_StatusTypeDef Статус операции. - * @details - * В зависимости от типа Modbus (coil/discrete или holding/input), формируется - * соответствующий CAN-пакет. Для coil/discrete отправляется один пакет, для holding/input — - * несколько, по 4 регистра в пакете. В случае ошибок при добавлении сообщения API HAL возвращается ошибка. - */ -PROTOCAN_StatusTypeDef PROTOCAN_SEND_MODBUS(const ProtoCanId_t id, const struct ProtoCanModbusData modbusData) -{ - ProtoCanId_t localId = id; - uint8_t msgType = localId.Fields.MsgType; - // Структура для отправки - CAN_TxHeaderTypeDef TxHeader; - uint32_t TxMailBox = 0; - uint8_t canData[8]; - if(msgType == PROTOCAN_MSGTYPE_MODBUS_COIL || msgType == PROTOCAN_MSGTYPE_MODBUS_DISCRETE) - { - // Формируем body - msgBodyModbusType body; - body.Fields.StrAdr = modbusData.StrAdr; - body.Fields.RegCount = modbusData.RegCount; - // Устанавливаем коллизию ExtId с body.Body - localId.Fields.MsgBody = (body.Body & 0xFFFF); - // Обновляем ExtId - TxHeader.ExtId = PROTOCAN_IdPack(&localId); - // Остальные настройки - TxHeader.IDE = CAN_ID_EXT; - TxHeader.RTR = CAN_RTR_DATA; - TxHeader.TransmitGlobalTime = DISABLE; - TxHeader.DLC = modbusData.RegCount % 8 + 1; - // Формируем CAN данные - canData[0] = LowByteOfWord(modbusData.Data[0]); - canData[1] = HighByteOfWord(modbusData.Data[0]); - if (HAL_CAN_AddTxMessage(_HCAN, &TxHeader, canData, &TxMailBox) != HAL_OK) - { - return PROTOCAN_ERROR; - } - } - else if(msgType == PROTOCAN_MSGTYPE_MODBUS_HOLDING || msgType == PROTOCAN_MSGTYPE_MODBUS_INPUT) - { - uint16_t* dataPtr = modbusData.Data; - unsigned totalRegs = modbusData.RegCount; - unsigned regsProcessed = 0; - unsigned startAddress = modbusData.StrAdr; - while (regsProcessed < totalRegs) - { - uint8_t regsInPacket = (totalRegs - regsProcessed) > 4 ? 4 : (totalRegs - regsProcessed); - // Формируем body - msgBodyModbusType body; - body.Fields.StrAdr = startAddress; - body.Fields.RegCount = regsInPacket; - // Обновляем ExtId - localId.Fields.MsgBody = (body.Body & 0xFFFF); - TxHeader.ExtId = PROTOCAN_IdPack(&localId); - TxHeader.IDE = CAN_ID_EXT; - TxHeader.RTR = CAN_RTR_DATA; - TxHeader.TransmitGlobalTime = DISABLE; - TxHeader.DLC = regsInPacket * 2; - // Добавляем регистры - for (int i = 0; i < regsInPacket; i++) - { - canData[i * 2] = LowByteOfWord(dataPtr[regsProcessed + i]); - canData[i * 2 + 1] = HighByteOfWord(dataPtr[regsProcessed + i]); - } - // Отправляем сообщение - if(HAL_CAN_AddTxMessage(_HCAN, &TxHeader, canData, &TxMailBox) != HAL_OK) - { - return PROTOCAN_ERROR; - } - regsProcessed += regsInPacket; - startAddress += regsInPacket; - } - } - else - { - return PROTOCAN_ERROR; // Неверный тип сообщения - } - return PROTOCAN_OK; -} +PROTOCAN_StatusTypeDef PROTOCAN_SEND_MODBUS(const ProtoCanId_t id, const struct ProtoCanModbusData data) /* Отправляет одно окно из 1…4 битов или регистров. */ +{ /* Вся полезная нагрузка помещается в один classic CAN-кадр с DLC не более восьми. */ + ProtoCanId_t local = id; /* Сохраняем исходный адрес узла, приоритет и направление. */ + CAN_TxHeaderTypeDef header = {0}; /* Нулевая инициализация исключает неопределённые поля HAL-заголовка. */ + uint32_t mailbox = 0U; /* HAL запишет номер использованного аппаратного mailbox. */ + uint8_t bytes[8] = {0}; /* Максимум четыре 16-битных регистра занимают восемь октетов. */ + unsigned index; /* Индекс ограничен проверенным количеством регистров 1…4. */ + if (_HCAN == NULL || local.Fields.MsgType != PROTOCAN_MSGTYPE_MODBUS || data.Function < 1U || data.Function > 4U || data.RegCount < 1U || data.RegCount > 4U || data.StrAdr > 0xFFFU || data.StrAdr + data.RegCount > 0x1000U) return PROTOCAN_ERROR; /* Не отправляем неинициализированный CAN или значения за пределами wire-полей. */ + if (data.Data == NULL && local.Fields.Route == PROTOCAN_ROUTE_FROM_DEVICE) return PROTOCAN_ERROR; /* Устройство не отправляет пустые ответы вместо запрошенных значений. */ + local.Fields.MsgBody = pcan_body_modbus(data.StrAdr, (uint_least8_t)data.RegCount, (uint_least8_t)data.Function); /* Общий упаковщик помещает функцию минус один в 3:2, количество минус один в 1:0. */ + header.ExtId = PROTOCAN_IdPack(&local); /* Используем явную переносимую упаковку всех полей CAN ID. */ + header.IDE = CAN_ID_EXT; header.RTR = CAN_RTR_DATA; header.TransmitGlobalTime = DISABLE; /* ProtoCAN передаётся расширенным data frame без RTR. */ + header.DLC = data.Data == NULL ? 0U : (data.Function <= 2U ? 1U : data.RegCount * 2U); /* NULL запрашивает чтение; непустой буфер содержит один октет битов либо 2…8 октетов регистров. */ + if (data.Data != NULL && data.Function <= 2U) { /* Битовые банки используют младшие биты первого слова, как и переносимый сервер. */ + if ((data.Data[0] >> data.RegCount) != 0U) return PROTOCAN_ERROR; /* Не усекаем установленные биты за пределами запрошенного окна. */ + bytes[0] = (uint8_t)data.Data[0]; /* Для 1…4 битов достаточно одного wire-октета. */ + } else if (data.Data != NULL) { /* Слова Holding/Input кодируются little-endian. */ + for (index = 0U; index < data.RegCount; ++index) { /* Каждому адресу соответствует ровно одно 16-битное слово. */ + bytes[index * 2U] = (uint8_t)data.Data[index]; /* Младший октет располагается первым в payload. */ + bytes[index * 2U + 1U] = (uint8_t)(data.Data[index] >> 8U); /* Сдвиг на восемь бит извлекает старший октет регистра. */ + } /* Заканчиваем упаковку проверенного числа регистров. */ + } /* Для запроса чтения массив остаётся пустым, поскольку DLC равен нулю. */ + return (PROTOCAN_StatusTypeDef)HAL_CAN_AddTxMessage(_HCAN, &header, bytes, &mailbox); /* Возвращаем фактический результат постановки одного кадра в очередь HAL. */ +} /* Конец отправки единого Modbus типа 0x5. */ /** * @brief __weak Функция отправки сообщения об ошибке. @@ -1649,10 +1472,9 @@ PROTOCAN_StatusTypeDef PROTOCAN_SEND(ProtoCanId_t id, ProtoCanData_t data) data.GeneralAddressSpaceData.Data, data.GeneralAddressSpaceData.RegCount); } - case PROTOCAN_MSGTYPE_MODBUS_COIL: - case PROTOCAN_MSGTYPE_MODBUS_DISCRETE: - case PROTOCAN_MSGTYPE_MODBUS_HOLDING: - case PROTOCAN_MSGTYPE_MODBUS_INPUT: + case PROTOCAN_MSGTYPE_GAS_SLOT: /* Отправка 0x4 использует служебную маску, а не структуру Modbus. */ + return PROTOCAN_SEND_GAS_SLOT(id, data.GasSlotData.Address, data.GasSlotData.Words, data.GasSlotData.Count); /* Count=0 запрашивает чтение; Count=4 передаёт маску и три значения. */ + case PROTOCAN_MSGTYPE_MODBUS: /* Все четыре банка отправляются одним типом, функция задаётся в ModbusData. */ { return PROTOCAN_SEND_MODBUS(id, data.ModbusData); break; diff --git a/c/set-protocol/ports/stm32-bxcan/protocan.h b/c/set-protocol/ports/stm32-bxcan/protocan.h index 2fac9b8..5e30422 100644 --- a/c/set-protocol/ports/stm32-bxcan/protocan.h +++ b/c/set-protocol/ports/stm32-bxcan/protocan.h @@ -10,6 +10,7 @@ #include "main.h" #include "can.h" #include "pcan_id.h" +#include "pcan_gas_slot.h" /* Общий формат типа 0x4 используется при приёме и отправке масочных слотов без дублирования кодека. */ #define _DEMO @@ -82,10 +83,8 @@ typedef enum { PROTOCAN_MSGTYPE_DISCRETE = 0b0001, /**< Дискретное цифровое сообщение. */ PROTOCAN_MSGTYPE_ANALOG = 0b0010, /**< Аналоговое сообщение. */ PROTOCAN_MSGTYPE_GENERAL_ADDRESS_SPACE = 0b0011, /**< Сообщение общего адресного пространства. */ - PROTOCAN_MSGTYPE_MODBUS_COIL = 0b0100, /**< Сообщение Modbus - Coil. */ - PROTOCAN_MSGTYPE_MODBUS_DISCRETE = 0b0101, /**< Сообщение Modbus - Discrete. */ - PROTOCAN_MSGTYPE_MODBUS_HOLDING = 0b0110, /**< Сообщение Modbus - Holding. */ - PROTOCAN_MSGTYPE_MODBUS_INPUT = 0b0111, /**< Сообщение Modbus - Input. */ + PROTOCAN_MSGTYPE_GAS_SLOT = 0b0100, /**< Слотный GAS: Word0 — маска, Word1…Word3 — значения; прежний код Coil заменён. */ + PROTOCAN_MSGTYPE_MODBUS = 0b0101, /**< Единый Modbus с функцией 1…4 в Body; номера 0x6/0x7 свободны. */ PROTOCAN_MSGTYPE_ERROR = 0b1000, /**< Сообщение об ошибке. */ PROTOCAN_MSGTYPE_BOOT_CONTROL = 0b1001, /**< Команды ProtoCAN Boot. */ PROTOCAN_MSGTYPE_BOOT_DATA_A = 0b1010, /**< Блок образа для слота A. */ @@ -224,7 +223,8 @@ typedef union{ */ typedef union{ struct msgBody_Modbus{ - unsigned RegCount:4; /**< Количество регистров (4 бита). */ + unsigned RegCountMinus1:2; /**< Биты 1:0 хранят количество регистров или битов минус один, wire-коды 0…3. */ + unsigned FunctionMinus1:2; /**< Биты 3:2 хранят функцию Coil=1, Discrete=2, Holding=3, Input=4 минус один. */ unsigned StrAdr:12; /**< Адрес строки или регистра (12 бит). */ } Fields; /**< Поля структуры сообщения Modbus. */ unsigned Body; /**< Общее 16-битное представление сообщения. */ @@ -314,10 +314,16 @@ typedef struct{ uint16_t *Data; /**< Указатель на массив данных. */ unsigned RegCount; /**< Количество регистров. */ } GeneralAddressSpaceData; + struct ProtoCanGasSlotData { /* Отдельная структура исключает смешение номера слота и адреса первого регистра GAS. */ + uint16_t Address; /* Полный 16-битный адрес слота 0…65535. */ + const uint16_t *Words; /* Четыре wire-слова: маска Word0 и значения Word1…Word3. */ + unsigned Count; /* Ноль означает чтение, четыре — маску и три значения; другие размеры отвергает C-кодек. */ + } GasSlotData; /* Член структуры используется только для MsgType=0x4. */ struct ProtoCanModbusData{ - uint16_t StrAdr; - uint16_t *Data; - unsigned RegCount:4; + uint16_t StrAdr; /* Адрес первого регистра или бита 0…4095; всё окно должно помещаться в этот диапазон. */ + uint16_t *Data; /* NULL запрашивает чтение; битовые банки используют упакованную маску в Data[0], регистровые — массив слов. */ + unsigned RegCount; /* Физическое количество 1…4; обычное поле позволяет отклонить неверный ввод до упаковки. */ + unsigned Function; /* Физический номер функции 1…4, независимый от единого MsgType=0x5. */ } ModbusData; struct ProtoCanErrorData{ uint16_t Info; @@ -422,10 +428,10 @@ PROTOCAN_StatusTypeDef ProtoCanMsgToGeneralAddressSpace(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef PROTOCAN_RequestError(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef PROTOCAN_ModbusProcessing(struct RXMsg _rxMsg); -PROTOCAN_StatusTypeDef ProtoCanMsgToModbusCoil(struct RXMsg _rxMsg); -PROTOCAN_StatusTypeDef ProtoCanMsgToModbusDiscrete(struct RXMsg _rxMsg); -PROTOCAN_StatusTypeDef ProtoCanMsgToModbusHolding(struct RXMsg _rxMsg); -PROTOCAN_StatusTypeDef ProtoCanMsgToModbusInput(struct RXMsg _rxMsg); +void PROTOCAN_GAS_SLOT_BIND(const pcan_gas_slot_port_t *port); /* Подключает долгоживущий provider слотов до обработки очереди; NULL отключает сервис. */ +PROTOCAN_StatusTypeDef ProtoCanMsgToGasSlot(struct RXMsg message); /* Передаёт тип 0x4 общему обработчику с проверкой адреса узла и маски Word0. */ +PROTOCAN_StatusTypeDef PROTOCAN_SEND_GAS_SLOT(ProtoCanId_t id, uint16_t address, const uint16_t *words, unsigned count); /* Отправляет один слот через общий C-кодек, без Modbus-упаковки адреса. */ +PROTOCAN_StatusTypeDef ProtoCanMsgToModbus(struct RXMsg _rxMsg); /* Единая weak-точка приложения обрабатывает все четыре банка по полю функции Body. */ void PROTOCAN_RTC_SYNC(uint8_t *data); diff --git a/c/set-protocol/ports/stm32g474-hope/IGBT_REALTIME.md b/c/set-protocol/ports/stm32g474-hope/IGBT_REALTIME.md new file mode 100644 index 0000000..b6509d0 --- /dev/null +++ b/c/set-protocol/ports/stm32g474-hope/IGBT_REALTIME.md @@ -0,0 +1,100 @@ +# HOPE STM32G474VET6: аппаратные IGBT-импульсы + +IGBT версии 4 формирует физические сигналы аппаратными таймерами, с заданиями в **наносекундах**. Поддерживаются все восемь независимых каналов и два режима: + +- **Внешний Vin → аппаратный ACK**: фронт внешней команды запускает задержку и ответ Vstat непосредственно в таймере. +- **Физический TX → настоящий драйвер**: выход выдаёт одиночный импульс или удерживаемый логический уровень; вход той же пары можно подключить к Vstat настоящего драйвера для наблюдения уровня и счётчика фронтов. + +Один выходной контакт используется либо как ACK, либо как TX. Это цифровая логическая сторона 3,3 В с общей землёй; сигналы силового затвора не формируются. По умолчанию после загрузки прошивки выбран УМП, а аппаратные выходы IGBT выключены. Работающие импульсы не обслуживаются миллисекундным циклом, USB или GUI. + +## Подключение восьми каналов + +Номера J5/J6 сверены визуально с заводской схемой HOPE от 14.04.2025. Входы и выходы **отличаются от прежней разводки PB… → PC0…PC7**. Отсчёт каналов в GUI начинается с 1, биты протокола — с 0. + +| Канал | Вход Vin / Vstat | Контакт входа | Выход ACK / TX | Контакт выхода | Таймер | +|---|---|---|---|---|---| +| 1 | PB6 | J6-7 | PB14 | J5-26 | HRTIM D1, EEV4 | +| 2 | PB7 | J6-8 | PC8 | J6-21 | HRTIM E1, EEV3 | +| 3 | PB3 | J6-12 | PC6 | J6-23 | HRTIM F1, EEV9 | +| 4 | PD3 | J6-15 | PD4 | J6-16 | TIM2 CH1/CH2 | +| 5 | PB4 | J6-9 | PB5 | J6-10 | TIM3 CH1/CH2 | +| 6 | PD12 | J6-27 | PD13 | J6-28 | TIM4 CH1/CH2 | +| 7 | PA0 | J5-5 | PA1 | J5-6 | TIM5 CH1/CH2 | +| 8 | PA2 | J5-7 | PA3 | J5-8 | TIM15 CH1/CH2 | + +Общая земля — **J5-29 или J6-30**. USB PA11/PA12, штатный USART1/CH340 PA9/PA10 и заводские CAN1/2/3 сохраняются. Перемычки JP2 снимать не требуется. SWD PA13/PA14 сохраняется; PB3 занимает аппаратный вход вместо SWO. На время всего режима IGBT приостанавливается ST7789, поскольку PC8 используется как HRTIM E1; после выхода дисплей восстанавливается, если ранее был включён. + +## Запуск эмулятора ACK + +1. Установите новую прошивку HOPE. Для установленного CANdle boot используйте приложение **с адреса 0x08008000**. Standalone предназначен для отдельного варианта без сохранения загрузчика. +2. Откройте SETGUI: **Терминал → STM32 → HOPE STM32G474VET6 → Эмуляторы → Настройки STM**. Выберите COM, адрес 16, 115200/8N1. Прочитайте STM, выберите IGBT и нажмите **«Применить в STM и проверить»**. +3. Откройте **IGBT / драйвер**, нажмите **«Прочитать состояние»**. В пояснении должно быть **IGBT v4**, у временных полей — **нс**. Старая прошивка остаётся явно обозначенной как v3/мс. +4. Выберите **«Внешний Vin → аппаратный ACK»**, канал и профиль 1SP0635 либо 1SD536F2. Нажмите **«Подготовить профиль с реальными временами»**. +5. Проверьте полярность, разрешения TX/RX и фронты, отметьте **«Аппаратные выходы разрешены»**, нажмите **«Применить канал и общие задания»**. +6. Подайте внешний Vin на вход выбранной пары. Измеряйте Vin и выходной ACK осциллографом либо анализатором с подходящей частотой выборки. Перечитайте счётчики в GUI. + +При подтверждении обоих фронтов ON и OFF должны иметь одинаковые задержки и одинаковые ширины. Для единственного разрешённого фронта используются соответствующие отдельные ON- либо OFF-поля. Фронт во время незавершённого ответа перезапускает аппаратный цикл; для раздельных ACK расстояние между входными фронтами должно превышать задержку плюс ширину ответа. Входной фронт не запускается из ISR. + +Принудительные RX=0/1 задают электрический уровень. «Нет ACK» сохраняет неактивный уровень с учётом полярности. FAULT применяется вместе с профилем: ненулевая длительность заменяет обычную ширину ответа, 0 удерживает активный ответ после фронта до явного изменения профиля или останова. При генерации физического TX маска FAULT не формирует искусственный ответ настоящего драйвера. + +## Запуск физического TX + +1. Подключите **выход** выбранной пары к логическому Vin настоящего драйвера. При необходимости соедините его логический Vstat со **входом** этой пары. +2. Выберите **«Физический TX → настоящий драйвер»**, задайте длительность TX в нс, разрешите канал и аппаратные выходы. +3. Снимите «Задание TX» выбранного канала и нажмите **«Применить канал и общие задания»**. +4. Нажмите **«Импульс TX выбранного канала»**. Профиль по умолчанию выдаёт **10000 нс = 10 мкс**. Реальную длительность отмеряет таймер. + +Кнопка «Отправить TX» устанавливает постоянные уровни. Повторный одиночный импульс при TX=1 либо занятости выбранного канала отвергается. Запись маски 0xFF в команду импульса запускает все восемь генераторов: HRTIM D/E/F запускаются одной записью, обычные TIM — короткой последовательностью записей. Общий синхронный фронт с одинаковой фазой между разными блоками HRTIM/TIM не гарантируется. Непрерывный PWM этой командой не включается. + +**«Выключить эмуляцию»** снимает все аппаратные триггеры и удерживает выходы в нуле. Останов доступен из любого режима и при незавершённой подготовке профиля. «Отменить обмен» прекращает только транзакцию COM и не заменяет физическую команду останова. + +## Времена, разрешение и компенсация + +Интервалы ACK, TX и конечного FAULT задаются в диапазоне **50…60000 нс**. Нулевой FAULT означает удержание. HRTIM автоматически выбирает максимальный множитель, при котором полный цикл помещается в 16-битный счётчик: при коротком профиле ×32 шаг выходной сетки **0,1953125 нс** от 160 МГц. Для больших интервалов множитель уменьшается. У TIM2/3/4/5/15 шаг **6,25 нс**. Значения округляются к ближайшему аппаратному кванту. + +Шаг выходной сетки не равен абсолютной точности Vin→Vstat. Входная синхронизация, GPIO, нагрузка и измерительный тракт добавляют задержку и джиттер. По умолчанию компенсация равна 0: заданная задержка отсчитывается после аппаратного триггера и внешнее измерение будет включать входной тракт. + +Калибровка каждого канала: + +1. Примените одинаковые ON/OFF и измерьте задержку между физическим Vin и началом ACK. +2. Вычислите добавку: измеренная задержка минус заданная задержка. +3. Запишите эту измеренную положительную добавку в **«Измеренная компенсация входа»**, нс, примените и повторите измерение. + +Прошивка вычитает компенсацию из таймерной задержки; оставшийся интервал должен быть не меньше 50 нс. Компенсация ограничена 1000 нс и не сохраняется во Flash. Паспортные 1SP0635 250/700 нс являются исходным заданием; у 1SD536F2 380 нс — справочная задержка, а 900 нс — номинал примера проекта, не заданная паспортом типичная ширина. См. профили и источники в SETGUI/docs/DRIVER_TIMING_RU.md. + +Счётчики фиксируют входные capture-события. Они не измеряют ширину выходного импульса. У обычных TIM отдельно публикуются overcapture; у HRTIM нет гарантии точного подсчёта всех IRQ при чрезмерно частых фронтах. Даже при нагрузке на IRQ времена выходов задаются аппаратными compare. Электрические времена требуют отдельного измерения на плате. + +## Совместимость и карта регистров + +Окно остаётся **0x1400…0x146F, 112 слов**, сигнатура 0x4947, версия **4**, 8 каналов, размер блока канала 12 слов. Код единиц в слове 11 равен **0 = нс**. Версия 3 имеет отдельный код 1 и миллисекундную семантику. GUI заново проверяет версию перед каждым планом записи и не отправляет задания, если единицы изменились. Безусловный останов совместим с обеими версиями. + +| Смещение от 0x1400 | Значение версии 4 | +|---|---| +| 2 | 0: немедленный останов; 1: проверить и применить весь подготовленный профиль, включить выходы | +| 3 / 4 | Фактические Vin/TX и Vstat/RX; в генераторе направления пары обращены | +| 5 | Возможности 0x001F; бит 15: есть неприменённые задания | +| 6 | Подготовленная маска FAULT | +| 7 / 8 | Минимум 50 и максимум 60000 нс | +| 9 | Сумма счётчиков входных фронтов; запись 0 сбрасывает диагностику | +| 10 / 11 | 8 каналов / код единиц 0 | +| 12 | Подготовленный режим: 0 внешний ACK, 1 физический TX | +| 13 | Удерживаемая маска TX; запись действует только в применённом режиме генератора | +| 14 | Чтение: занятые TX; запись ненулевой восьмибитной маски запускает одиночные импульсы | +| 15 | 12 слов на канал | + +База канала с битом `n`: `16 + 12*n`. Поля 0…8 сохраняют порядок флагов, режима RX, задержки ON, ширины ON, задержки OFF, ширины OFF, длительности TX, маски фронтов и длительности FAULT. Все времена здесь в нс. Поле 9 — счётчик входных фронтов; 10 — измеренная компенсация входа в нс; 11 — overcapture обычного TIM. + +Поканальные записи и маски готовятся отдельно от работающих таймеров. Только завершающая запись 1 в смещение 2 применяет согласованный профиль. При изменении одного канала остальные неизменённые каналы продолжают работать; незавершённый ответ изменяемого канала сбрасывается. Смена направления ACK/TX либо включение после останова перенастраивает все каналы. Во время выполняемого физического TX либо удерживаемого TX=1 применение отвергается, чтобы перенастройка GPIO/AF не создала лишний фронт настоящему драйверу. Сначала отправьте нулевой TX либо выполните явный останов. Ошибка проверки или часов обнаруживается до изменения оборудования. + +## Сборка и проверка + +Основной проект: `stm32f407_emulator/G474/HOPE/MDK-ARM/UMP_Emulator_HOPE_G474VE.uvprojx`. Оба target включают переносимый `set_igbt_realtime.c` и аппаратный `igbt_realtime_port.c`. Адреса Flash и существующий startup сохранены. + +Из SETGUI: + +```powershell +.\scripts\build_igbt_realtime.ps1 # Собирает приложение CANdle с VTOR 0x08008000, сохраняя первые 32 КиБ загрузчика. +.\scripts\build_igbt_realtime.ps1 -Standalone # Собирает отдельный образ с VTOR 0x08000000 для варианта без сохранения boot. +``` + +Результаты находятся в `dist/igbt-realtime/hope/`. Тесты `tests/test_igbt_realtime.py` проверяют настоящий протокол C и Qt-клиент, подготовку/применение, отказы, версионную защиту, восемь маршрутов и реальные CMSIS-маски/compare в host-MMIO. Эти проверки и успешная ARM-линковка не заменяют измерение Vin/Vstat на физической плате. diff --git a/c/set-protocol/ports/stm32g474-hope/README.md b/c/set-protocol/ports/stm32g474-hope/README.md new file mode 100644 index 0000000..3796dc4 --- /dev/null +++ b/c/set-protocol/ports/stm32g474-hope/README.md @@ -0,0 +1,95 @@ +# HOPE STM32G474VET6: HAL-порт эмуляторов + +Общий аппаратный порт платы HOPE G474VET6, опознанной пользователем по +[фотографии платы с тремя CAN-разъёмами](https://www.ebay.com/itm/397096571989). +Найдена [исходная схема от 14.04.2025](docs/HOPE_G474VE_schematic_20250414.pdf): +USART1 PA9/PA10 соединён с CH340N через JP2, FDCAN1 PD0/PD1 — с U6 +TJA1051T/3 и CAN1L/CAN1H разъёма J4. Кварц JT1 имеет частоту 8 МГц. +Источник PDF: пользовательская папка +`F:/programm/utilits/china/aliexpresы/stm32g474vet_fdcan`, файл +`G474VET6板子原理图20250414.pdf`. Копия сохранена побайтно без изменения схемы. +Публичный репозиторий производителя и исходники заводских примеров пока не найдены. +Аппаратный запуск на физической плате ещё не выполнен. + +Этот порт находится в общем репозитории `templates`. Пример интеграции Keil: +`stm32f407_emulator/G474/HOPE`. Локальные `Src` — include-обёртки; +модели УМП, 2812 и IGBT, DAC-протокол, GAS и кодеки не копируются. + +## Подключение + +Включите этот каталог в include path перед портом USB boot G474RB. +Предоставьте `board_config.h`, включающий `board_config.template.h`. +Компилируйте `board.c`, общий `stm32g474-periph/main.c`, +`stm32g474-periph/transport.c`, `stm32g474-periph/wave_hal.c` и +`stm32g474-usb-boot/boot_usb_port.c`. Нужны HAL G4 UART/FDCAN/PCD/RCC/PWR, +DAC/DMA/TIM, CMSIS startup G474, ST USB Device CDC и обычная композиция моделей. +`EMU_CAPACITY=400`: один архив 32000 байт — в SRAM, второй — в CCM 32 КиБ; +таблица DAC 8192 байта должна оставаться в SRAM, доступной DMA. + +| Интерфейс | Назначение | +| --- | --- | +| USART1 PA9 TX / PA10 RX AF7 | RTU и SETGUI v1/GAS, 115200 бод, 8N1 | +| FDCAN1 PD0 RX / PD1 TX AF9 | U6 TJA1051T/3, CAN1L/CAN1H J4; Classic CAN, 250 кбит/с, extended RX 0xBA0004 / TX 0xBA0024 | +| USB PA11 D− / PA12 D+ | Нативный USB CDC SET v2, отдельный от USB–UART платы | +| DAC1 channel 1 PA4 | TIM6 TRGO → DMAMUX → DMA1 channel 1, до 1 млн отсчётов/с | +| USART3 PD8 TX / PD9 RX, PD10 DE | Встроенный RS-485 SP3485EN-L; порт его не инициализирует | +| FDCAN2 PB12 RX / PB13 TX | U7 TJA1051T/3; порт его не инициализирует | +| FDCAN3 PA8 RX / PA15 TX | U8 TJA1051T/3; порт его не инициализирует | +| SPI4 PE4 CS / PE2 SCK / PE5 MISO / PE6 MOSI | W25Q64; порт его не инициализирует | +| KEY1/2/3 PE7/8/9; LED1/2/3 PF2/9/10 | Заводские органы управления; порт их не инициализирует | + +По умолчанию CPU=160 МГц от кварца HSE 8 МГц/PLL; APB1=80 МГц, TIM6=160 МГц, +USART1 от APB2=160 МГц. USB использует HSI48 с CRS по SOF. +HSE определяет точность CAN и DAC; CRS подстраивает только USB. +`EMU_USE_HSE=0` выбирает резервный HSI16. Порт также допускает HSE 24 МГц +при физической замене кварца и соответствующем `EMU_HSE_HZ`. +RTC-кварц JT2 32,768 кГц не участвует в системной PLL. + +## Совместимость загрузчика + +Найденный исходный проект: `https://git.rd12.ru/setcorp/CANdle_stm32.git`. +Название `candle_474` не подтверждено как отдельный доступный репозиторий. +Сам reusable загрузчик уже находится в актуальном общем `templates`: +[`c/protocan-boot/ports/stm32g474`](../../../protocan-boot/ports/stm32g474/README.md). +Его модули `pcan_boot` и `rs485-boot` обслуживают CAN и UART. Данный порт +эмулятора не включает загрузочную машину состояний в основное приложение. + +Для установленного CANdle boot задайте `EMU_FLASH_BASE=0x08008000`, +Flash приложения 480 КиБ и RAM `0x20000000..0x20013FF7`. +Исключите последние восемь байт прежних 80 КиБ SRAM: загрузчик проверяет +initial MSP до `0x20014000`, маркер CANB хранится в `0x20013FFC`. +Начальные векторы должны находиться по тому же адресу, что VTOR. +Образ с `0x08010000`, рассчитанный на RB USB boot, здесь несовместим. + +Только для CANdle-профиля компилируйте `boot_request.c` и определите +`EMU_USB_BOOT_ENABLE`. Адресная USB SET v2 команда `0x1003` без payload +записывает `0x43414E42` в SRAM и через 500 мс перезагружает MCU. +После reset работает существующий CAN/UART boot: FDCAN1 500 кбит/с, +ProtoCAN Type=7/ID=15; USART1 512000 бод. USB-прошивальщик RB +`flash-usb.py --target g474` этому загрузчику не соответствует. +Исходный общий boot использовал PB8/PB9, которые не соединены с CAN1 HOPE: +PB8 занят BOOT0. Готовый [адаптер BOOT HOPE](../../../protocan-boot/ports/stm32g474-hope/README.md) +подключает тот же загрузчик к PD0/PD1 AF9. Он собирается отдельным проектом +`HOPE_G474VE_BOOT`, включённым в `474-hope.uvmpw`. UART PA9/PA10, Flash-слот +и SRAM-маркер сохранены. Для обновления установленного BOOT нужен его новый HEX через SWD. +Автоматический вход по CAN ENTER_BOOT или UART BEGIN из работающего эмулятора +в этой интеграции не добавлен; для них используйте окно загрузчика после reset. + +Самостоятельный профиль задаёт `EMU_FLASH_BASE=0x08000000` и не определяет +`EMU_USB_BOOT_ENABLE`. Он заменяет загрузчик, если записывается через SWD. +512 КиБ Flash проверяются при запуске; DBANK=0 и DBANK=1 допускаются, +перестановка BFB2/FB_MODE отвергается. Option Bytes порт не изменяет. + +## IGBT + +Модель доступна во всех профилях через регистры: `0x140C=1` выбирает +программный TX, `0x1403` задаёт маску, `0x1404` возвращает RX. +Физические GPIO по умолчанию отключены (`EMU_IGBT_GPIO_ENABLE=0`): +PB12/PB13 прежнего ручного профиля соединены со штатным трансивером CAN2. +Профиль Vin=PB0/1/2/10..14 и Vstat=PC0..PC7 допустим только после физического +устранения этого соединения или изменения профиля на свободные выводы. +Адреса и алгоритм IGBT остаются общими для всех MCU. + +## Аппаратный IGBT v4 + +Новый HOPE по умолчанию использует `EMU_IGBT_REALTIME=1`, HRTIM D/E/F и TIM2/3/4/5/15. Все восемь каналов работают аппаратно с заданиями в нс; поддержаны внешний Vin→ACK и физический TX. Новая распиновка и порядок проверки: [IGBT_REALTIME.md](IGBT_REALTIME.md). UART, USB и заводские CAN сохранены; PC8 временно используется вместо CS ST7789. Компилируйте также `src/set_igbt_realtime.c` и `igbt_realtime_port.c`. Прежний GPIO-профиль доступен при `EMU_IGBT_REALTIME=0`. diff --git a/c/set-protocol/ports/stm32g474-hope/board.c b/c/set-protocol/ports/stm32g474-hope/board.c new file mode 100644 index 0000000..e053dbf --- /dev/null +++ b/c/set-protocol/ports/stm32g474-hope/board.c @@ -0,0 +1,131 @@ +#include "board.h" /* Подключает публичный интерфейс аппаратного HAL-слоя HOPE. */ +#include "board_config.h" /* Выбирает размещение Flash, USART1 и разрешение физических выводов IGBT. */ +#include "transport.h" /* Объявляет запуск общего UART/FDCAN-транспорта после настройки GPIO. */ +#include "emulator.h" /* Подключает единый шаг моделей УМП, 2812, IGBT и генератора. */ +#include "igbt_realtime_port.h" /* Объявляет аппаратный IGBT версии 4 с наносекундными compare. */ +#include "emulator_port.h" /* Даёт доступ к существующей карте сервера до первого транспортного запроса. */ +#include "igbt_emulator.h" /* Передаёт физическую маску Vin и получает маску ответов Vstat. */ +#include "stm32g4xx_hal.h" /* Предоставляет HAL RCC/PWR/GPIO и определения регистров Cortex-M4. */ +volatile uint32_t clock_fault; /* Хранит диагностический код запуска для просмотра через SWD. */ +uint32_t SystemCoreClock = 16000000u; /* После reset HSI16 работает на 16 МГц до настройки PLL HAL. */ +const uint8_t AHBPrescTable[16] = {0,0,0,0,0,0,0,0,1,2,3,4,6,7,8,9}; /* CMSIS-кодирует делители HPRE как степени двойки по RM0440. */ +const uint8_t APBPrescTable[8] = {0,0,0,0,1,2,3,4}; /* HAL использует кодировку PPRE для вычисления частоты периферии G4. */ +static uint8_t usb_clock_ready; /* До настройки HSI48/CRS предотвращает преждевременный запуск USB. */ +#if EMU_IGBT_GPIO_ENABLE && !EMU_IGBT_REALTIME /* Не занимает выводы FLASH/CAN2/CAN3 на неподтверждённой ревизии HOPE по умолчанию. */ +static const uint16_t input_pins[8] = {GPIO_PIN_0,GPIO_PIN_1,GPIO_PIN_2,GPIO_PIN_10,GPIO_PIN_11,GPIO_PIN_12,GPIO_PIN_13,GPIO_PIN_14}; /* Ручной профиль Vin PB0/1/2/10..14 совпадает с прежним портом G474. */ +#endif /* Без физического порта все команды IGBT остаются доступны через общую карту регистров. */ +void SystemInit(void) /* Startup вызывает функцию до инициализации глобальных переменных C runtime. */ +{ /* До runtime доступны только константы сборки и регистры, поэтому HAL здесь не вызывается. */ + SCB->CPACR |= 0xFu << 20; /* Разрешает CP10/CP11 FPU: четыре бита доступа 20..23 по ARM Cortex-M4 TRM. */ + SCB->VTOR = EMU_FLASH_BASE; /* Переносит векторы на 0x08008000 для CANdle либо 0x08000000 для самостоятельного образа. */ + __DSB(); /* Завершает запись VTOR до потенциальной доставки аппаратного исключения. */ + __ISB(); /* Обновляет контекст инструкций после включения FPU и смены таблицы векторов. */ + SET_BIT(RCC->CR, RCC_CR_HSION); /* Включает HSI16, поскольку CANdle boot передаёт управление с PLL 144 МГц без сброса RCC. */ + while ((RCC->CR & RCC_CR_HSIRDY) == 0u) {} /* Ждёт готовности внутреннего источника до переключения SYSCLK без зависимости от неинициализированного HAL tick. */ + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_HSI); /* Переводит SYSCLK на HSI16 до изменения PLL, запрещённого при её использовании ядром. */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) {} /* Подтверждает аппаратное завершение переключения SYSCLK до отключения прежней PLL. */ + CLEAR_BIT(RCC->CR, RCC_CR_PLLON); /* Выключает PLL предыдущего загрузчика, чтобы HAL мог задать новые M/N/R для 160 МГц. */ + while ((RCC->CR & RCC_CR_PLLRDY) != 0u) {} /* Дожидается фактической остановки PLL перед дальнейшей инициализацией C runtime. */ + CLEAR_BIT(RCC->CFGR, RCC_CFGR_HPRE | RCC_CFGR_PPRE1 | RCC_CFGR_PPRE2); /* Возвращает AHB/APB к делению 1: глобальная SystemCoreClock=16 МГц и первый SysTick HAL совпадают с железом. */ +} /* Завершает минимальную настройку процессора без зависимости от BSS. */ +void SystemCoreClockUpdate(void) /* Поддерживает интерфейс CMSIS, используемый HAL при изменении дерева часов. */ +{ /* Частота определяется фактическим RCC, а не только константой желаемой частоты CPU. */ + RCC_ClkInitTypeDef config; uint32_t latency; /* Получает делитель AHB и обязательный выходной параметр задержки Flash. */ + HAL_RCC_GetClockConfig(&config, &latency); /* Читает активную конфигурацию RCC штатным HAL G4. */ + SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[config.AHBCLKDivider >> RCC_CFGR_HPRE_Pos]; /* Переводит SYSCLK в HCLK с аппаратным делителем AHB по RM0440. */ +} /* Завершает обновление частоты ядра в герцах. */ +void SysTick_Handler(void) { HAL_IncTick(); } /* Прерывание только увеличивает счётчик миллисекунд; модели выполняются в main. */ +void board_fatal(uint32_t code) { clock_fault = code; for (;;) {} } /* Останавливает дальнейшую настройку после отказа, сохраняя его причину в Watch. */ +static void peripheral_clock(void) /* Создаёт одинаковую частоту таймера DAC для обоих вариантов Flash. */ +{ /* Штатная PLL использует кварц JT1 8 МГц по схеме HOPE от 14.04.2025; HSI16 остаётся резервным профилем сборки. */ + RCC_OscInitTypeDef osc = {0}; RCC_ClkInitTypeDef clk = {0}; /* Нулевая инициализация отключает неиспользуемые ветви настройки генераторов и шин. */ + RCC_PeriphCLKInitTypeDef peripheral = {0}; RCC_CRSInitTypeDef crs = {0}; /* Готовит независимые источники USB, USART1 и FDCAN. */ + __HAL_RCC_PWR_CLK_ENABLE(); /* Разрешает HAL доступ к регулятору питания перед повышением частоты. */ + if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST) != HAL_OK) board_fatal(3); /* Boost Range1 требуется для CPU 160 МГц по ограничениям ST. */ + osc.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSI48; /* Включает HSI16 для CPU и отдельный HSI48 для USB FS. */ + osc.HSIState = RCC_HSI_ON; osc.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; /* Сохраняет заводскую подстройку внутреннего 16-МГц источника. */ + osc.HSI48State = RCC_HSI48_ON; /* USB получает собственный 48-МГц источник, корректируемый USB SOF через CRS. */ + osc.PLL.PLLState = RCC_PLL_ON; osc.PLL.PLLSource = RCC_PLLSOURCE_HSI; /* Задаёт внутренний источник для резервного профиля; штатная ветвь ниже выбирает HSE. */ + osc.PLL.PLLM = RCC_PLLM_DIV4; /* HSI16 / 4 даёт вход PLL 4 МГц, допустимый для PLLN=80. */ +#if EMU_USE_HSE /* Штатный профиль использует подтверждённый схемой кварц JT1 8 МГц для точности CAN и DAC. */ + osc.OscillatorType |= RCC_OSCILLATORTYPE_HSE; /* Добавляет внешний источник, сохраняя HSI48 для USB. */ + osc.HSEState = EMU_HSE_BYPASS ? RCC_HSE_BYPASS : RCC_HSE_ON; /* Различает внешний генератор и пассивный кварц по настройке платы. */ + osc.PLL.PLLSource = RCC_PLLSOURCE_HSE; /* Переключает источник PLL, от которого зависят CAN и частота генератора. */ +#if EMU_HSE_HZ == 8000000u /* Кварц 8 МГц требует делитель два для того же входа PLL 4 МГц. */ + osc.PLL.PLLM = RCC_PLLM_DIV2; /* Сохраняет итоговые 160 МГц при HSE 8 МГц. */ +#elif EMU_HSE_HZ == 24000000u /* Кварц 24 МГц требует делитель шесть для входа PLL 4 МГц. */ + osc.PLL.PLLM = RCC_PLLM_DIV6; /* Сохраняет итоговые 160 МГц при HSE 24 МГц. */ +#else /* Другие частоты требуют явного расчёта PLL вместо незаметного неверного тайминга. */ +#error Unsupported HOPE HSE frequency /* Допускает только проверяемые варианты внешнего источника 8 и 24 МГц. */ +#endif /* Завершает выбор делителя по физической частоте кварца. */ +#endif /* При EMU_USE_HSE=0 внешний источник вообще не запускается. */ + osc.PLL.PLLN = 80; osc.PLL.PLLP = RCC_PLLP_DIV2; /* Вход 4 МГц умножается до VCO 320 МГц; неиспользуемый PLLP имеет допустимый делитель. */ + osc.PLL.PLLQ = RCC_PLLQ_DIV2; osc.PLL.PLLR = RCC_PLLR_DIV2; /* PLLR / 2 создаёт CPU 160 МГц; USB не использует PLLQ. */ + if (HAL_RCC_OscConfig(&osc) != HAL_OK) board_fatal(3); /* Не продолжает запуск при отказе генератора или захвата PLL. */ + clk.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; /* Перенастраивает все шины, от которых зависит используемая периферия. */ + clk.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; clk.AHBCLKDivider = RCC_SYSCLK_DIV1; /* CPU и AHB получают 160 МГц без дополнительного деления. */ + clk.APB1CLKDivider = RCC_HCLK_DIV2; clk.APB2CLKDivider = RCC_HCLK_DIV1; /* PCLK1=80 МГц, TIM6=160 МГц и USART1 на PCLK2=160 МГц. */ + if (HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_4) != HAL_OK) board_fatal(3); /* Четыре wait-state соответствуют 160 МГц в Boost Range1 по RM0440. */ + peripheral.PeriphClockSelection = RCC_PERIPHCLK_USB | RCC_PERIPHCLK_FDCAN | RCC_PERIPHCLK_USART1; /* Выбирает только реальные блоки HOPE, исключая USART2 профиля Nucleo. */ + peripheral.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; /* Подаёт независимые 48 МГц на USB FS. */ + peripheral.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1; /* Общий CAN-порт рассчитывает 250 кбит/с из фактических 80 МГц PCLK1. */ + peripheral.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2; /* HAL вычисляет делитель USART1 из 160 МГц APB2. */ + if (HAL_RCCEx_PeriphCLKConfig(&peripheral) != HAL_OK) board_fatal(3); /* Ошибка выбора kernel clock обнаруживается до включения транспорта. */ + __HAL_RCC_CRS_CLK_ENABLE(); /* Разрешает блок автоматической подстройки HSI48 по USB SOF. */ + crs.Prescaler = RCC_CRS_SYNC_DIV1; crs.Source = RCC_CRS_SYNC_SOURCE_USB; /* Использует каждый входящий SOF USB без деления. */ + crs.Polarity = RCC_CRS_SYNC_POLARITY_RISING; /* Сохраняет рекомендованный HAL фронт синхронизации USB. */ + crs.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000u, 1000u); /* Рассчитывает 47999 тактов HSI48 на период SOF 1 мс. */ + crs.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT; crs.HSI48CalibrationValue = RCC_CRS_HSI48CALIBRATION_DEFAULT; /* Использует заводские начальные значения допусков и подстройки. */ + HAL_RCCEx_CRSConfig(&crs); usb_clock_ready = 1; /* Разрешает main запуск CDC после подготовки независимого USB clock. */ +} /* Завершает настройку часов без обращения к Flash Option Bytes. */ +void board_init(void) /* Вызывается после создания общих моделей и миллисекундного HAL tick. */ +{ /* Геометрия VE отличается от RB, но оба состояния DBANK при 512 КиБ имеют непрерывную карту Flash. */ + GPIO_InitTypeDef gpio = {0}; /* Не оставляет неинициализированных параметров альтернативных функций GPIO. */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); /* Даёт доступ к признаку фактической перестановки Flash-банков. */ + if (*(const uint16_t *)FLASHSIZE_BASE != 512u || (FLASH->OPTR & FLASH_OPTR_BFB2) || (SYSCFG->MEMRMP & SYSCFG_MEMRMP_FB_MODE)) board_fatal(5); /* Требует реальные 512 КиБ VE и обычное отображение банков; DBANK не изменяет. */ + peripheral_clock(); /* Стабилизирует частоты до запуска GPIO, USART1, FDCAN и USB. */ + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /* Порт A обслуживает USB/UART/DAC, порт D — штатный CAN1, порт B оставлен опциональным GPIO. */ + __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_FDCAN_CLK_ENABLE(); /* Подаёт часы только на выбранный USART1 и общий FDCAN kernel. */ + gpio.Pin = GPIO_PIN_9 | GPIO_PIN_10; gpio.Mode = GPIO_MODE_AF_PP; /* PA9 TX и PA10 RX подключены через JP2 к CH340N по схеме HOPE от 14.04.2025. */ + gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; gpio.Pull = GPIO_PULLUP; gpio.Alternate = GPIO_AF7_USART1; /* AF7 назначает USART1; подтяжка сохраняет idle RX при отсутствии адаптера. */ + HAL_GPIO_Init(GPIOA, &gpio); /* Применяет HAL-настройку UART к порту A одним вызовом. */ + gpio.Pin = GPIO_PIN_0 | GPIO_PIN_1; gpio.Alternate = GPIO_AF9_FDCAN1; /* PD0 RX и PD1 TX соединены с U6 TJA1051T/3; PB8 на этой плате занят BOOT0. */ + HAL_GPIO_Init(GPIOD, &gpio); /* Подключает FDCAN1 к штатным CAN1L/CAN1H разъёма J4 по схеме от 14.04.2025. */ +#if EMU_IGBT_GPIO_ENABLE && !EMU_IGBT_REALTIME /* Физический профиль включается вручную после проверки занятых выводов FLASH и других разъёмов. */ + __HAL_RCC_GPIOC_CLK_ENABLE(); /* Порт C нужен только для восьми физических выходов Vstat. */ + gpio.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14; /* Сохраняет отключённый ручной профиль Vin; PB12/PB13 соединены с CAN2 и требуют изменения внешних соединений. */ + gpio.Mode = GPIO_MODE_INPUT; gpio.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIOB, &gpio); /* Задаёт нулевой Vin на неподключённых входах выбранного ручного профиля. */ + gpio.Pin = 0xFFu; gpio.Mode = GPIO_MODE_OUTPUT_PP; gpio.Pull = GPIO_NOPULL; /* Биты 0..7 порта C становятся восемью ответами Vstat IGBT. */ + HAL_GPIO_WritePin(GPIOC, 0xFFu, GPIO_PIN_RESET); HAL_GPIO_Init(GPIOC, &gpio); /* Сначала записывает нули в ODR, исключая импульс при включении выходов. */ +#endif /* Без включённого профиля IGBT GPIO сохраняют своё состояние после reset. */ +#if EMU_RS485_DE /* Направление разрешается только для отдельно подключённого внешнего RS-485. */ + gpio.Pin = SERIAL_DE_PIN; gpio.Mode = GPIO_MODE_OUTPUT_PP; gpio.Pull = GPIO_NOPULL; /* Настраивает выбранный внешний вывод DE, не меняя UART TX/RX. */ + HAL_GPIO_WritePin(SERIAL_DE_PORT, SERIAL_DE_PIN, GPIO_PIN_RESET); HAL_GPIO_Init(SERIAL_DE_PORT, &gpio); /* Начинает в режиме приёма с выключенным передатчиком RS-485. */ +#endif /* Штатный TTL UART не занимает вывод DE. */ +#if EMU_IGBT_REALTIME /* Регистрирует аппаратный сервис только в новой сборке HOPE. */ + hope_igbt_realtime_init(emu_server_state()); /* Подменяет окно 0x1400 до первого запроса, сохраняя остальные модели и транспорты. */ +#endif /* Прежний профиль продолжает использовать миллисекундный IGBT версии 3. */ + transport_init(); /* Запускает HAL UART IRQ и Classic CAN после полной настройки GPIO/clock. */ +} /* Завершает аппаратный запуск HOPE, не запуская генерацию DAC без команды. */ +uint8_t board_usb_ready(void) { return usb_clock_ready; } /* Возвращает main готовность источника USB, общую для обоих вариантов Flash. */ +void board_tick(void) /* Выполняется главным циклом один раз на каждую обслуженную миллисекунду. */ +{ /* Протокольная инъекция IGBT работает и при отключённом физическом GPIO. */ +#if EMU_IGBT_REALTIME /* Выходные сроки обслуживаются аппаратными таймерами независимо от миллисекундного цикла. */ + emu_tick(); /* Сохраняет штатное время моделей и применения выбранного режима MCU. */ + hope_igbt_realtime_poll(); /* Останавливает аппаратный IGBT в том же шаге, в котором выбран другой режим. */ +#else /* Ветка совместимости сохраняет прежние миллисекундные GPIO. */ +#if EMU_IGBT_GPIO_ENABLE && !EMU_IGBT_REALTIME /* Считывает восемь физических Vin только для явно включённого ручного профиля. */ + uint8_t inputs = 0, outputs; unsigned i; /* Накопленная маска привязана к порядку input_pins, а не к номерам PB. */ + for (i = 0; i < 8; ++i) if (HAL_GPIO_ReadPin(GPIOB, input_pins[i]) == GPIO_PIN_SET) inputs |= (uint8_t)(1u << i); /* Переводит восемь уровней в логические Vin0..Vin7. */ + igbt_emu_set_tx(inputs); /* Передаёт физическую маску общей модели, сохраняя её выбор источника через регистр 0x140C. */ +#else /* Штатный профиль HOPE не использует неподтверждённые внешние дискретные линии. */ + igbt_emu_set_tx(0); /* При выборе GPIO задаёт нулевой Vin; регистровый источник остаётся независимым. */ +#endif /* Далее все модели продвигаются одинаково независимо от наличия дискретного порта. */ + emu_tick(); /* Продвигает выбранную модель и общие отложенные настройки ровно на 1 мс. */ +#if EMU_IGBT_GPIO_ENABLE && !EMU_IGBT_REALTIME /* Выдаёт Vstat только после завершения шага модели. */ + outputs = igbt_emu_get_rx(); /* Получает одну согласованную восьмибитную маску ответов IGBT. */ + HAL_GPIO_WritePin(GPIOC, (uint16_t)(~outputs & 0xFFu), GPIO_PIN_RESET); /* Сбрасывает только неактивные PC0..PC7 без изменения остальных выводов C. */ + HAL_GPIO_WritePin(GPIOC, outputs, GPIO_PIN_SET); /* Устанавливает активные ответы Vstat текущего шага модели. */ +#endif /* Завершает опциональное обновление физических ответов. */ +#endif /* Завершает выбор аппаратного либо прежнего логического IGBT. */ +} /* Завершает один миллисекундный шаг без обработки моделей из прерываний. */ diff --git a/c/set-protocol/ports/stm32g474-hope/board.h b/c/set-protocol/ports/stm32g474-hope/board.h new file mode 100644 index 0000000..06fe653 --- /dev/null +++ b/c/set-protocol/ports/stm32g474-hope/board.h @@ -0,0 +1,10 @@ +#ifndef HOPE_BOARD_H /* Защищает интерфейс платы от повторных объявлений в общей композиции. */ +#define HOPE_BOARD_H /* Отделяет аппаратную реализацию HOPE от моделей и транспортных кодеков. */ +#include /* Предоставляет фиксированные типы времени и диагностических кодов. */ +extern volatile uint32_t clock_fault; /* Watch: 2 — CAN, 3 — HAL/часы, 4 — UART, 5 — плотность Flash или перестановка банков. */ +void board_init(void); /* После HAL_Init и emu_init настраивает тактирование, GPIO и HAL-транспорт. */ +void board_tick(void); /* Выполняет один шаг моделей длительностью 1 мс в основном контексте. */ +uint8_t board_usb_ready(void); /* Разрешает запуск USB CDC после подготовки HSI48 и CRS. */ +void board_fatal(uint32_t code); /* Сохраняет причину отказа и останавливает main до аппаратного сброса. */ +void SysTick_Handler(void); /* Обслуживает миллисекундный счётчик HAL без исполнения моделей из IRQ. */ +#endif /* Завершает публичный интерфейс аппаратного слоя HOPE. */ diff --git a/c/set-protocol/ports/stm32g474-hope/board_config.template.h b/c/set-protocol/ports/stm32g474-hope/board_config.template.h new file mode 100644 index 0000000..5729ffd --- /dev/null +++ b/c/set-protocol/ports/stm32g474-hope/board_config.template.h @@ -0,0 +1,48 @@ +#ifndef HOPE_BOARD_CONFIG_H /* Защищает единый профиль платы HOPE от повторного включения. */ +#ifndef EMU_IGBT_REALTIME /* Разрешает явную сборку прежней логической модели для старого GUI. */ +#define EMU_IGBT_REALTIME 1 /* Штатный HOPE использует HRTIM D/E/F и TIM2/3/4/5/15 с окном IGBT версии 4 в наносекундах. */ +#endif /* Сохраняет явное переопределение параметром компилятора. */ +#define HOPE_BOARD_CONFIG_H /* Используется всеми аппаратными адаптерами и общей композицией моделей. */ +#define EMU_USB_SET_V2 1 /* Нативный USB MCU переносит SET v2; UART сохраняет RTU и SETGUI v1/GAS. */ +#define USB_CDC_IRQn USB_LP_IRQn /* G474 обслуживает USB FS через низкоприоритетный вектор USB_LP. */ +#define USB_CDC_PRODUCT_NAME "SET HOPE G474VE Emulator" /* Отличает виртуальный COM эмулятора от USB–UART CH340N на плате. */ +#define EMU_PRODUCT_MODEL "STM32G474VE-HOPE-EMU" /* Возвращается в DEVICE_INFO и проверяется host-тестом SET v2. */ +#define EMU_BOOT_REQUEST 0x1003u /* Сохраняет прикладную команду входа в загрузчик из USB SET v2. */ +#define EMU_REQUEST_BOOT(now) g474_request_boot(now) /* Адаптер HOPE записывает CANB в SRAM, совместимую с CANdle. */ +#define EMU_RS_ADDRESS 16u /* Узел управления моделями использует прежний адрес SetGUI, отличный от адреса CMD_STD. */ +#define EMU_TMS_ADDRESS 1u /* Отдельный адрес 2812 позволяет отличать CMD_STD от команд настройки эмулятора. */ +#define EMU_CAN_MODE 5u /* Общий протокол эмулятора использует extended RX 0xBA0004 и TX 0xBA0024. */ +#define EMU_UART_BAUD 115200u /* Начальная скорость приложения в бодах; загрузчик CANdle отдельно использует 512000. */ +#define EMU_CAN_BITRATE 250000u /* Начальная скорость приложения в бит/с; CAN-загрузчик отдельно использует 500000. */ +#define EMU_FLAGS_DEFAULT 1u /* После сброса разрешает синтетический сценарий УМП; модель по умолчанию остаётся УМП. */ +#define EMU_UART_INSTANCE USART1 /* Использует USART1 PA9/PA10, подключённый через JP2 к CH340N по схеме HOPE от 14.04.2025. */ +#define EMU_UART_IRQn USART1_IRQn /* Направляет RX/TX HAL в аппаратный вектор USART1 вместо USART2 Nucleo. */ +#define SERIAL_UART_IRQ_HANDLER USART1_IRQHandler /* Общий HAL UART публикует правильное имя вектора startup G474. */ +#define EMU_RS485_DE 0 /* Прямой TTL UART PA9/PA10 не требует управления направлением внешнего трансивера. */ +#define SERIAL_DE_PORT GPIOB /* При ручном включении RS-485 используется внешний DE на порту B. */ +#define SERIAL_DE_PIN GPIO_PIN_15 /* PB15 оставлен только опциональному внешнему DE; встроенный RS-485 HOPE не предполагается. */ +#ifndef EMU_USE_HSE /* Позволяет выбрать внешний кварц через настройки компилятора, не меняя переносимый порт. */ +#define EMU_USE_HSE 1 /* Использует кварц JT1 8 МГц, указанный в найденной схеме G474VET6 от 14.04.2025. */ +#endif /* Завершает выбор источника системной PLL. */ +#ifndef EMU_HSE_HZ /* Частота задаётся в герцах и должна соответствовать фактически установленному кварцу. */ +#define EMU_HSE_HZ 8000000u /* Номинал JT1 равен 8 МГц по схеме; HAL и PLL используют одну частоту в герцах. */ +#endif /* Сохраняет явно переданную частоту внешнего источника. */ +#define EMU_HSE_BYPASS 0 /* Внешний режим рассчитан на кварц; для готового генератора нужно отдельно выбрать bypass. */ +#ifndef EMU_IGBT_GPIO_ENABLE /* Ручной профиль Vin требует устранить подтверждённое схемой пересечение PB12/PB13 с CAN2. */ +#define EMU_IGBT_GPIO_ENABLE 0 /* Модель IGBT доступна через регистры; штатные линии CAN2 не становятся дискретными Vin. */ +#endif /* Позволяет включить физические Vin/Vstat параметром компилятора. */ +#ifndef EMU_FLASH_BASE /* Адрес задаётся одинаково в профиле Keil и его scatter-файле. */ +#define EMU_FLASH_BASE 0x08008000u /* Резервирует первые 32 КиБ под найденный CAN/UART-загрузчик CANdle. */ +#endif /* Самостоятельный профиль переопределяет адрес на 0x08000000. */ +#define HOPE_BOOT_REQUEST_ADDRESS 0x20013FFCu /* Совпадает с последним словом 80 КиБ SRAM в boot_profile.h CANdle. */ +#define HOPE_BOOT_REQUEST_MAGIC 0x43414E42u /* ASCII CANB запрашивает вход в существующий CAN/UART-загрузчик после reset. */ +#if EMU_RS_ADDRESS < 1 || EMU_RS_ADDRESS > 247 || EMU_TMS_ADDRESS < 1 || EMU_TMS_ADDRESS > 255 || EMU_TMS_ADDRESS == EMU_RS_ADDRESS /* Исключает недопустимые или совпадающие адреса двух обслуживаемых узлов. */ +#error Invalid HOPE emulator addresses /* Останавливает сборку до получения прошивки с неоднозначной маршрутизацией. */ +#endif /* Завершает проверку адресов протокола. */ +#if EMU_CAN_MODE < 1 || EMU_CAN_MODE > 16 /* Номер режима входит в младшую часть extended CAN ID общего протокола. */ +#error Invalid HOPE CAN mode /* Не допускает CAN ID за пределами поддерживаемых шестнадцати режимов. */ +#endif /* Завершает проверку режима CAN. */ +#if EMU_FLASH_BASE != 0x08000000u && EMU_FLASH_BASE != 0x08008000u /* Поддерживаются только два проверяемых варианта размещения Flash. */ +#error Invalid HOPE vector address /* Ошибка адреса VTOR не должна обнаруживаться только после прошивки платы. */ +#endif /* Завершает проверку размещения таблицы векторов. */ +#endif /* Завершает аппаратный профиль HOPE STM32G474VET6. */ diff --git a/c/set-protocol/ports/stm32g474-hope/boot_port.h b/c/set-protocol/ports/stm32g474-hope/boot_port.h new file mode 100644 index 0000000..dd9d455 --- /dev/null +++ b/c/set-protocol/ports/stm32g474-hope/boot_port.h @@ -0,0 +1,6 @@ +#ifndef HOPE_BOOT_PORT_H /* Защищает интерфейс входа в существующий CANdle boot от повторного включения. */ +#define HOPE_BOOT_PORT_H /* Общий USB SET-адаптер использует этот профиль вместо несовместимого RB USB boot. */ +#include /* Определяет тип миллисекундного времени отложенного reset. */ +void g474_request_boot(uint32_t now); /* Сохраняет CANB в исключённом слове SRAM и назначает reset через 500 мс. */ +void g474_reset_poll(uint32_t now); /* Выполняет назначенный reset из main после отправки ответа USB. */ +#endif /* Завершает интерфейс входа HOPE в найденный загрузчик CANdle. */ diff --git a/c/set-protocol/ports/stm32g474-hope/boot_request.c b/c/set-protocol/ports/stm32g474-hope/boot_request.c new file mode 100644 index 0000000..73a5909 --- /dev/null +++ b/c/set-protocol/ports/stm32g474-hope/boot_request.c @@ -0,0 +1,16 @@ +#include "boot_port.h" /* Сохраняет общий API отложенного reset для USB SET v2 и main эмулятора. */ +#include "board_config.h" /* Получает адрес и magic CANB, совпадающие с исходным профилем CANdle. */ +#include "stm32g4xx_hal.h" /* Предоставляет барьер памяти Cortex-M4 и NVIC_SystemReset. */ +static uint32_t reset_at; /* Содержит срок reset в миллисекундах HAL с арифметикой по модулю 2^32. */ +static uint8_t reset_pending; /* Разделяет отсутствие запроса и допустимый срок reset_at=0 после переполнения. */ +void g474_request_boot(uint32_t now) /* Вызывается только после корректного адресного запроса USB SET v2. */ +{ /* Маркер живёт вне RW/ZI и стека обоих профилей scatter HOPE. */ + *(volatile uint32_t *)(uintptr_t)HOPE_BOOT_REQUEST_ADDRESS = HOPE_BOOT_REQUEST_MAGIC; /* Записывает CANB именно в SRAM 0x20013FFC, а не в TAMP->BKP0R RB-загрузчика. */ + __DSB(); /* Завершает запись SRAM до любого последующего системного сброса. */ + reset_at = now + 500u; /* Даёт USB CDC 500 мс для передачи положительного ответа до переподключения. */ + reset_pending = 1u; /* Публикует запрос после подготовки его маркера и времени. */ +} /* Завершает подготовку входа, не прерывая текущую передачу ответа. */ +void g474_reset_poll(uint32_t now) /* Вызывается главным циклом независимо от текущей активности транспорта. */ +{ /* Знаковая разность корректна при переполнении HAL tick на коротком интервале 500 мс. */ + if (reset_pending && (int32_t)(now - reset_at) >= 0) NVIC_SystemReset(); /* Передаёт управление существующему загрузчику только после завершения задержки. */ +} /* Завершает обслуживание отложенного reset без собственных операций Flash. */ diff --git a/c/set-protocol/ports/stm32g474-hope/docs/HOPE_G474VE_schematic_20250414.pdf b/c/set-protocol/ports/stm32g474-hope/docs/HOPE_G474VE_schematic_20250414.pdf new file mode 100644 index 0000000..0852057 Binary files /dev/null and b/c/set-protocol/ports/stm32g474-hope/docs/HOPE_G474VE_schematic_20250414.pdf differ diff --git a/c/set-protocol/ports/stm32g474-hope/igbt_realtime_port.c b/c/set-protocol/ports/stm32g474-hope/igbt_realtime_port.c new file mode 100644 index 0000000..98da110 --- /dev/null +++ b/c/set-protocol/ports/stm32g474-hope/igbt_realtime_port.c @@ -0,0 +1,203 @@ +#include "igbt_realtime_port.h" /* Получает интерфейс регистрации в уже существующем сервере эмуляторов. */ +#include "set_igbt_realtime.h" /* Использует отдельную карту версии 4 с целыми наносекундами. */ +#include "stm32g4xx_hal.h" /* Предоставляет CMSIS-регистры G474, GPIO и безопасную настройку NVIC. */ +#include /* Обнуляет аппаратный снимок перед публикацией диагностических значений. */ +typedef struct { /* Однозначная привязка входа и выхода каждого из восьми аппаратных каналов. */ + GPIO_TypeDef *input, *output; uint16_t input_pin, output_pin; /* Порты и маски ровно одного физического вывода, сверенные с заводской схемой HOPE. */ + uint8_t input_af, output_af, event, index; TIM_TypeDef *timer; IRQn_Type irq; /* Альтернативные функции, внешний EEV и индекс D/E/F либо обычный TIM с собственным IRQ. */ +} hope_igbt_pin; /* Каждый канал имеет отдельный счётчик времени и не делит задержку с другим каналом. */ +static const hope_igbt_pin pins[8] = { /* Выбирает свободные J5/J6, сохраняя USB, CH340/USART1 и все три заводских CAN. */ + {GPIOB, GPIOB, GPIO_PIN_6, GPIO_PIN_14, 13, 13, 4, 3, 0, HRTIM1_TIMD_IRQn}, /* Канал 1: Vin J6-7/PB6 EEV4 → Vstat/TX J5-26/PB14 HRTIM D1; контакты сверены визуально с заводской схемой. */ + {GPIOB, GPIOC, GPIO_PIN_7, GPIO_PIN_8, 13, 3, 3, 4, 0, HRTIM1_TIME_IRQn}, /* Канал 2: Vin J6-8/PB7 EEV3 → Vstat/TX J6-21/PC8 HRTIM E1; дисплей уступает CS в режиме IGBT. */ + {GPIOB, GPIOC, GPIO_PIN_3, GPIO_PIN_6, 13, 13, 9, 5, 0, HRTIM1_TIMF_IRQn}, /* Канал 3: Vin J6-12/PB3 EEV9 → Vstat/TX J6-23/PC6 HRTIM F1; SWD PA13/14 сохранён, SWO не используется. */ + {GPIOD, GPIOD, GPIO_PIN_3, GPIO_PIN_4, 2, 2, 0, 0, TIM2, TIM2_IRQn}, /* Канал 4: Vin J6-15/PD3 TIM2_CH1 → Vstat/TX J6-16/PD4 TIM2_CH2. */ + {GPIOB, GPIOB, GPIO_PIN_4, GPIO_PIN_5, 2, 2, 0, 0, TIM3, TIM3_IRQn}, /* Канал 5: Vin J6-9/PB4 TIM3_CH1 → Vstat/TX J6-10/PB5 TIM3_CH2. */ + {GPIOD, GPIOD, GPIO_PIN_12, GPIO_PIN_13, 2, 2, 0, 0, TIM4, TIM4_IRQn}, /* Канал 6: Vin J6-27/PD12 TIM4_CH1 → Vstat/TX J6-28/PD13 TIM4_CH2. */ + {GPIOA, GPIOA, GPIO_PIN_0, GPIO_PIN_1, 2, 2, 0, 0, TIM5, TIM5_IRQn}, /* Канал 7: Vin J5-5/PA0 TIM5_CH1 → Vstat/TX J5-6/PA1 TIM5_CH2. */ + {GPIOA, GPIOA, GPIO_PIN_2, GPIO_PIN_3, 9, 9, 0, 0, TIM15, TIM1_BRK_TIM15_IRQn}, /* Канал 8: Vin J5-7/PA2 TIM15_CH1 → Vstat/TX J5-8/PA3 TIM15_CH2; USART1 PA9/10 свободен от таймеров. */ +}; /* Завершает восемь независимых маршрутов с одной общей землёй J5-29/J6-30 и логикой 3,3 В. */ +static const uint32_t reset_events[3] = {HRTIM_RSTR_EXTEVNT4, HRTIM_RSTR_EXTEVNT3, HRTIM_RSTR_EXTEVNT9}; /* Использует маски reset из CMSIS: EEV4/3/9 находятся в битах 12/11/17, а не рядом с capture. */ +static const uint32_t capture_events[3] = {HRTIM_CPT1CR_EXEV4CPT, HRTIM_CPT1CR_EXEV3CPT, HRTIM_CPT1CR_EXEV9CPT}; /* Маски CPT1 берутся из CMSIS независимо от расположения reset-битов тех же внешних событий. */ +static set_igbt_rt service; static set_emu_server *server; /* Хранит один аппаратный сервис и ссылку на текущий режим существующего MCU-сервера. */ +static set_igbt_rt_config applied; static uint8_t owned, pulse_mask, dll_ready; /* Применённые времена, владение выводами, выполняемые TX и результат калибровки HRTIM. */ +static volatile uint16_t edge_count[8], overruns[8]; /* ISR изменяют только диагностику; фронты выходов формирует исключительно оборудование. */ +static uint8_t busy(void); /* Применение профиля предварительно проверяет занятость физического TX без обрыва импульса. */ +static uint32_t ticks(uint32_t ns, uint32_t multiplier) /* Переводит наносекунды в кванты таймера от подтверждённых 160 МГц. */ +{ /* Максимум 60000*160*32 укладывается в uint32_t, поэтому вычисление не требует деления uint64_t на Cortex-M4. */ + return (ns * 160u * multiplier + 500u) / 1000u; /* Округляет к ближайшему кванту: 6,25 нс у TIM и до 0,1953125 нс у HRTIM ×32. */ +} /* Завершает детерминированное преобразование единиц без системных задержек. */ +static void gpio_mode(GPIO_TypeDef *port, uint16_t pin, uint32_t mode, uint32_t af, uint32_t pull) /* Настраивает единственный принадлежащий каналу физический вывод. */ +{ /* Остальные биты GPIO, включая UART/CAN/SWD, остаются без изменения. */ + GPIO_InitTypeDef gpio = {0}; gpio.Pin = pin; gpio.Mode = mode; gpio.Alternate = af; /* Явно задаёт маску, направление и альтернативную функцию выбранного контакта. */ + gpio.Pull = pull; gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(port, &gpio); /* Высокая скорость фронтов нужна для импульсов короче микросекунды. */ +} /* Завершает настройку контакта штатным HAL, не включая таймер. */ +static unsigned selected(void *context) /* Общий протокол разрешает аппаратное управление только в выбранном режиме IGBT. */ +{ /* Контекст сервиса статический, режим читает существующий сервер платы. */ + (void)context; return server->config[3] == 2; /* Значение 2 совпадает с каталогом MCU и регистром выбора эмулятора 0x1219. */ +} /* Завершает проверку маршрута без побочного действия. */ +static void stop_channel(unsigned ch) /* Останавливает один независимый аппаратный маршрут перед его перенастройкой. */ +{ /* Не изменяет счётчики и состояние остальных семи каналов. */ + const hope_igbt_pin *p = &pins[ch]; /* Читает единственную каноническую таблицу привязки выбранного канала. */ + if (p->timer) { p->timer->SMCR = 0; p->timer->DIER = 0; p->timer->CR1 = 0; p->timer->CCER = 0; } /* Запрещает внешний пуск, IRQ, счёт и альтернативный выход обычного TIM. */ + else { HRTIM_Timerx_TypeDef *t = &HRTIM1->sTimerxRegs[p->index]; t->RSTxR = 0; t->TIMxDIER = 0; HRTIM1->sMasterRegs.MCR &= ~(1u << (17u + p->index)); HRTIM1->sCommonRegs.ODISR = 1u << (2u * p->index); } /* Отключает EEV, счётчик и физический выход HRTIM D/E/F. */ + HAL_GPIO_WritePin(p->output, p->output_pin, GPIO_PIN_RESET); /* Заранее записывает ноль в ODR, чтобы переход из AF не создавал положительного импульса. */ + gpio_mode(p->output, p->output_pin, GPIO_MODE_OUTPUT_PP, 0, GPIO_NOPULL); /* Явно удерживает выход в нуле даже при ранее инвертированном ACK. */ + NVIC_ClearPendingIRQ(p->irq); /* Убирает отложенное диагностическое прерывание выключенного таймера. */ + pulse_mask &= (uint8_t)~(1u << ch); /* Снимает занятость только остановленного физического TX. */ +} /* Завершает останов одного маршрута без воздействия на остальные таймеры. */ +static void stop(void *context) /* Безусловно снимает аппаратные триггеры и уровни всех принадлежащих IGBT выходов. */ +{ /* Не касается дисплея и чужих GPIO, пока аппаратный IGBT ещё не захватывал выводы. */ + unsigned i; (void)context; if (!owned) return; /* Первое чтение состояния другого режима не меняет аппаратную конфигурацию платы. */ + for (i = 0; i < 8; ++i) stop_channel(i); /* Безусловная команда останова отключает все восемь маршрутов. */ + applied.enabled = 0; /* Следующее применение того же профиля обязано заново вооружить таймеры после явного останова. */ +} /* Завершает останов без ожидания millis или ответа GUI. */ +static void event_config(unsigned event, unsigned edges) /* Выбирает фронты на аппаратном входе EEV без вызова ISR для запуска ACK. */ +{ /* События 1…5 находятся в EECR1, события 6…10 — в EECR2; каждый блок занимает шесть бит по RM0440. */ + volatile uint32_t *reg = event <= 5 ? &HRTIM1->sCommonRegs.EECR1 : &HRTIM1->sCommonRegs.EECR2; /* Выбирает правильный регистр по номеру внешнего события. */ + unsigned shift = ((event - 1u) % 5u) * 6u; uint32_t mask = 63u << shift; /* Выделяет source/polarity/sensitivity/fast одного EEV, сохраняя остальные события. */ + uint32_t sensitivity = edges == 1 ? 1u : edges == 2 ? 2u : 3u; /* Кодирует ON, OFF или оба фронта; source=0 выбирает GPIO соответствующей AF. */ + *reg = (*reg & ~mask) | (sensitivity << (shift + 3u)); /* Использует синхронный путь без цифрового фильтра; задержка входа учитывается измеренной компенсацией. */ +} /* Завершает настройку входного события без программной задержки. */ +static void hrtim_config(unsigned ch, const set_igbt_rt_config *cfg) /* Настраивает один самостоятельный HRTIM D/E/F при отключённом физическом выходе. */ +{ /* Начало и конец каждого ACK либо TX задаются двумя аппаратными compare одного счётчика. */ + const hope_igbt_pin *p = &pins[ch]; const set_igbt_rt_channel *c = &cfg->channel[ch]; HRTIM_Timerx_TypeDef *t = &HRTIM1->sTimerxRegs[p->index]; /* Выбирает канал и его применяемые наносекундные параметры. */ + uint32_t delay = c->edges == 2 ? c->off_delay : c->on_delay, width = c->edges == 2 ? c->off_width : c->on_width; /* При обоих фронтах времена уже проверены на равенство; одиночный OFF использует отдельные задания. */ + uint32_t multiplier = 32, prescaler = 0, start, duration, end, period; unsigned hold = 0; /* Начинает с максимального разрешения HRTIM и при необходимости расширяет диапазон. */ + if (cfg->source) { delay = 50; width = c->tx_width; } /* Физический TX начинает импульс после короткого внутреннего запуска 50 нс; его ширина аппаратно равна заданию. */ + else { delay -= c->compensation; if (cfg->fault & (1u << ch)) { hold = c->fault_width == 0; if (!hold) width = c->fault_width; } } /* Учитывает измеренный входной тракт и выбранный конечный либо удерживаемый FAULT. */ + for (;;) { start = ticks(delay, multiplier); duration = ticks(width, multiplier); end = start + duration; period = end + 3u * multiplier; if (period <= 65503u || multiplier == 1) break; multiplier >>= 1; ++prescaler; } /* Умещает compare и запас три базовых такта в 16-битный счётчик, сохраняя максимально возможное разрешение. */ + t->TIMxCR = prescaler | HRTIM_TIMCR_RETRIG; t->PERxR = period; t->REPxR = 0; /* Выбирает одиночный повторно запускаемый цикл без фоновой периодической генерации. */ + t->CMP1xR = start; t->CMP2xR = end; t->CMP3xR = 0; t->CMP4xR = 0; /* Записывает точные точки начала и конца; неиспользуемые compare не участвуют в выходном crossbar. */ + t->SETx1R = HRTIM_SET1R_CMP1; t->RSTx1R = hold ? 0 : HRTIM_RST1R_CMP2 | HRTIM_RST1R_RESYNC | HRTIM_RST1R_PER; /* Удерживаемый FAULT сохраняет активный уровень до явного снятия, обычный ответ заканчивается compare 2. */ + t->OUTxR = (!cfg->source && (c->flags & 4)) ? HRTIM_OUTR_POL1 : 0; /* Инверсия ACK меняет электрическую полярность, не сдвигая аппаратные времена. */ + t->RSTx1R |= HRTIM_RST1R_SRT; /* Программно задаёт неактивное состояние внутреннего выходного триггера до подключения AF. */ + event_config(p->event, cfg->source ? 3u : c->edges); /* Настраивает вход захвата; в режиме генератора он может принимать фактический Vstat реального драйвера. */ + t->CPT1xCR = (c->flags & 1) ? capture_events[ch] : 0; t->TIMxDIER = (c->flags & 1) ? HRTIM_TIMDIER_CPT1IE : 0; /* Захват CPT1 фиксирует внешние фронты для диагностики; ISR не формирует ACK. */ + t->RSTxR = (!cfg->source && c->edges && c->mode == 0 && (c->flags & 3) == 3) ? reset_events[ch] : 0; /* Разрешает прямой аппаратный пуск только для включённого автоматического ACK. */ + t->TIMxICR = 0xFFFFFFFFu; t->CNTxR = period; /* Начинает на конце периода, чтобы разрешение счётчика не породило ложный ACK при включении. */ + HRTIM1->sMasterRegs.MCR |= 1u << (17u + p->index); HRTIM1->sCommonRegs.OENR = 1u << (2u * p->index); /* Разрешает отдельный счётчик и только его первый физический выход. */ + if (!cfg->source && (!(c->flags & 2) || c->mode == 1 || c->mode == 2 || c->mode == 3 || !c->edges)) { /* Постоянные режимы не должны случайно выдавать импульс по compare при конфигурации. */ + unsigned level = (c->flags & 2) && (c->mode == 2 || ((c->mode == 3 || !c->edges) && (c->flags & 4))); /* Принудительные 0/1 имеют электрический смысл; пропущенный ACK сохраняет полярность неактивного уровня. */ + HAL_GPIO_WritePin(p->output, p->output_pin, level ? GPIO_PIN_SET : GPIO_PIN_RESET); gpio_mode(p->output, p->output_pin, GPIO_MODE_OUTPUT_PP, 0, GPIO_NOPULL); /* Фиксирует постоянный уровень без подмены времён программным переключением. */ + } else gpio_mode(p->output, p->output_pin, GPIO_MODE_AF_PP, p->output_af, GPIO_NOPULL); /* Подключает аппаратный выход только после полного задания таймера и его неактивного состояния. */ +} /* Завершает аппаратную подготовку одного канала HRTIM. */ +static void tim_config(unsigned ch, const set_igbt_rt_config *cfg) /* Настраивает один обычный TIM2/3/4/5/15 с независимым счётчиком 160 МГц. */ +{ /* Канал 1 принимает фронт, канал 2 формирует ответ; IRQ используются только для диагностического счётчика захватов. */ + const hope_igbt_pin *p = &pins[ch]; const set_igbt_rt_channel *c = &cfg->channel[ch]; TIM_TypeDef *t = p->timer; /* Выбирает проверенные альтернативные функции входа и выхода этого TIM. */ + uint32_t delay = c->edges == 2 ? c->off_delay : c->on_delay, width = c->edges == 2 ? c->off_width : c->on_width; unsigned hold = 0; /* Обе полярности используют один аппаратный профиль, если разрешены одновременно. */ + uint32_t start, duration, output_mode; /* Хранит параметры compare в базовых тактах 6,25 нс. */ + if (cfg->source) { delay = 50; width = c->tx_width; } /* В режиме TX аппаратная ширина не зависит от момента доставки команды USB/UART. */ + else { delay -= c->compensation; if (cfg->fault & (1u << ch)) { hold = c->fault_width == 0; if (!hold) width = c->fault_width; } } /* Учитывает фактическую калибровку и сценарий ошибки ACK. */ + start = ticks(delay, 1); duration = ticks(width, 1); output_mode = hold ? 1u : 7u; /* Режим OC set удерживает FAULT; PWM2 выдаёт активный интервал от CCR2 до переполнения ARR. */ + t->CCMR1 = TIM_CCMR1_CC1S_0 | (4u << TIM_CCMR1_OC2M_Pos); /* Сначала принудительно сбрасывает OC2REF: удерживаемый FAULT не должен наследовать активный уровень предыдущего профиля. */ + t->CR1 = TIM_CR1_OPM | TIM_CR1_URS; t->PSC = 0; t->ARR = start + duration - 1u; t->CCR2 = start; /* Записывает одиночный цикл с точной аппаратной шириной duration тактов и без IRQ от программного update. */ + t->CCMR1 = TIM_CCMR1_CC1S_0 | (output_mode << TIM_CCMR1_OC2M_Pos); /* Канал 1 привязан к TI1, канал 2 — к требуемому аппаратному выходному режиму. */ + t->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | ((!cfg->source && (c->flags & 4)) ? TIM_CCER_CC2P : 0); /* Разрешает захват и выход с независимой электрической инверсией ACK. */ + if (cfg->source || c->edges == 3) t->CCER |= TIM_CCER_CC1P | TIM_CCER_CC1NP; else if (c->edges == 2) t->CCER |= TIM_CCER_CC1P; /* Диагностика захватывает оба фронта либо выбранный OFF; ON сохраняет обычную полярность. */ + if (t == TIM15) t->BDTR = TIM_BDTR_MOE; /* TIM15 требует разрешения главного выхода MOE, в отличие от TIM2/3/4/5. */ + t->EGR = TIM_EGR_UG; t->CNT = 0; t->SR = 0; /* Загружает делитель и period при отключённом выходе, затем удаляет технические события конфигурации. */ + t->DIER = (c->flags & 1) ? TIM_DIER_CC1IE : 0; /* Прерывания capture служат только счётчику; окончание ACK всегда выполняется счётчиком и OC. */ + t->SMCR = (!cfg->source && c->edges && c->mode == 0 && (c->flags & 3) == 3) ? TIM_SMCR_SMS_3 | (c->edges == 3 ? TIM_TS_TI1F_ED : TIM_TS_TI1FP1) : 0; /* Combined reset+trigger аппаратно запускает одиночный ответ на каждый разрешённый фронт. */ + if (!cfg->source && (!(c->flags & 2) || c->mode || !c->edges)) { /* Постоянные и пропущенные ответы обходят PWM, сохраняя требуемый электрический уровень. */ + unsigned level = (c->flags & 2) && (c->mode == 2 || ((c->mode == 3 || !c->edges) && (c->flags & 4))); /* ACK активен низким только в автоматическом/пропущенном режиме; принудительный уровень трактуется буквально. */ + HAL_GPIO_WritePin(p->output, p->output_pin, level ? GPIO_PIN_SET : GPIO_PIN_RESET); gpio_mode(p->output, p->output_pin, GPIO_MODE_OUTPUT_PP, 0, GPIO_NOPULL); /* Выставляет постоянный уровень, не создавая периодическую генерацию. */ + } else gpio_mode(p->output, p->output_pin, GPIO_MODE_AF_PP, p->output_af, GPIO_NOPULL); /* Передаёт физический выход полностью подготовленному аппаратному PWM/OC. */ +} /* Завершает конфигурацию одного обычного независимого таймера. */ +static void levels(void *context, uint8_t mask) /* Удерживает ручные уровни физического TX без изменения записанной длительности одиночного импульса. */ +{ /* Вызывается только при остановленных одиночных TX; общая карта предварительно проверяет занятость и разрешения. */ + unsigned i; (void)context; for (i = 0; i < 8; ++i) { /* Обрабатывает каждый физический выход независимо от типа таймера. */ + HAL_GPIO_WritePin(pins[i].output, pins[i].output_pin, (mask & (1u << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET); /* Подготавливает требуемый уровень в ODR до смены AF. */ + gpio_mode(pins[i].output, pins[i].output_pin, GPIO_MODE_OUTPUT_PP, 0, GPIO_NOPULL); /* Удерживаемый уровень не зависит от того, на каком значении остановился счётчик PWM. */ + } /* Завершает запись восьми постоянных уровней. */ +} /* Завершает ручное управление уровнем без busy-wait или задержки HAL. */ +static unsigned apply(void *context, const set_igbt_rt_config *cfg) /* Проверяет аппаратные предпосылки и применяет весь согласованный профиль. */ +{ /* До первого изменения GPIO обнаруживает отказ DLL и неверное дерево часов. */ + unsigned i, full; (void)context; if (SystemCoreClock != 160000000u || HAL_RCC_GetPCLK1Freq() != 80000000u || HAL_RCC_GetPCLK2Freq() != 160000000u || !dll_ready) return 4; /* Пересчёт наносекунд допустим только для подтверждённой конфигурации 160/80/160 МГц и готовой HRTIM DLL. */ + if (owned && applied.source && busy()) return 6; /* Применение конфигурации не обрывает выполняемый аппаратный одиночный TX; явная команда останова остаётся доступной. */ + if (owned && applied.source) for (i = 0; i < 8; ++i) if (pins[i].output->IDR & pins[i].output_pin) return 6; /* Удерживаемый TX=1 также блокирует перенастройку: перевод AF/GPIO не должен создавать лишний фронт настоящему драйверу. */ + full = !owned || !applied.enabled || cfg->source != applied.source; /* Все маршруты перенастраиваются только после останова либо при смене физического направления ACK/TX. */ + if (full) stop(0); /* Смена направления переводит все контакты в ноль до подключения новых функций. */ + owned = 1; /* Последующие команды останова вправе управлять только уже выделенными IGBT выводами. */ + for (i = 0; i < 8; ++i) if (full || memcmp(&cfg->channel[i], &applied.channel[i], sizeof(cfg->channel[i])) || ((cfg->fault ^ applied.fault) & (1u << i))) { /* Поканальное применение оставляет неизменённые семь аппаратных маршрутов работающими. */ + if (!full) stop_channel(i); /* Изменение выбранного профиля сбрасывает только его незавершённый ACK/FAULT, сохраняя остальные каналы. */ + gpio_mode(pins[i].input, pins[i].input_pin, GPIO_MODE_AF_PP, pins[i].input_af, GPIO_PULLDOWN); /* Неподключённый Vin имеет нулевой уровень; внешние сигналы используют только логику 3,3 В. */ + if (pins[i].timer) tim_config(i, cfg); else hrtim_config(i, cfg); /* Выбирает аппаратную реализацию без программного отсчёта наносекундных сроков. */ + NVIC_SetPriority(pins[i].irq, 5); NVIC_ClearPendingIRQ(pins[i].irq); NVIC_EnableIRQ(pins[i].irq); /* Диагностика фронтов ниже критических аппаратных событий; приоритет не влияет на выходные compare. */ + } /* Завершает подготовку всех восьми независимых каналов. */ + applied = *cfg; /* Обновляет аппаратную копию только после настройки всех действительно изменившихся каналов. */ + if (cfg->source) levels(0, (uint8_t)cfg->tx); /* Генератор после применения держит заданные постоянные уровни до отдельной команды импульса. */ + return 0; /* Подтверждает работу оборудования только после полной конфигурации. */ +} /* Завершает аппаратное применение без миллисекундного шага модели. */ +static uint8_t busy(void) /* Проверяет фактическое окончание аппаратных одиночных TX. */ +{ /* HRTIM сохраняет CEN в single-shot, поэтому окончание определяется аппаратным repetition flag, а не этим битом. */ + unsigned i; for (i = 0; i < 8; ++i) if (pulse_mask & (1u << i)) { /* Просматривает только реально запущенные одиночные импульсы генератора. */ + unsigned done = pins[i].timer ? !(pins[i].timer->CR1 & TIM_CR1_CEN) : !!(HRTIM1->sTimerxRegs[pins[i].index].TIMxISR & HRTIM_TIMISR_REP); /* Обычный OPM сбрасывает CEN, HRTIM фиксирует конец единственного периода. */ + if (done) pulse_mask &= (uint8_t)~(1u << i); /* Снимает занятость по аппаратному событию, независимо от задержки USB/UART и частоты GUI. */ + } /* Завершает чтение состояния аппаратных генераторов. */ + return pulse_mask; /* Возвращает оставшиеся активные биты без запуска нового импульса. */ +} /* Завершает обслуживание только статуса, не формы сигнала. */ +static unsigned pulse(void *context, uint8_t mask) /* Запускает одиночные TX на выбранных независимых таймерах. */ +{ /* Все каналы предварительно проверяются до первого физического запуска. */ + unsigned i; uint32_t saved, hrtim_reset = 0; (void)context; if (busy() & mask) return 6; /* Повторный пуск выполняемого канала не обрывает его текущий импульс. */ + for (i = 0; i < 8; ++i) if ((mask & (1u << i)) && (pins[i].output->IDR & pins[i].output_pin)) return 6; /* Требует фактический низкий TX на каждом выбранном контакте, включая удерживаемый вручную уровень. */ + saved = __get_PRIMASK(); __disable_irq(); /* Делает последовательность подготовки и запуска короткой и не прерываемой диагностическими IRQ. */ + for (i = 0; i < 8; ++i) if (mask & (1u << i)) { /* Перезапускает только явно выбранные биты, сохраняя работу остальных каналов. */ + const hope_igbt_pin *p = &pins[i]; /* Выбирает аппаратный генератор данного физического TX. */ + if (p->timer) { p->timer->CR1 &= ~TIM_CR1_CEN; p->timer->CNT = 0; p->timer->SR = 0; } /* Подготавливает начало PWM2 в нуле, удаляя только события выбранного таймера. */ + else { HRTIM_Timerx_TypeDef *t = &HRTIM1->sTimerxRegs[p->index]; t->TIMxICR = HRTIM_TIMICR_REPC; t->RSTx1R |= HRTIM_RST1R_SRT; } /* Сбрасывает прежнее окончание single-shot и внутренний выход до подключения AF. */ + gpio_mode(p->output, p->output_pin, GPIO_MODE_AF_PP, p->output_af, GPIO_NOPULL); /* Подключает неактивный аппаратный выход до начала отсчёта импульса. */ + pulse_mask |= (uint8_t)(1u << i); /* Помечает канал занятым перед аппаратным стартом, исключая повторный запуск. */ + if (!p->timer) hrtim_reset |= 1u << (9u + p->index); /* Собирает общий software-reset HRTIM, не запуская первый канал во время настройки остальных GPIO. */ + } /* Все выбранные выходы уже подключены к неактивным таймерам до первого физического старта. */ + __DSB(); /* Завершает записи конфигурации и GPIO до аппаратного запуска счётчиков. */ + if (hrtim_reset) HRTIM1->sCommonRegs.CR2 = hrtim_reset; /* Каналы HRTIM D/E/F запускаются одной записью без межканального цикла GPIO. */ + for (i = 3; i < 8; ++i) if (mask & (1u << i)) pins[i].timer->CR1 |= TIM_CR1_CEN; /* Независимые TIM стартуют короткой последовательностью записей; общий наносекундный фронт между разными периферийными блоками не обещается. */ + __set_PRIMASK(saved); return 0; /* Восстанавливает прежнее состояние прерываний сразу после запуска аппаратных импульсов. */ +} /* Завершает команду, не ожидая длительность TX на CPU. */ +static void sample(void *context, set_igbt_rt_snapshot *snapshot) /* Снимает реальные уровни контактов и аппаратную занятость. */ +{ /* Короткие ACK могут уже закончиться; накопленные capture IRQ позволяют видеть факт внешних фронтов. */ + unsigned i; uint32_t saved; (void)context; memset(snapshot, 0, sizeof(*snapshot)); /* Начинает согласованный снимок с нулевых масок. */ + snapshot->busy = owned ? busy() : 0; saved = __get_PRIMASK(); __disable_irq(); /* Не допускает изменения поканальных счётчиков во время копирования диагностического снимка. */ + for (i = 0; i < 8; ++i) { /* Преобразует физическую разводку в прежние биты 0…7 общего протокола. */ + unsigned in = !!(pins[i].input->IDR & pins[i].input_pin), out = !!(pins[i].output->IDR & pins[i].output_pin); /* Читает электрические уровни, включая реальную инверсию ACK. */ + if (owned && service.active.enabled) { if (applied.source ? out : in) snapshot->tx |= (uint8_t)(1u << i); if (applied.source ? in : out) snapshot->rx |= (uint8_t)(1u << i); } /* В генераторе выход означает TX, а вход принимает Vstat настоящего драйвера; в эмуляторе направления обратные. */ + snapshot->count[i] = edge_count[i]; snapshot->overrun[i] = overruns[i]; /* Публикует только диагностические счётчики ISR, не выдавая их за измерение ширины импульса. */ + } /* Завершает копирование одного согласованного снимка. */ + __set_PRIMASK(saved); /* Возвращает прежнее разрешение прерываний после короткой критической секции. */ +} /* Завершает чтение без изменения сигналов. */ +static void clear(void *context) /* Очищает диагностические счётчики без остановки аппаратной генерации. */ +{ /* Сброс не меняет compare, разрешение выходов и текущий Vin. */ + unsigned i; uint32_t saved = __get_PRIMASK(); (void)context; __disable_irq(); /* Защищает все восемь пар счётчиков от конкурентного capture IRQ. */ + for (i = 0; i < 8; ++i) { edge_count[i] = 0; overruns[i] = 0; } /* Устанавливает новый нуль отсчёта диагностики. */ + __set_PRIMASK(saved); /* Восстанавливает состояние прерываний вызывающего контекста. */ +} /* Завершает диагностический сброс без формирования фронта. */ +static void capture_irq(unsigned ch) /* Обслуживает только факт захвата внешнего фронта данного аппаратного канала. */ +{ /* Ни задержка ACK, ни ширина импульса здесь не вычисляются и не переключаются. */ + if (pins[ch].timer) { TIM_TypeDef *t = pins[ch].timer; uint32_t status = t->SR; /* Сохраняет флаги до чтения CCR1, которое подтверждает capture. */ + if (status & TIM_SR_CC1IF) { (void)t->CCR1; ++edge_count[ch]; if (status & TIM_SR_CC1OF) ++overruns[ch]; t->SR = ~TIM_SR_CC1OF; } /* Отмечает потерю capture при слишком частых фронтах, не скрывая диагностическую перегрузку CPU. */ + } else { HRTIM_Timerx_TypeDef *t = &HRTIM1->sTimerxRegs[pins[ch].index]; if (t->TIMxISR & HRTIM_TIMISR_CPT1) { t->TIMxICR = HRTIM_TIMICR_CPT1C; ++edge_count[ch]; } } /* Для HRTIM подтверждает CPT1; выходной crossbar уже сработал независимо от времени входа в ISR. */ +} /* Завершает диагностику фронта без программного воздействия на таймерные сроки. */ +void HRTIM1_TIMD_IRQHandler(void) { capture_irq(0); } /* Привязывает вектор HRTIM D к каналу 1, вход PB6. */ +void HRTIM1_TIME_IRQHandler(void) { capture_irq(1); } /* Привязывает вектор HRTIM E к каналу 2, вход PB7. */ +void HRTIM1_TIMF_IRQHandler(void) { capture_irq(2); } /* Привязывает вектор HRTIM F к каналу 3, вход PB3. */ +void TIM2_IRQHandler(void) { capture_irq(3); } /* Привязывает независимый TIM2 к каналу 4, вход PD3. */ +void TIM3_IRQHandler(void) { capture_irq(4); } /* Привязывает независимый TIM3 к каналу 5, вход PB4. */ +void TIM4_IRQHandler(void) { capture_irq(5); } /* Привязывает независимый TIM4 к каналу 6, вход PD12. */ +void TIM5_IRQHandler(void) { capture_irq(6); } /* Привязывает независимый TIM5 к каналу 7, вход PA0. */ +void TIM1_BRK_TIM15_IRQHandler(void) { capture_irq(7); } /* Общий вектор используется только TIM15; TIM1 этот порт не включает. */ +void hope_igbt_realtime_init(set_emu_server *instance) /* Запускается после настройки PLL и до первого обслуживания UART/CAN/USB. */ +{ /* Инициализация таймерных часов не включает физические выходы. */ + static const set_igbt_rt_port port = {selected, apply, pulse, levels, stop, sample, clear}; unsigned i; uint32_t began; /* Связывает переносимый сервис с единственным набором аппаратных callbacks. */ + server = instance; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /* Открывает только необходимые порты, сохраняя их направления до явного применения. */ + __HAL_RCC_TIM2_CLK_ENABLE(); __HAL_RCC_TIM3_CLK_ENABLE(); __HAL_RCC_TIM4_CLK_ENABLE(); __HAL_RCC_TIM5_CLK_ENABLE(); __HAL_RCC_TIM15_CLK_ENABLE(); __HAL_RCC_HRTIM1_CLK_ENABLE(); /* Все восемь независимых счётчиков получают своё штатное тактирование от дерева 160 МГц. */ + HRTIM1->sCommonRegs.DLLCR = HRTIM_DLLCR_CAL | HRTIM_DLLCR_CALEN | HRTIM_DLLCR_CALRTE_0; began = HAL_GetTick(); /* Запускает и периодически поддерживает DLL; частота её обслуживания не формирует импульсы на CPU. */ + while (!(HRTIM1->sCommonRegs.ISR & HRTIM_ISR_DLLRDY) && HAL_GetTick() - began < 10u) {} /* Ограничивает ожидание готовности DLL десятью миллисекундами при включённом SysTick. */ + dll_ready = !!(HRTIM1->sCommonRegs.ISR & HRTIM_ISR_DLLRDY); set_igbt_rt_init(&service, &port, 0); /* Отказ DLL оставляет сервис читаемым, но блокирует применение точного профиля кодом аппаратной ошибки. */ + for (i = 0; i < server->map.count; ++i) if (server->regions[i].base == SET_EMU_IGBT_BASE) { /* Заменяет существующий регион до первого транспортного запроса, сохраняя адрес и остальные сервисы. */ + server->regions[i].version = 4; server->regions[i].context = &service; server->regions[i].read = set_igbt_rt_read; server->regions[i].write = set_igbt_rt_write; /* Общие RTU, SET v2 и CAN используют один аппаратный экземпляр без копии протокола. */ + } /* Завершает регистрацию окна IGBT 0x1400…0x146F версии 4. */ +} /* Завершает аппаратную регистрацию без автоматического включения модели. */ +void hope_igbt_realtime_poll(void) /* Вызывается после миллисекундного шага только для контроля владения режимом. */ +{ /* Аппаратная генерация уже идёт независимо от частоты вызова этой функции. */ + if (owned && !selected(0)) { stop(0); service.active.enabled = service.staged.enabled = 0; service.active.tx = service.staged.tx = 0; owned = 0; } /* Смена режима выключает физический IGBT в том же проходе, в котором общий сервер применил новый режим. */ +} /* Завершает контроль режима без программного формирования ACK или TX. */ diff --git a/c/set-protocol/ports/stm32g474-hope/igbt_realtime_port.h b/c/set-protocol/ports/stm32g474-hope/igbt_realtime_port.h new file mode 100644 index 0000000..502b159 --- /dev/null +++ b/c/set-protocol/ports/stm32g474-hope/igbt_realtime_port.h @@ -0,0 +1,6 @@ +#ifndef HOPE_IGBT_REALTIME_PORT_H /* Исключает повторное объявление привязки наносекундного IGBT к HOPE. */ +#define HOPE_IGBT_REALTIME_PORT_H /* Отделяет аппаратные таймеры от общего миллисекундного сервера. */ +#include "set_emu_server.h" /* Передаёт существующую карту регистров без нового транспорта или копии сервера. */ +void hope_igbt_realtime_init(set_emu_server *); /* Подменяет окно IGBT до первого обращения к карте; выходы остаются выключенными. */ +void hope_igbt_realtime_poll(void); /* Останавливает таймеры при выходе из режима IGBT; формы импульсов основной цикл не обслуживает. */ +#endif /* Завершает интерфейс аппаратного порта HOPE. */ diff --git a/c/set-protocol/ports/stm32g474-hope/transport.h b/c/set-protocol/ports/stm32g474-hope/transport.h new file mode 100644 index 0000000..65830ca --- /dev/null +++ b/c/set-protocol/ports/stm32g474-hope/transport.h @@ -0,0 +1,9 @@ +#ifndef HOPE_TRANSPORT_H /* Исключает повторное объявление транспорта HOPE при включении общего UART. */ +#define HOPE_TRANSPORT_H /* Сохраняет одинаковый poll API у всех аппаратных портов эмулятора. */ +#include /* Объявляет миллисекундное время и диагностические счётчики фиксированной ширины. */ +extern volatile uint32_t uart_errors, uart_overflows, can_timeouts, can_overflows; /* Показывает ошибки HAL, потери очереди UART и отказы CAN в Watch. */ +void transport_init(void); /* Инициализирует USART1 PA9/PA10 и штатный FDCAN1 PD0/PD1 после настройки GPIO и часов по схеме HOPE. */ +void transport_uart_poll(uint32_t now); /* Обслуживает RTU/SETGUI v1/GAS; now передаётся в миллисекундах HAL_GetTick. */ +void transport_can_poll(uint32_t now); /* За один проход обрабатывает не более одного CAN RX и одного фрагмента TX. */ +void USART1_IRQHandler(void); /* Предоставляет startup G474 правильный обработчик RX/TX и ошибок выбранного UART. */ +#endif /* Завершает интерфейс транспорта HOPE. */ diff --git a/c/set-protocol/ports/stm32g474-periph/transport.c b/c/set-protocol/ports/stm32g474-periph/transport.c index 307f74f..cda4271 100644 --- a/c/set-protocol/ports/stm32g474-periph/transport.c +++ b/c/set-protocol/ports/stm32g474-periph/transport.c @@ -13,6 +13,15 @@ #include "board_config.h" #include "emulator.h" #include "stm32g4xx_hal.h" +#ifndef EMU_UART_INSTANCE /* Сохраняет USART2 у существующей Nucleo и позволяет HOPE выбрать USART1. */ +#define EMU_UART_INSTANCE USART2 /* Штатный порт Nucleo использует VCP на PA2/PA3. */ +#endif /* Экземпляр UART может быть явно задан аппаратным профилем другой платы G474. */ +#ifndef EMU_UART_IRQn /* Номер IRQ выбирается согласованно с экземпляром UART конкретной платы. */ +#define EMU_UART_IRQn USART2_IRQn /* Сохраняет прежний вектор существующей сборки G474RB. */ +#endif /* HOPE передаёт USART1_IRQn из своего board_config.h. */ +#ifndef SERIAL_UART_IRQ_HANDLER /* Сохраняет общий автомат UART при разных аппаратных экземплярах USART. */ +#define SERIAL_UART_IRQ_HANDLER USART2_IRQHandler /* Существующие порты F103/F407/G474RB сохраняют прежний вектор USART2. */ +#endif /* HOPE задаёт USART1_IRQHandler в конфигурации платы. */ static UART_HandleTypeDef uart; static FDCAN_HandleTypeDef can; static volatile uint8_t transmitting; @@ -21,13 +30,13 @@ volatile uint32_t uart_errors,uart_overflows,can_timeouts,can_overflows; void transport_init(void) { FDCAN_FilterTypeDef filter={0}; - uart.Instance=USART2; uart.Init.BaudRate=emu_uart_baud(); + uart.Instance=EMU_UART_INSTANCE; uart.Init.BaudRate=emu_uart_baud(); /* Выбирает физический UART платы и актуальную скорость общей конфигурации сервера. */ uart.Init.WordLength=UART_WORDLENGTH_8B; uart.Init.StopBits=UART_STOPBITS_1; uart.Init.Parity=UART_PARITY_NONE; uart.Init.Mode=UART_MODE_TX_RX; uart.Init.HwFlowCtl=UART_HWCONTROL_NONE; uart.Init.OverSampling=UART_OVERSAMPLING_16; uart.Init.ClockPrescaler=UART_PRESCALER_DIV1; if(HAL_UART_Init(&uart)!=HAL_OK) board_fatal(4); - HAL_NVIC_SetPriority(USART2_IRQn,6,0); HAL_NVIC_EnableIRQ(USART2_IRQn); + HAL_NVIC_SetPriority(EMU_UART_IRQn,6,0); HAL_NVIC_EnableIRQ(EMU_UART_IRQn); /* Приоритет 6 оставляет SysTick/USB доступными, а номер вектора соответствует USART1 HOPE либо USART2 Nucleo. */ can.Instance=FDCAN1; can.Init.ClockDivider=FDCAN_CLOCK_DIV1; can.Init.FrameFormat=FDCAN_FRAME_CLASSIC; can.Init.Mode=FDCAN_MODE_NORMAL; can.Init.AutoRetransmission=ENABLE; can.Init.TransmitPause=DISABLE; @@ -103,7 +112,7 @@ void transport_can_poll(uint32_t now) } /* HAL обслуживает TXE/TC и вызывает callback завершения; прикладной протокол в ISR не выполняется. */ -void USART2_IRQHandler(void) { HAL_UART_IRQHandler(&uart); } +void SERIAL_UART_IRQ_HANDLER(void) { HAL_UART_IRQHandler(&uart); } /* Передаёт RXNE/TXE/TC и ошибки в HAL только выбранного UART; имя вектора согласовано со startup платы. */ /* Вызывается HAL после TC: последний стоп-бит уже вышел на линию, можно отключить передатчик RS-485. * Также используется локально для возврата в приём, если запуск передачи завершился ошибкой. */ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *h) diff --git a/c/set-protocol/src/deif_xdi.c b/c/set-protocol/src/deif_xdi.c new file mode 100644 index 0000000..dc23a45 --- /dev/null +++ b/c/set-protocol/src/deif_xdi.c @@ -0,0 +1,185 @@ +#include "deif_xdi.h" /* Публичный ABI не зависит от Python, Kotlin, Qt или Android. */ +#include /* Фиксированные структуры копируются без динамической памяти. */ +#include /* Проверка конечности пользовательского масштаба предотвращает недопустимые показания. */ +#define DEIF_MAGIC 0x44454946U /* Метка DEIF отличает валидный caller-owned контекст. */ +#define DEIF_FIELDS 6U /* POWER, RPM, фактический угол, POWER%, RPM%, задание угла. */ +#define DEIF_QUEUE 16U /* Ограниченная очередь покрывает Boot-up, heartbeat и ответы без heap. */ +typedef struct { /* Привязка и последнее сообщение одного индикатора. */ + uint8_t selector[4]; /* SAM/DAM, индекс LE и подиндекс сохраняются в wire-порядке. */ + double scale; /* Множитель физической величины задаётся библиотекой прибора. */ + uint64_t seen; /* Монотонные миллисекунды последнего принятого объекта. */ + int32_t raw; /* Исходный I16 хранится без обратного округления показания. */ + unsigned bound, received, status; /* Привязка, наличие кадра и служебный статус I16. */ +} deif_binding; /* Внутренний layout не является частью публичного ABI. */ +typedef struct { /* Всё состояние принадлежит порту, часы и транспорт в ядре отсутствуют. */ + uint32_t magic, monitor_id; /* Метка контекста и точный CAN ID пассивного наблюдателя. */ + unsigned node, source, xdi, self_start, pdo, group, services; /* Профиль по DEIF 4189350066D. */ + unsigned active, nmt, heartbeat, accepted, brightness, palette, error, queued; /* Изменяемые коммуникационные параметры сеанса. */ + uint64_t started, last_hb, auto_at; /* Независимые сроки в монотонных миллисекундах. */ + deif_binding field[DEIF_FIELDS]; /* Каждый вход имеет собственные данные и срок свежести. */ + setp_deif_frame_t queue[DEIF_QUEUE]; /* Служебные кадры выдаются только один раз через poll. */ +} deif_state; /* Размер сообщает state_size, порты не повторяют эту структуру. */ +static const uint16_t bases[8] = {0x3420,0x3080,0x3000,0x3430,0x3090,0x3000,0x3500,0x3500}; /* Опубликованные семейства переменных и диммера. */ +static const uint8_t subs[8] = {2,2,2,2,2,7,2,3}; /* Фактическое значение, отдельное задание, яркость и палитра. */ +static deif_state *context(void *p) { /* Все публичные функции проверяют инициализацию состояния. */ + deif_state *s = (deif_state *)p; /* Порт выделяет выровненную память через uint64 либо direct ByteBuffer. */ + return s && s->magic == DEIF_MAGIC ? s : NULL; /* Невалидный указатель контекста не трактуется как работающий узел. */ +} /* Проверка не обращается к ОС. */ +static uint16_t le16(const uint8_t *p) { return (uint16_t)((uint16_t)p[0] | ((uint16_t)p[1] << 8)); } /* Единственная реализация little-endian U16. */ +static void put16(uint8_t *p, uint16_t v) { p[0]=(uint8_t)v; p[1]=(uint8_t)(v>>8); } /* Обратное преобразование принадлежит тому же C-кодеку. */ +static void put32(uint8_t *p, uint32_t v) { unsigned i; for(i=0;i<4;i++) p[i]=(uint8_t)(v>>(8U*i)); } /* SDO и EMCY используют младший байт первым. */ +static unsigned raw_status(int32_t raw) { return raw == -32768 ? 1U : raw == 32766 ? 2U : raw == 32767 ? 3U : 0U; } /* §2.1.2: три зарезервированных значения I16. */ +static int address(uint32_t id, unsigned node, unsigned dam) { /* Проверка адреса применяется одинаково в обоих GUI. */ + if(!node || node>127U) return 0; /* Нулевой адрес не является источником или получателем MPDO. */ + return dam ? (id==0x200U+node || id==0x300U+node || id==0x400U+node || id==0x500U+node) : (id==0x200U+node || id==0x27FU); /* RPDO1…4 либо SAM с исключением service broadcast. */ +} /* Номер получателя не подменяет источник SAM. */ +int setp_deif_version(void) { return 1; } /* Независимая версия расширения ABI. */ +size_t setp_deif_state_size(void) { return sizeof(deif_state); } /* Клиент не зависит от внутренних паддингов структуры. */ +int setp_deif_catalog(unsigned f, int32_t *o) { /* Каталог является единственным источником числовых индексов. */ + if(f>=8U || !o) return 0; /* Неизвестное поле не создаёт фиктивный объект. */ + o[0]=bases[f]; o[1]=subs[f]; o[2]=(f==0U ? 127 : f<6U ? -1 : 0); return 1; /* 127 означает неизвестную физическую единицу POWER, прочие разрешения заданы в десятичной степени. */ +} /* Тексты и локализация остаются в GUI-портах. */ +int setp_deif_selector(unsigned f,unsigned node,unsigned instance,unsigned dam,uint8_t *o) { /* Формирует четыре байта привязки из каталога. */ + if(f>=8U || !o || node<1U || node>127U || instance<1U || instance>(f<6U?15U:9U) || dam>1U) return 0; /* Проверяет границы Node, экземпляра и сетевой группы. */ + o[0]=(uint8_t)(node|(dam?128U:0U)); put16(o+1,(uint16_t)(bases[f]+instance)); o[3]=subs[f]; return 1; /* Индекс и режим MPDO собираются только здесь. */ +} /* В портах нет копии wire-разметки. */ +int setp_deif_inspect(uint32_t id,const uint8_t *d,size_t n,unsigned flags,int32_t *o) { /* Коды ошибок сохраняют причину для локализованной диагностики. */ + unsigned i,node,index,sub,instance; int field=-1; /* Промежуточные поля ограничены размерами Classic CAN. */ + if(!o || (!d && n)) return -1; /* Отсутствующий вход не разыменовывается. */ + memset(o,0,12U*sizeof(*o)); if(flags) return -1; /* EXT и RTR не интерпретируются как XDi STD data frames. */ + if(id>=0x701U && id<=0x77FU) { /* Heartbeat и Boot-up имеют отдельный формат DLC1. */ + o[1]=(int32_t)(id-0x700U); if(n!=1U) return -2; o[10]=d[0]; o[0]=2; /* Сохраняем Node-ID и исходный NMT-байт даже при неизвестном коде. */ + return d[0]==0U || d[0]==4U || d[0]==5U || d[0]==127U ? 2 : -3; /* Toggle-бит node guarding не снимается автоматически. */ + } /* Переменные и диммер разбираются следующим общим путём. */ + if(id<0x201U || id>0x57FU) return 0; if(n!=8U) return -4; /* Неизвестный COB-ID отделён от неправильного DLC MPDO. */ + node=d[0]&127U; index=le16(d+1); sub=d[3]; instance=index&15U; /* Семейства переменных имеют по пятнадцать экземпляров. */ + o[1]=(int32_t)node; o[2]=(int32_t)index; o[3]=(int32_t)sub; o[4]=(int16_t)le16(d+4); o[6]=(int32_t)instance; o[8]=(d[0]&128U)!=0; o[9]=(d[6]==0U && d[7]==0U); /* Метаданные не требуют повторного endian-разбора в Python или Kotlin. */ + if(!address(id,node,(unsigned)o[8])) return -5; /* Включает согласование источника SAM с COB-ID. */ + for(i=0;i<6U;i++) if((index&0xFFF0U)==bases[i] && instance && (sub==2U || sub==7U)) { field=(int)i; break; } /* Известные переменные разрешают фактическое значение и задание. */ + if(index>=0x3501U && index<=0x3509U && (sub==2U || sub==3U)) { o[0]=3; o[5]=sub==2U?6:7; o[4]=d[4]; return 3; } /* Диммер имеет U8, а не I16. */ + if(field<0) return -6; o[0]=1; o[5]=field; o[7]=(int32_t)raw_status(o[4]); return 1; /* Служебный I16 не становится физическим измерением. */ +} /* Ненулевые старшие байты отмечаются отдельно, приёмник их отклонит. */ +int setp_deif_make(unsigned f,unsigned node,unsigned instance,int32_t v,uint32_t id,unsigned dam,setp_deif_frame_t *o) { /* Сборка данных, яркости и Color для всех платформ. */ + if(!id) id=0x200U+node; /* Нулевой аргумент выбирает исходный RPDO1 без копии формулы в портах. */ + if(!o || !address(id,node,dam) || (f<6U?(v< -32768 || v>32767):(f==6U?(v<0 || v>100):(f!=7U || v<0 || v>2)))) return 0; /* Значения проверяются до сужения разрядности. */ + memset(o,0,sizeof(*o)); o->can_id=id; o->dlc=8; if(!setp_deif_selector(f,node,instance,dam,o->data)) return 0; /* Неизвестное поле или экземпляр не создаёт частичный кадр. */ + if(f<6U) put16(o->data+4,(uint16_t)v); else o->data[4]=(uint8_t)v; return 1; /* Старшие байты всегда нулевые согласно §3.2.1. */ +} /* Передача готового кадра остаётся обязанностью транспорта. */ +int setp_deif_master(unsigned node,const int32_t *v,uint32_t id,unsigned dam,unsigned angle_subindex,setp_deif_frame_t *o) { /* Цикл MASTER использует единственный каталог и единственную сборку MPDO. */ + static const unsigned order[5]={2,1,4,0,3}; unsigned i,f; if(!v || !o || (angle_subindex!=2U && angle_subindex!=7U)) return 0; /* Подиндекс азимута выбирается явно, неизвестные коды не подставляются автоматически. */ + for(i=0;i<5U;i++) { f=i==0U && angle_subindex==7U?5U:order[i]; if(!setp_deif_make(f,node,1,v[i],id,dam,&o[i])) return 0; } return 5; /* Все кадры сохраняют один Node-ID, режим и COB-ID. */ +} /* Неуспешный цикл не должен передаваться портом частично. */ +int setp_deif_service(unsigned kind,unsigned node,unsigned value,setp_deif_frame_t *o) { /* Готовые служебные кадры не собираются повторно в GUI. */ + if(!o || node>127U || kind>1U) return 0; memset(o,0,sizeof(*o)); /* Границы проверяются до сужения байтов. */ + if(!kind) { if(!node || (value!=0U && value!=4U && value!=5U && value!=127U)) return 0; o->can_id=0x700U+node; o->dlc=1; o->data[0]=(uint8_t)value; } /* Boot-up и heartbeat своего CANopen-узла. */ + else { if(value!=1U && value!=2U && value!=128U && value!=129U && value!=130U) return 0; o->dlc=2; o->data[0]=(uint8_t)value; o->data[1]=(uint8_t)node; } return 1; /* NMT допускает broadcast 0 и передаёт два байта в COB-ID 0. */ +} /* Отправка физическому или локальному получателю остаётся за портом. */ +int setp_deif_angle_command(const setp_deif_frame_t *a,setp_deif_frame_t *o) { /* Перевод фактического азимута в независимый set-point использует тот же каталог. */ + int32_t m[12]; if(!a || setp_deif_inspect(a->can_id,a->data,a->dlc,0,m)!=1 || (m[2]&0xFFF0)!=0x3000) return 0; return setp_deif_make(5,(unsigned)m[1],(unsigned)m[6],m[4],a->can_id,(unsigned)m[8],o); /* Источник, экземпляр и RAW не вычисляются повторно в Python. */ +} /* Это второй отдельный CAN-кадр, не подмена фактического объекта. */ +int setp_deif_selector_info(const uint8_t *s,int32_t *o) { /* Общий разбор пользовательского селектора для всех редакторов. */ + if(!s || !o || !(s[0]&127U)) return 0; o[0]=s[0]&127U; o[1]=le16(s+1); o[2]=s[3]; o[3]=(s[0]&128U)!=0; return 1; /* Текст HEX остаётся форматом настроек, wire-геометрия находится в C. */ +} /* Неизвестные библиотечные индексы могут быть явно привязаны пользователем. */ +int setp_deif_readdress(const uint8_t *s,unsigned node,unsigned mode,uint8_t *o) { /* Перенос старого профиля не требует wire-масок в приложении. */ + if(!s || !o || !node || node>127U || mode>2U) return 0; memcpy(o,s,4); o[0]=(uint8_t)(node|(mode==2U?(s[0]&128U):(mode?128U:0U))); return 1; /* Индекс и подиндекс сохраняются побайтно, включая ручные объекты библиотеки. */ +} /* Адресный байт меняется единственным общим правилом. */ +int setp_deif_route(unsigned node,unsigned dam,uint32_t id,unsigned op,uint32_t *o) { /* Общая настройка COB-ID не смешивается с физическим каналом приложения. */ + if(!o || dam>1U || op>2U || (op==2U && (id<0x201U || id>0x57FU))) return 0; if(op==2U && (id!=0x27FU || dam)) node=id&127U; if(!node) node=1; if(node>127U) return 0; /* Legacy SAM 0x27F сохраняет явно выбранный источник. */ + if(!op) id=dam?(id/0x100U)*0x100U+node:(id==0x27FU?id:0x200U+node); o[0]=id; o[1]=node; o[2]=node|(dam?128U:0U); return 1; /* RPDO-база DAM сохраняется, SAM использует исходный диапазон XDi-net. */ +} /* Точный допустимый адрес проверяется кодеком перед отправкой. */ +int setp_deif_validate(uint32_t id,const uint8_t *d,size_t n,unsigned flags,unsigned slave) { /* Разделяет выход MASTER и события собственного SLAVE. */ + int32_t m[12]; int k; if(flags || (!d && n)) return 0; /* RTR/EXT запрещены в обоих маршрутах. */ + if(slave) { /* Сервер не может посылать запросы конфигурации другим узлам. */ + if(slave>127U) return 0; if(id==0x700U+slave && n==1U) return d[0]==0U || d[0]==4U || d[0]==5U || d[0]==127U; /* Только собственные NMT-состояния. */ + if(id==0x580U+slave && n==8U) return d[0]==0x43U || d[0]==0x47U || d[0]==0x4BU || d[0]==0x4FU || d[0]==0x60U || d[0]==0x80U; /* Только ответы expedited SDO либо abort. */ + if(id==0x80U+slave && n==8U) { static const uint8_t lost[8]={0,0x81,0x81,6,0,0,0,0}; static const uint8_t clear[8]={0}; return !memcmp(d,lost,8) || !memcmp(d,clear,8); } /* Data lost и сброс по Appendix 5. */ + return 0; /* Чужие идентификаторы и ответные PDO не разрешены. */ + } /* MASTER сохраняет отдельный ограниченный набор команд. */ + k=setp_deif_inspect(id,d,n,0,m); if(k==2) return d[0]==5U; if(k!=1 && k!=3) return 0; /* Обычный MASTER не передаёт NMT, SDO и Boot-up. */ + if(!m[9]) return 0; if(k==3) return d[5]==0U && (m[5]==6 ? d[4]<=100U : d[4]<=2U); return 1; /* Значения диммера проверяются как U8 с нулевым хвостом. */ +} /* Проверка не производит физический TX. */ +static void event(deif_state *s,uint32_t id,const uint8_t *d,unsigned n) { /* Очередь имеет явную ограниченную вместимость. */ + setp_deif_frame_t *f; if(s->queued>=DEIF_QUEUE) return; f=&s->queue[s->queued++]; memset(f,0,sizeof(*f)); f->can_id=id; f->dlc=n; memcpy(f->data,d,n); /* Один event соответствует одному готовому CAN-кадру. */ +} /* Порты регулярно выгружают очередь через poll. */ +int setp_deif_init(void *p,size_t size,unsigned node,unsigned source,unsigned xdi,unsigned self_start,unsigned pdo,unsigned group,unsigned services,uint32_t monitor_id) { /* Общий конструктор наблюдателя и серверного SLAVE. */ + deif_state *s=(deif_state *)p; unsigned f; uint8_t selector[4]; /* Селекторы строятся тем же общим каталогом. */ + if(!s || size(services?126U:127U) || group>9U || pdo<1U || pdo>4U || (services && (!node || node>(xdi?126U:127U) || (xdi && pdo==1U)))) return 0; /* Источник обычной рассылки не занимает сервисный Node 127; RPDO1 резервируется в XDi-net. */ + memset(s,0,sizeof(*s)); s->magic=DEIF_MAGIC; s->node=node; s->source=source; s->xdi=xdi; s->self_start=xdi||self_start; s->pdo=pdo; s->group=group; s->services=services; s->monitor_id=monitor_id?monitor_id:0x200U+source; /* Исходный CAN ID источника вычисляется в C, без копии формулы в Kotlin. */ + s->heartbeat=500; s->brightness=100; s->nmt=services?127U:5U; s->active=!services; /* Пассивный наблюдатель не выдаёт heartbeat и сразу принимает данные. */ + for(f=0;f=DEIF_FIELDS || !isfinite(scale)) return 0; /* Неверный масштаб не попадает в снимок индикатора. */ + b=&s->field[f]; bound=selector && (selector[0]||selector[1]||selector[2]||selector[3]); if(b->bound==bound && b->scale==scale && (!bound || !memcmp(b->selector,selector,4))) return 1; /* Повторная синхронизация порта не стирает принятые значения. */ + memset(b,0,sizeof(*b)); b->bound=bound; b->scale=scale; if(bound) memcpy(b->selector,selector,4); /* Новая привязка начинает собственный срок ожидания. */ + if(f==2U) { uint8_t cmd[4]; if(bound && (le16(selector+1)&0xFFF0U)==0x3000U) { memcpy(cmd,selector,4); cmd[3]=7; setp_deif_bind(s,5,cmd,scale); } else setp_deif_bind(s,5,NULL,scale); } return 1; /* Задание угла выводится отдельно даже при пассивном наблюдении. */ +} /* Выбор фактического или заданного объекта сохраняется в исходной привязке. */ +int setp_deif_default_angle(void *p,uint8_t *o,double *scale) { /* Миграция старой пустой привязки использует уже настроенную адресацию прибора. */ + deif_state *s=context(p); unsigned f,addr; if(!s || !o || !scale) return 0; addr=s->source; /* При отсутствии других полей применяется источник профиля. */ + for(f=0;ffield[f].bound) { addr=s->field[f].selector[0]; break; } /* SAM-источник либо DAM-получатель берётся без предположений UI. */ + *scale=0.1; return setp_deif_selector(2,addr&127U,1,(addr&128U)!=0,o); /* Стандартный азимут экземпляра 1 имеет разрешение 0,1°. */ +} /* Остальные пользовательские привязки не меняются. */ +int setp_deif_get_binding(void *p,unsigned f,uint8_t *o,double *scale) { /* Порт не содержит второй таблицы исходных коэффициентов. */ + deif_state *s=context(p); if(!s || f>=DEIF_FIELDS || !o || !scale) return 0; memcpy(o,s->field[f].selector,4); *scale=s->field[f].scale; return (int)s->field[f].bound; /* Публичный ABI выдаёт только селектор и скаляр масштаба. */ +} /* Внутренний layout deif_binding не раскрывается клиентам. */ +void setp_deif_reset_values(void *p) { /* Сброс данных не переключает коммуникационное состояние. */ + deif_state *s=context(p); unsigned f; if(!s) return; for(f=0;ffield[f].received=0; s->field[f].status=0; s->field[f].seen=0; s->field[f].raw=0; } /* Профиль и масштабы сохраняются. */ +} /* Этот путь используется при изменении маршрута наблюдателя. */ +int setp_deif_start(void *p,uint64_t now,unsigned reset_values) { /* NMT Reset communication сохраняет прикладные значения. */ + deif_state *s=context(p); uint8_t boot=0; if(!s) return 0; if(reset_values) setp_deif_reset_values(s); /* Reset node дополнительно очищает прикладную область. */ + s->active=1; s->nmt=s->services?127U:5U; s->accepted=0; s->queued=0; s->error=0; s->heartbeat=500; s->started=s->last_hb=now; s->auto_at=s->services && s->self_start?now+1000U:0; /* DEIF §1.8 и §1.10: 1000 мс self-start, 500 мс heartbeat. */ + if(s->services) event(s,0x700U+s->node,&boot,1); return 1; /* Наблюдатель не объявляет себя узлом сети. */ +} /* Включение само по себе не создаёт выдуманных измерений. */ +void setp_deif_stop(void *p) { deif_state *s=context(p); if(s) { s->active=0; s->queued=0; } } /* Выключение отменяет в том числе невыданные служебные кадры. */ +unsigned setp_deif_lost(void *p,uint64_t now) { /* Каждый используемый вход имеет независимый таймер. */ + deif_state *s=context(p); unsigned f,mask=0; if(!s || !s->active) return 0; /* Неактивный узел не генерирует ошибку Data lost. */ + for(f=0;f<5U;f++) if(s->field[f].bound) { uint64_t t=s->field[f].received?s->field[f].seen:s->started; if(f==2U && !s->field[2].received && s->field[5].received) t=s->field[5].seen; if(now>=t && now-t>=3000U) mask|=1U<raw=raw; b->seen=now; b->received=1; b->status=raw_status(raw); } /* Служебная ошибка отличается от отсутствия обновлений. */ +static int sdo(deif_state *s,const uint8_t *d,uint64_t now) { /* Явный ограниченный сервер expedited SDO без выдуманного полного EDS. */ + uint16_t idx=le16(d+1); unsigned sub=d[3],bytes=0,found_index=0,f; uint32_t value=0,abort=0; uint8_t out[8]={0}; /* Ответ всегда содержит исходный мультиплексор запроса. */ + memcpy(out+1,d+1,3); if(d[0]==0x80U) return 0; /* Клиентский abort не вызывает ответного abort. */ + if(idx==0x1000U || idx==0x1001U || idx==0x1017U || idx==0x1018U) found_index=1; /* Стандартные объекты объявлены явно. */ + if(idx==0x1000U && !sub) { bytes=4; value=0; } else if(idx==0x1001U && !sub) { bytes=1; value=s->error?0x81U:0U; } /* Тип устройства и error register по Appendix 1. */ + else if(idx==0x1017U && !sub) { bytes=2; value=s->heartbeat; } else if(idx==0x1018U && sub<=1U) { bytes=sub?4U:1U; value=sub?0x100000B2U:1U; } /* DEIF vendor ID опубликован; продукт и серийный номер не выдумываются. */ + for(f=0;ffield[f].bound && le16(s->field[f].selector+1)==idx) { found_index=1; if(s->field[f].selector[3]==sub) { bytes=2; value=s->field[f].received?(uint16_t)s->field[f].raw:0x7FFFU; } } /* До обновления I16 возвращается «данные недействительны». */ + if(d[0]!=0x40U && d[0]!=0x2FU && d[0]!=0x2BU && d[0]!=0x27U && d[0]!=0x23U) abort=0x05040001U; else if(!bytes) abort=found_index?0x06090011U:0x06020000U; /* Различаем неподдерживаемую команду, подиндекс и объект. */ + else if(d[0]==0x40U) { out[0]=(uint8_t)(0x43U|((4U-bytes)<<2)); put32(out+4,value); event(s,0x580U+s->node,out,8); return 1; } /* Upload возвращает фактическую ширину U8/U16/U32. */ + else if(idx!=0x1017U || sub) abort=0x06010002U; else if(d[0]!=0x2BU) abort=0x06070010U; /* Запись данного профиля разрешена только для U16 heartbeat producer. */ + else { value=le16(d+4); if(s->xdi && !value) abort=0x06090030U; else { s->heartbeat=value; s->last_hb=now; out[0]=0x60; event(s,0x580U+s->node,out,8); return 1; } } /* В XDi-net heartbeat обязателен, в CANopen ноль его отключает. */ + out[0]=0x80; put32(out+4,abort); event(s,0x580U+s->node,out,8); return 0; /* Неподдерживаемый запрос не меняет значения или NMT-состояние. */ +} /* На каждый запрос получается не более одного ответа. */ +int setp_deif_accept(void *p,uint32_t id,const uint8_t *d,size_t n,unsigned flags,uint64_t now) { /* Основной общий автомат приёма внешнего MASTER. */ + deif_state *s=context(p); int32_t m[12]; int kind,changed=0; unsigned f,dam; if(!s || !s->active || flags || (!d && n)) return 0; /* Неверный канал отфильтровывает порт, EXT/RTR — ядро. */ + if(s->auto_at && now>=s->auto_at) { s->nmt=5; s->auto_at=0; } /* Автозапуск действует и перед приёмом очередного кадра. */ + if(s->services && id==0 && n==2U && (!d[1] || d[1]==s->node)) { /* NMT адресует свой узел либо broadcast 0. */ + if(d[0]==129U || d[0]==130U) return setp_deif_start(s,now,d[0]==129U); /* Два вида сброса различаются сохранением прикладных данных. */ + if(d[0]==1U || d[0]==2U || d[0]==128U) { s->nmt=d[0]==1U?5U:d[0]==2U?4U:127U; s->auto_at=0; return 1; } return 0; /* Явная NMT-команда отменяет отложенный self-start. */ + } /* Остальные служебные кадры не являются измерениями. */ + if(s->services && id==0x600U+s->node && n==8U && (s->nmt==5U || s->nmt==127U)) return sdo(s,d,now); /* SDO доступен в Operational и Pre-operational. */ + if(s->nmt!=5U || n!=8U) return 0; kind=setp_deif_inspect(id,d,n,0,m); if(kind!=1 && kind!=3 && kind!=-6) return 0; /* Явная пользовательская привязка разрешает неизвестный каталогу I16, но не неверную адресацию. */ + dam=(unsigned)m[8]; if(dam) { if(s->node && (unsigned)m[1]!=s->node) return 0; if(!s->node && id!=s->monitor_id) return 0; if(s->services && id!=(s->pdo+1U)*0x100U+s->node) return 0; } /* Без заданного физического Node пассивный монитор сохраняет точную привязку CAN ID и селектора. */ + else if(s->services ? (!s->xdi || m[1]>=127) : id!=s->monitor_id) return 0; /* Пассивный монитор сохраняет точную настройку CAN ID, CANopen без XDi-net игнорирует SAM. */ + if(kind==3 && s->services && s->group && (unsigned)m[2]==0x3500U+s->group) { if(d[5]||d[6]||d[7] || ((m[3]==2 && d[4]>100U)||(m[3]==3 && d[4]>2U))) return 0; if(m[3]==2) s->brightness=d[4]; else s->palette=d[4]; s->accepted++; return 1; } /* Яркость и Color не продлевают свежесть измерений. */ + if(d[6]||d[7]) return 0; for(f=0;ffield[f].bound && !memcmp(s->field[f].selector+1,d+1,3) && ((dam && s->node) || s->field[f].selector[0]==d[0])) { store(&s->field[f],m[4],now); changed=1; } /* DAM без настроенного физического получателя не превращается в приём всех узлов сети. */ + if(changed) s->accepted++; return changed; /* Приём PDO не создаёт выдуманного ответного PDO. */ +} /* Словарь прикладных значений не зависит от способа доставки кадра. */ +size_t setp_deif_poll(void *p,uint64_t now,setp_deif_frame_t *o,size_t cap) { /* Таймеры используют только переданные портом монотонные часы. */ + deif_state *s=context(p); size_t count; uint8_t state; unsigned lost; if(!s || !s->active || !s->services) return 0; /* Пассивное наблюдение не передаёт ничего в сеть. */ + if(s->auto_at && now>=s->auto_at) { s->nmt=5; s->auto_at=0; } /* Стандартный self-start заканчивается через 1000 мс. */ + if(s->heartbeat && now>=s->last_hb && now-s->last_hb>=s->heartbeat) { state=(uint8_t)s->nmt; event(s,0x700U+s->node,&state,1); s->last_hb=now; } /* После задержки создаётся один актуальный heartbeat без пачки пропущенных тиков. */ + lost=setp_deif_lost(s,now)!=0; if(s->nmt==5U && lost!=s->error) { uint8_t emcy[8]={0}; if(lost) { emcy[1]=0x81; emcy[2]=0x81; emcy[3]=6; } event(s,0x80U+s->node,emcy,8); s->error=lost; } /* Appendix 5: Data lost 0x8100/0x81/0x06 и нулевой Error reset. */ + count=s->queuedqueued:cap; if(!o || !count) return 0; memcpy(o,s->queue,count*sizeof(*o)); s->queued-=(unsigned)count; memmove(s->queue,s->queue+count,s->queued*sizeof(*o)); return count; /* Непоместившиеся события сохраняются для следующего вызова. */ +} /* Владение выходным буфером остаётся у Python/JNI/MCU. */ +int setp_deif_read(void *p,unsigned f,uint64_t now,unsigned expiry,double *value,int64_t *m) { /* Возвращает данные без подмены ошибочного кода числом. */ + deif_state *s=context(p); deif_binding *b; unsigned flags=0; if(!s || f>=DEIF_FIELDS || !value || !m) return 0; b=&s->field[f]; /* Границы поля проверяются до доступа к массиву. */ + if(b->bound && b->received) { flags=1U; if(!b->status) flags|=2U; if(expiry && now>=b->seen && now-b->seen>expiry) flags|=4U; } /* Пассивный UI скрывает данные через пять секунд, сервер хранит последнее значение для мигания. */ + *value=b->raw*b->scale; m[0]=(int64_t)b->seen; m[1]=b->raw; m[2]=b->status; m[3]=flags; return (int)flags; /* Разрешение применяется в единственном общем ядре. */ +} /* Метаданные позволяют отличить invalid от устаревания и отсутствия кадра. */ +int setp_deif_angle(void *p,uint64_t now,unsigned expiry,double *v) { /* Единое правило выбора азимута для Desktop и Android. */ + deif_state *s=context(p); int64_t m[4]; unsigned f,kind; int flags; if(!s || !v) return 0; f=s->field[2].received?2U:5U; kind=f==5U || s->field[2].selector[3]==7U?2U:1U; /* До первого фактического кадра используется только принятое сетевое задание с явной пометкой. */ + flags=setp_deif_read(s,f,now,expiry,v,m); return (flags&2) && !(flags&4) ? (int)kind : 0; /* Ошибочное фактическое сообщение не заменяется старым заданием. */ +} /* Черновиков GUI в этом API нет. */ +int setp_deif_meta(void *p,int64_t *o) { /* Копирует скалярный снимок без раскрытия private-layout состояния. */ + deif_state *s=context(p); if(!s || !o) return 0; o[0]=s->active; o[1]=s->nmt; o[2]=(int64_t)s->started; o[3]=(int64_t)s->last_hb; o[4]=s->heartbeat; o[5]=s->accepted; o[6]=s->group; o[7]=s->brightness; o[8]=s->palette; o[9]=s->error; return 1; /* Индексы массива документированы в публичном заголовке. */ +} /* API пригоден для прямого буфера JNI и ctypes без платформенных зависимостей. */ diff --git a/c/set-protocol/src/pcan_gas.c b/c/set-protocol/src/pcan_gas.c index 27132b4..1562edb 100644 --- a/c/set-protocol/src/pcan_gas.c +++ b/c/set-protocol/src/pcan_gas.c @@ -139,7 +139,8 @@ uint16_t pcan_gas_write_block(const pcan_gas_map_t *map, uint16_t addr, uint16_t pcan_gas_frame_to_regs(const pcan_frame_t *frame, uint16_t *out, uint16_t max) { - uint16_t n = 0U; + uint16_t n = 0U; /* Счётчик увеличивается только после проверки длины и наличия обоих октетов слова. */ + if (frame == NULL || out == NULL || frame->dlc > PCAN_DATA_MAX || (frame->dlc & 1U) != 0U) return 0U; /* Отвергаем нечётные и превышающие classic CAN длины до доступа к данным. */ for (uint8_t i = 0U; (uint8_t)(i + 1U) < frame->dlc; i = (uint8_t)(i + 2U)) { if (n >= max) { break; @@ -178,9 +179,10 @@ void pcan_gas_regs_to_frame(pcan_frame_t *frame, uint32_t base_id, bool pcan_gas_handle(const pcan_gas_map_t *map, const pcan_frame_t *req, pcan_frame_t *rsp) { - pcan_id_t id; - pcan_id_unpack(req->id, &id); - if (id.msg_type != (uint8_t)PCAN_MSG_GAS) { + pcan_id_t id; /* Адрес регистра и направление проверяются до вызова provider, чтобы ответ не стал записью. */ + if (map == NULL || req == NULL || (req->id & ~PCAN_ID_MASK) != 0U || (req->flags & PCAN_FLAG_IDE) == 0U || (req->flags & (PCAN_FLAG_RTR | PCAN_FLAG_ERR)) != 0U || req->dlc > PCAN_DATA_MAX || (req->dlc & 1U) != 0U) return false; /* Принимаем только extended data frame с целыми 16-битными регистрами. */ + pcan_id_unpack(req->id, &id); /* Разбираем проверенный 29-битный идентификатор единственным общим кодеком. */ + if (id.msg_type != (uint8_t)PCAN_MSG_GAS || id.route != PCAN_ROUTE_FROM_PM || (uint32_t)id.msg_body + req->dlc / 2U > 0x10000UL || (req->dlc == 0U && rsp == NULL)) { /* Тип 0x4, ответы прибора и блоки за адресом 65535 не изменяют карту; чтению нужен выходной кадр. */ return false; } diff --git a/c/set-protocol/src/pcan_gas_slot.c b/c/set-protocol/src/pcan_gas_slot.c new file mode 100644 index 0000000..3df5c9a --- /dev/null +++ b/c/set-protocol/src/pcan_gas_slot.c @@ -0,0 +1,103 @@ +#include "pcan_gas_slot.h" /* Подключаем независимый слотный GAS типа 0x4 с маской в нулевом слове. */ +#include "pcan_id.h" /* Используем единственный общий упаковщик полей 29-битного CAN ID. */ +#include /* Локальный ответ обнуляется до заполнения и публикации вызывающему коду. */ +static unsigned available_mask(unsigned local) /* Вычисляем действующие позиции трёх значений PERIPH, включая неполный последний слот. */ +{ /* Маска не является хранимым регистром и не занимает адрес в карте технологических слов. */ + unsigned word, mask = 0U; /* Биты 1…3 соответствуют одноимённым позициям wire-пакета после маски. */ + for (word = 1U; word <= PCAN_GAS_SLOT_DATA_WORDS; ++word) if (local * PCAN_GAS_SLOT_DATA_WORDS + word - 1U < PCAN_GAS_SLOT_MODE_WORDS) mask |= 1U << word; /* Сохраняем ровно 200 слов без фиктивного 201-го регистра. */ + return mask; /* Для обычного слота получаем 0x000E, для последнего — 0x0006. */ +} /* Завершаем расчёт единственной геометрии PERIPH. */ +int32_t pcan_gas_slot_address(unsigned mode, unsigned local) /* Строим читаемый адрес только для реально выделенной страницы PERIPH. */ +{ /* Остальные 16-битные адреса доступны через общий адресный API отдельного узла. */ + if (mode >= PCAN_GAS_SLOT_MODE_COUNT || local >= PCAN_GAS_SLOT_MODE_SLOTS) return -1; /* Отвергаем чужой mode и резерв страницы до сужения типов. */ + return (int32_t)(((uint32_t)mode << 8) | local); /* Старший октет повторяет mode, младший содержит локальный слот 0…66. */ +} /* Конец проверки координат PERIPH. */ +uint32_t pcan_gas_slot_id(unsigned device_type, unsigned device_id, unsigned address, unsigned route) /* Поддерживаем любой узел ProtoCAN и полный адрес слота 0…65535. */ +{ /* Нулевой результат означает недопустимые поля, а не молчаливое усечение адреса. */ + pcan_id_t id; /* Битовую раскладку идентификатора формирует существующее общее ядро. */ + if (device_type > 7U || device_id > 15U || address > 65535UL || route > 1U) return 0U; /* Проверяем все поля до приведения к их wire-типам. */ + id.priority = PCAN_PRIORITY_STANDARD; id.route = (uint_least8_t)route; /* Обычный приоритет и явное направление сохраняют семантику ProtoCAN. */ + id.device_type = (uint_least8_t)device_type; id.device_id = (uint_least8_t)device_id; /* Не связываем общий слотный сервис исключительно с семейством PERIPH. */ + id.msg_type = PCAN_MSG_GAS_SLOT; id.msg_body = (uint16_t)address; /* Тип 0x4 однозначно отличает слот от адреса отдельного регистра типа 0x3. */ + return pcan_id_pack(&id); /* Публикуем идентификатор после проверки полного диапазона входов. */ +} /* Конец общего адресного построителя. */ +uint32_t pcan_gas_slot_request_id(unsigned mode, unsigned local, unsigned route) /* Сохраняем удобный совместимый вызов для mode PERIPH. */ +{ /* Обёртка добавляет только раскладку mode и не реализует второй кодек. */ + int32_t address = pcan_gas_slot_address(mode, local); /* Проверяем принадлежность слота выделенной странице. */ + return address < 0 ? 0U : pcan_gas_slot_id(1U + mode / 16U, mode % 16U, (unsigned)address, route); /* Обе группы по 16 узлов используют общий конструктор типа 0x4. */ +} /* Конец PERIPH-обёртки построения ID. */ +int pcan_gas_slot_encode(const uint16_t *words, unsigned count, uint_least8_t *data) /* Word0 содержит маску, Word1…Word3 — значения в фиксированных позициях. */ +{ /* Пустой payload означает чтение, полный восьмибайтовый payload — маску и данные. */ + unsigned i; /* Индекс относится к четырём wire-словам, включая служебную маску. */ + if (count == 0U) return 0; /* Запрос чтения не требует массива значений или фиктивной маски. */ + if (count != PCAN_GAS_SLOT_WORDS || words == NULL || data == NULL || words[0] == 0U || (words[0] & ~PCAN_GAS_SLOT_MASK) != 0U) return -1; /* Биты 0 и 4…15 зарезервированы, пустая запись запрещена. */ + for (i = 0U; i < PCAN_GAS_SLOT_WORDS; ++i) { /* Проверенная маска и три значения одинаково упаковываются little-endian. */ + data[2U * i] = (uint_least8_t)(words[i] & 255U); data[2U * i + 1U] = (uint_least8_t)(words[i] >> 8); /* Значения 255 и сдвиг 8 задают октеты линии независимо от ширины char C28x. */ + } /* Все восемь октетов сформированы только после проверки входа. */ + return 8; /* DLC измеряется октетами CAN, а не размером C-массива на wide-char процессоре. */ +} /* Конец единственного кодирования маски и значений. */ +int pcan_gas_slot_decode_words(uint32_t raw, unsigned flags, const uint_least8_t *data, unsigned dlc, uint16_t *words) /* Общая проверка формата не ограничивает узел PERIPH или страницу слота. */ +{ /* Выходные слова остаются неизменными при любой ошибке. */ + pcan_id_t id; unsigned i; uint16_t decoded[PCAN_GAS_SLOT_WORDS]; /* Сначала собираем результат в локальном массиве, чтобы отказ был безопасным. */ + if ((raw & ~PCAN_ID_MASK) != 0U || !(flags & PCAN_GAS_SLOT_FLAG_IDE) || (flags & (PCAN_GAS_SLOT_FLAG_RTR | PCAN_GAS_SLOT_FLAG_ERR)) != 0U) return -1; /* Принимаем только extended data frames classic CAN. */ + if ((dlc != 0U && dlc != 8U) || (dlc == 8U && (data == NULL || words == NULL))) return -1; /* Усечённая маска или часть слота не являются допустимой командой. */ + pcan_id_unpack(raw, &id); /* Все адресные поля извлекаются общим C-кодеком. */ + if (id.msg_type != PCAN_MSG_GAS_SLOT || (dlc == 0U && id.route != PCAN_ROUTE_FROM_PM)) return -1; /* Регистровый GAS 0x3 и пустой ответ не попадают в слотный сервис. */ + if (dlc == 0U) return 0; /* Пустой запрос чтения не изменяет массив значений. */ + for (i = 0U; i < 8U; ++i) if (data[i] > 255U) return -1; /* На C28x запрещаем ненулевые старшие биты каждой ячейки, представляющей wire-октет. */ + for (i = 0U; i < PCAN_GAS_SLOT_WORDS; ++i) decoded[i] = (uint16_t)((uint16_t)data[2U * i] | ((uint16_t)data[2U * i + 1U] << 8)); /* Восстанавливаем четыре слова с явно заданным порядком октетов. */ + if (decoded[0] == 0U || (decoded[0] & ~PCAN_GAS_SLOT_MASK) != 0U) return -1; /* Разрешены только непустые комбинации битов 1, 2 и 3, соответствующие позициям значений. */ + for (i = 0U; i < PCAN_GAS_SLOT_WORDS; ++i) words[i] = decoded[i]; /* Публикуем значения после проверки всей маски. */ + return PCAN_GAS_SLOT_WORDS; /* Четыре возвращённых слова включают Word0 с маской, а не четвёртый регистр. */ +} /* Конец общего декодера любого адреса слота. */ +int pcan_gas_slot_decode(uint32_t raw, unsigned flags, const uint_least8_t *data, unsigned dlc, unsigned *mode, unsigned *local, uint16_t *words) /* Добавляем к общему формату ограничения страницы PERIPH. */ +{ /* При отказе ни координаты, ни значения не меняются. */ + pcan_id_t id; unsigned found_mode, found_local, i; uint16_t decoded[PCAN_GAS_SLOT_WORDS]; int count; /* Подготавливаем промежуточные выходы общей проверки. */ + if (mode == NULL || local == NULL || (dlc != 0U && words == NULL)) return -1; /* Все требуемые выходные указатели проверяются до чтения или публикации данных. */ + count = pcan_gas_slot_decode_words(raw, flags, data, dlc, decoded); if (count < 0) return -1; /* Единственный wire-декодер проверяет тип 0x4, маску, DLC и флаги. */ + pcan_id_unpack(raw, &id); if (id.device_type < 1U || id.device_type > 2U) return -1; /* PERIPH занимает только два существующих класса адресов. */ + found_mode = (unsigned)(id.device_type - 1U) * 16U + id.device_id; found_local = id.msg_body & 255U; /* Номер mode восстанавливается независимо от старшего октета слота. */ + if (pcan_gas_slot_address(found_mode, found_local) != (int32_t)id.msg_body || (count > 0 && (decoded[0] & ~available_mask(found_local)) != 0U)) return -1; /* Отвергаем чужую страницу, резерв и несуществующее третье значение последнего слота. */ + if (count > 0) for (i = 0U; i < PCAN_GAS_SLOT_WORDS; ++i) words[i] = decoded[i]; /* Значения публикуются после проверки геометрии PERIPH. */ + *mode = found_mode; *local = found_local; return count; /* Возвращаем координаты только успешно проверенного кадра. */ +} /* Конец совместимой PERIPH-обёртки декодирования. */ +int pcan_gas_slot_native(unsigned local, unsigned word, unsigned write, uint16_t *address) /* Сопоставляем только значения Word1…Word3 с прежними native-регистрами. */ +{ /* Нулевая позиция является маской и никогда не адресует технологический регистр. */ + unsigned offset; uint16_t native; /* Смещение измеряется в 16-битных словах полезной карты, без служебных масок. */ + if (local >= PCAN_GAS_SLOT_MODE_SLOTS || word == 0U || word > PCAN_GAS_SLOT_DATA_WORDS || write > 1U || address == NULL) return 0; /* Предотвращаем адресацию маски и выход за выделенные позиции. */ + offset = local * PCAN_GAS_SLOT_DATA_WORDS + word - 1U; /* Каждый следующий слот содержит следующие три значения исходной карты из 200 слов. */ + if (offset < 128U) native = (uint16_t)offset; /* Все 128 технологических регистров сохраняют свои native-адреса и смысл. */ + else if (offset < 144U && !write) native = (uint16_t)(0x1000U + offset - 128U); /* Следующие 16 слов читают статус регистратора УМП. */ + else if (offset >= 144U && offset < 156U && !write) native = (uint16_t)(0x1200U + offset - 144U); /* Двенадцать слов паспорта доступны только для чтения. */ + else if (offset >= 156U && offset < 164U) { /* Восемь следующих слов относятся к защите УМП. */ + native = (uint16_t)(0x1300U + offset - 156U); /* Сохраняем исходные адреса 0x1300…0x1307 независимо от границ слота. */ + if (write && native != 0x1302U && native != 0x1303U) return 0; /* Масочная запись допускает только два разрешённых поля защиты. */ + } else if (offset >= 164U && offset < 168U) native = (uint16_t)(0x1000U + offset - 164U); /* Команды регистратора сохраняют собственные native-адреса четырёх слов. */ + else return 0; /* Резерв 168…199 и лишняя позиция 200 не имитируются нулевыми значениями. */ + *address = native; return 1; /* Доступность конкретного сервиса и применение записи проверяет provider устройства. */ +} /* Конец сопоставления без побочных эффектов. */ +int pcan_gas_slot_handle_address(unsigned device_type, unsigned device_id, const pcan_gas_slot_port_t *port, const pcan_gas_slot_frame_t *request, pcan_gas_slot_frame_t *response) /* Обрабатываем любой адресуемый узел ProtoCAN, включая отдельный инвертор. */ +{ /* Provider отвечает за общую проверку и изменение только выбранных маской значений. */ + pcan_id_t id; uint16_t words[PCAN_GAS_SLOT_WORDS]; int count, length; pcan_gas_slot_frame_t out; /* Все рабочие данные локальны и не требуют динамической памяти. */ + if (port == NULL || request == NULL || device_type > 7U || device_id > 15U) return -1; /* Не принимаем отсутствующий порт или усечённый адрес узла. */ + count = pcan_gas_slot_decode_words(request->id, request->flags, request->data, request->dlc, words); if (count < 0) return -1; /* Проверяем полный wire-контракт до обращения к provider. */ + pcan_id_unpack(request->id, &id); /* Направление и адрес проверяем отдельно от декодирования payload. */ + if (id.route != PCAN_ROUTE_FROM_PM || id.device_type != device_type || id.device_id != device_id) return -1; /* Ответы приборов и запросы соседям не исполняются. */ + if (count > 0) return port->write != NULL && port->write(port->context, id.msg_body, words) == 0 ? 0 : -1; /* Единственный callback получает маску Word0 и обязан сохранять невыбранные значения без чтения на хосте. */ + if (response == NULL || port->read == NULL || port->read(port->context, id.msg_body, words) != 0) return -1; /* Ошибка чтения не превращается в успешные нули. */ + memset(&out, 0, sizeof(out)); length = pcan_gas_slot_encode(words, PCAN_GAS_SLOT_WORDS, out.data); if (length < 0) return -1; /* Проверяем маску достоверных значений, которую вернул provider. */ + id.route = PCAN_ROUTE_FROM_DEVICE; out.id = pcan_id_pack(&id); out.flags = PCAN_GAS_SLOT_FLAG_IDE; out.dlc = (unsigned)length; /* Ответ сохраняет полный адрес слота и меняет только направление. */ + *response = out; return 1; /* Публикуем только полностью сформированный ответ. */ +} /* Конец общего обработчика слотов типа 0x4. */ +int pcan_gas_slot_handle(unsigned mode, const pcan_gas_slot_port_t *port, const pcan_gas_slot_frame_t *request, pcan_gas_slot_frame_t *response) /* Сохраняем специализированный вход PERIPH поверх общего обработчика. */ +{ /* Временный ответ защищает выходной кадр от ошибочного provider последнего слота. */ + unsigned found_mode, local; uint16_t words[PCAN_GAS_SLOT_WORDS]; pcan_gas_slot_frame_t out; int result; /* Буферы ограничены одним classic CAN кадром. */ + if (request == NULL || mode >= PCAN_GAS_SLOT_MODE_COUNT || pcan_gas_slot_decode(request->id, request->flags, request->data, request->dlc, &found_mode, &local, words) < 0 || found_mode != mode) return -1; /* Проверяем страницу PERIPH и маску до возможной записи. */ + if (request->dlc == 0U && response == NULL) return -1; /* Не вызываем read-provider, если вызывающая сторона не предоставила место для ответа. */ + result = pcan_gas_slot_handle_address(1U + mode / 16U, mode % 16U, port, request, &out); /* Используем общий обработчик типа 0x4 без второго алгоритма записи. */ + if (result == 1) { /* Дополнительно проверяем маску чтения с учётом неполного последнего слота PERIPH. */ + if (pcan_gas_slot_decode(out.id, out.flags, out.data, out.dlc, &found_mode, &local, words) < 0) return -1; /* Нельзя опубликовать фиктивный 201-й регистр или чужую страницу из ошибочного provider. */ + *response = out; /* Передаём вызывающей стороне только ответ, прошедший обе проверки. */ + } /* Запись возвращает ноль и не изменяет выходной кадр. */ + return result; /* Отрицательный результат означает отказ без автоматического перехода в регистровый GAS. */ +} /* Конец PERIPH-обёртки. */ diff --git a/c/set-protocol/src/pcan_id.c b/c/set-protocol/src/pcan_id.c index 82dbcbb..9f2ae4e 100644 --- a/c/set-protocol/src/pcan_id.c +++ b/c/set-protocol/src/pcan_id.c @@ -19,9 +19,9 @@ void pcan_id_unpack(uint32_t raw, pcan_id_t *id) { raw &= PCAN_ID_MASK; id->msg_body = (uint16_t)(raw & 0xFFFFU); - id->msg_type = (uint8_t)((raw >> 16) & 0xFU); - id->device_id = (uint8_t)((raw >> 20) & 0xFU); - id->device_type = (uint8_t)((raw >> 24) & 0x7U); - id->route = (uint8_t)((raw >> 27) & 0x1U); - id->priority = (uint8_t)((raw >> 28) & 0x1U); + id->msg_type = (uint_least8_t)((raw >> 16) & 0xFU); /* Сужает извлечённое поле к переносимому типу октета, включая C28x с 16-битным char. */ + id->device_id = (uint_least8_t)((raw >> 20) & 0xFU); /* Сужает извлечённое поле к переносимому типу октета, включая C28x с 16-битным char. */ + id->device_type = (uint_least8_t)((raw >> 24) & 0x7U); /* Сужает извлечённое поле к переносимому типу октета, включая C28x с 16-битным char. */ + id->route = (uint_least8_t)((raw >> 27) & 0x1U); /* Сужает извлечённое поле к переносимому типу октета, включая C28x с 16-битным char. */ + id->priority = (uint_least8_t)((raw >> 28) & 0x1U); /* Сужает извлечённое поле к переносимому типу октета, включая C28x с 16-битным char. */ } diff --git a/c/set-protocol/src/pcan_modbus_server.c b/c/set-protocol/src/pcan_modbus_server.c index 46081f6..38758fb 100644 --- a/c/set-protocol/src/pcan_modbus_server.c +++ b/c/set-protocol/src/pcan_modbus_server.c @@ -10,12 +10,6 @@ #include "pcan_id.h" -static bool is_bank(uint8_t value) -{ - return (value >= (uint8_t)PCAN_MODBUS_COIL) && - (value <= (uint8_t)PCAN_MODBUS_INPUT); -} - bool pcan_modbus_server_init(pcan_modbus_server_t *server, uint8_t device_type, uint8_t device_id, pcan_modbus_read_fn read, @@ -58,15 +52,15 @@ pcan_modbus_result_t pcan_modbus_server_handle(pcan_modbus_server_t *server, pcan_id_unpack(request->id, &id); if ((id.route != PCAN_ROUTE_FROM_PM) || (id.device_type != server->device_type) || - (id.device_id != server->device_id) || !is_bank(id.msg_type)) { + (id.device_id != server->device_id) || (id.msg_type != PCAN_MSG_MODBUS)) { /* Только единый тип 0x5 адресует Modbus; 0x4, 0x6 и 0x7 не вызывают provider. */ return PCAN_MODBUS_NOT_FOR_US; } server->requests++; address = (uint16_t)(id.msg_body >> 4U); - count = (uint8_t)(id.msg_body & 0x0FU); - bank = (pcan_modbus_bank_t)id.msg_type; - if (count == 0U) { + count = (uint8_t)pcan_modbus_count(id.msg_body); /* Два младших бита хранят количество минус один, поэтому нулевого запроса больше нет. */ + bank = (pcan_modbus_bank_t)pcan_modbus_function(id.msg_body); /* Биты 3:2 выбирают банк Coil/Discrete/Holding/Input через функцию 1…4. */ + if ((address + count > 0x1000U) || (request->dlc > 8U) || ((request->flags & PCAN_FLAG_RTR) != 0U)) { /* Диапазон не пересекает границу 4096 адресов; поддерживаются только classic data frames. */ return reject(server); } @@ -78,10 +72,7 @@ pcan_modbus_result_t pcan_modbus_server_handle(pcan_modbus_server_t *server, if (request->dlc == 0U) { uint16_t packed = 0U; - if ((bank == PCAN_MODBUS_COIL) || (bank == PCAN_MODBUS_DISCRETE)) { - if (count > 16U) { - return reject(server); - } + if ((bank == PCAN_MODBUS_COIL) || (bank == PCAN_MODBUS_DISCRETE)) { /* Функции 1 и 2 возвращают до четырёх последовательных битов в одном октете. */ for (uint8_t index = 0U; index < count; ++index) { uint16_t value = 0U; if (!server->read(server->user, bank, @@ -92,9 +83,8 @@ pcan_modbus_result_t pcan_modbus_server_handle(pcan_modbus_server_t *server, packed |= (uint16_t)(1U << index); } } - response->dlc = 2U; + response->dlc = 1U; /* Для 1…4 битов достаточно одного октета; старшие биты остаются нулевыми. */ response->data[0] = (uint8_t)packed; - response->data[1] = (uint8_t)(packed >> 8U); } else { if (count > 4U) { return reject(server); @@ -111,25 +101,16 @@ pcan_modbus_result_t pcan_modbus_server_handle(pcan_modbus_server_t *server, } } } else { - if ((bank == PCAN_MODBUS_INPUT) || (bank == PCAN_MODBUS_DISCRETE) || + if ((bank == PCAN_MODBUS_INPUT) || (bank == PCAN_MODBUS_DISCRETE) || /* Входные банки функций 2 и 4 сохраняют запрет записи. */ (server->write == NULL)) { return reject(server); } - if (bank == PCAN_MODBUS_COIL) { - uint16_t bits; - if ((count > 16U) || (request->dlc != 2U)) { - return reject(server); - } - bits = (uint16_t)((uint16_t)request->data[0] | - ((uint16_t)request->data[1] << 8U)); - for (uint8_t index = 0U; index < count; ++index) { - if (!server->write(server->user, bank, - (uint16_t)(address + index), - (uint16_t)((bits >> index) & 1U))) { - return reject(server); - } - } - } else { + if (bank == PCAN_MODBUS_COIL) { /* ProtoCAN выбирает запись по непустому payload, сохраняя номер функции как селектор банка. */ + if ((request->dlc != 1U) || (request->data[0] >> count) != 0U) return reject(server); /* Ровно один октет хранит маску выбранного числа выходов без лишних установленных битов. */ + for (uint8_t index = 0U; index < count; ++index) { /* Выходы записываются по возрастанию адреса начиная с младшего бита маски. */ + if (!server->write(server->user, bank, (uint16_t)(address + index), (uint16_t)((request->data[0] >> index) & 1U))) return reject(server); /* Передаём provider значение 0 или 1 каждого выхода. */ + } /* Все запрошенные выходы обработаны. */ + } else { /* Для Holding сохраняется запись 16-битных значений little-endian. */ if ((count > 4U) || (request->dlc != (uint8_t)(count * 2U))) { return reject(server); } diff --git a/c/set-protocol/src/set_gas_watch.c b/c/set-protocol/src/set_gas_watch.c new file mode 100644 index 0000000..c2d9692 --- /dev/null +++ b/c/set-protocol/src/set_gas_watch.c @@ -0,0 +1,155 @@ +/* GAS_WATCH2 отделяет настройку списка, согласованный захват RAM и сериализацию готовой выборки. */ +#include "set_gas_watch.h" /* Подключает общий контракт списка, состояния, выборки и стабильного ABI. */ +#include "set_protocol.h" /* Повторно использует единые endian-преобразования SETProtocol вместо отдельного кодека чисел. */ +#include /* Даёт обнуление собственных структур и сравнение канонического подтверждения. */ + +static bool config_valid(uint32_t id, uint16_t period, const uint16_t *addresses, size_t count) /* Проверяет модель до чтения адресов или записи в буфер. */ +{ /* Открывает проверку общих ограничений конфигурации. */ + if (id == 0U || count > SET_GAS_WATCH_MAX || (count > 0U && addresses == NULL) || ((period == 0U) != (count == 0U))) return false; /* Требует ненулевое поколение и однозначную команду stop. */ + for (size_t i = 0U; i < count; ++i) { /* Проверяет каждый адрес только внутри переданной длины списка. */ + for (size_t j = 0U; j < i; ++j) { /* Сравнивает адрес с уже проверенными позициями, сохраняя исходный порядок. */ + if (addresses[i] == addresses[j]) return false; /* Дубли требуют устранения у потребителя, иначе индексный контракт неоднозначен. */ + } /* Завершает проверку совпадений текущего адреса. */ + } /* Завершает проверку всех адресов без выделения памяти. */ + return true; /* Разрешает обработку полностью проверенной модели. */ +} /* Завершает общую проверку ограничений конфигурации. */ + +static bool config_decode(const uint8_t *payload, size_t size, set_gas_watch_t *out) /* Разбирает заявку во временное состояние, не затрагивая действующее. */ +{ /* Открывает проверку бинарного описания списка. */ + if (payload == NULL || size < SET_GAS_WATCH_CONFIG_HEADER || size > SET_GAS_WATCH_CONFIG_MAX) return false; /* Проверяет границы до чтения полей заголовка. */ + if (setp_get_u16(payload) != SET_GAS_WATCH_VERSION || setp_get_u16(payload + 10U) != 0U) return false; /* Версия 2 и нулевой резерв определены контрактом GAS_WATCH2. */ + memset(out, 0, sizeof(*out)); /* Инициализирует также счётчик выборок, расписание и неиспользуемые адреса. */ + out->period_ms = setp_get_u16(payload + 2U); /* Читает период в миллисекундах после двухбайтовой версии. */ + out->config_id = setp_get_u32(payload + 4U); /* Читает 32-битное поколение из байтов 4..7. */ + out->count = setp_get_u16(payload + 8U); /* Читает число 16-битных GAS-слов перед резервом заголовка. */ + if (out->count > SET_GAS_WATCH_MAX || size != SET_GAS_WATCH_CONFIG_HEADER + 2U * (size_t)out->count) return false; /* Запрещает усечённые и дополненные пакеты до обхода адресов. */ + for (size_t i = 0U; i < out->count; ++i) out->address[i] = setp_get_u16(payload + SET_GAS_WATCH_CONFIG_HEADER + 2U * i); /* Декодирует адреса в неизменном порядке, два байта на слово. */ + return config_valid(out->config_id, out->period_ms, out->address, out->count); /* Применяет одинаковые правила к входящему и исходящему спискам. */ +} /* Завершает разбор временной конфигурации. */ + +static bool active(const set_gas_watch_t *watch) /* Ограничивает обращения к массиву рамками настроенной активной подписки. */ +{ /* Открывает проверку минимальных инвариантов состояния. */ + return watch != NULL && watch->config_id != 0U && watch->period_ms != 0U && watch->count > 0U && watch->count <= SET_GAS_WATCH_MAX; /* Остановленная или неинициализированная подписка не выдаёт выборки. */ +} /* Завершает проверку активности. */ + +void set_gas_watch_init(set_gas_watch_t *watch) /* Подготавливает независимый экземпляр для одного управляющего клиента. */ +{ /* Открывает безопасную инициализацию состояния. */ + if (watch != NULL) memset(watch, 0, sizeof(*watch)); /* Нулевое поколение обозначает отсутствие применённой конфигурации. */ +} /* Завершает инициализацию экземпляра. */ + +size_t set_gas_watch_request(uint32_t config_id, uint16_t period_ms, const uint16_t *addresses, size_t count, uint8_t *out, size_t capacity) /* Собирает единственный канонический формат команды и её полного эхо-ответа. */ +{ /* Открывает создание payload конфигурации. */ + if (!config_valid(config_id, period_ms, addresses, count) || out == NULL || capacity < SET_GAS_WATCH_CONFIG_HEADER + 2U * count) return 0U; /* Проверяет всё до первой записи, включая дубли и размер буфера в байтах. */ + setp_put_u16(out, SET_GAS_WATCH_VERSION); /* Записывает версию payload 2 независимо от внешнего транспорта. */ + setp_put_u16(out + 2U, period_ms); /* Кодирует период в миллисекундах в байты 2..3. */ + setp_put_u32(out + 4U, config_id); /* Кодирует ненулевое поколение в байты 4..7. */ + setp_put_u16(out + 8U, (uint16_t)count); /* Сохраняет проверенное число слов в двухбайтовом поле. */ + setp_put_u16(out + 10U, 0U); /* Резерв всегда нулевой, чтобы будущие расширения требовали явного согласования. */ + for (size_t i = 0U; i < count; ++i) setp_put_u16(out + SET_GAS_WATCH_CONFIG_HEADER + 2U * i, addresses[i]); /* Сериализует по два байта на адрес без перестановки списка. */ + return SET_GAS_WATCH_CONFIG_HEADER + 2U * count; /* Возвращает фактический размер payload, а не вместимость буфера. */ +} /* Завершает кодирование команды настройки. */ + +int set_gas_watch_apply(set_gas_watch_t *watch, const pcan_gas_map_t *map, const uint8_t *payload, size_t size) /* Транзакционно заменяет список после всех проверок; вызывающий удерживает общий lock. */ +{ /* Открывает применение новой конфигурации. */ + set_gas_watch_t proposed; /* Держит весь новый список отдельно от состояния, доступного сборщику. */ + if (watch == NULL || !config_decode(payload, size, &proposed)) return SET_GAS_WATCH_INVALID; /* Неверный пакет не меняет действующий список и расписание. */ + if (watch->config_id == proposed.config_id) { /* Обрабатывает повтор команды после потери подтверждения. */ + if (watch->count != proposed.count || watch->period_ms != proposed.period_ms) return SET_GAS_WATCH_CONFLICT; /* Запрещает изменение содержимого под тем же поколением. */ + for (size_t i = 0U; i < proposed.count; ++i) if (watch->address[i] != proposed.address[i]) return SET_GAS_WATCH_CONFLICT; /* Сравнивает также порядок адресов, определяющий смысл позиций. */ + return SET_GAS_WATCH_OK; /* Точный повтор не сбрасывает sequence и срок следующей выборки. */ + } /* Завершает идемпотентный путь повторного запроса. */ + if (watch->config_id != 0U && (uint32_t)(proposed.config_id - watch->config_id) >= 0x80000000UL) return SET_GAS_WATCH_CONFLICT; /* Отклоняет старые поколения по модульному порядку с полуинтервалом 2^31. */ + if (proposed.count > 0U) { /* Команда остановки не зависит от наличия карты или исправности источников. */ + if (!pcan_gas_map_validate(map)) return SET_GAS_WATCH_INVALID; /* Не допускает двоичный поиск по несортированной, перекрытой или повреждённой карте. */ + for (size_t i = 0U; i < proposed.count; ++i) { /* Проверяет доступность каждого выбранного слова до замены состояния. */ + const pcan_gas_region_t *region = pcan_gas_find(map, proposed.address[i]); /* Находит описание региона, не вызывая callback источника. */ + if (region == NULL) return SET_GAS_WATCH_NO_REG; /* Один неизвестный адрес отменяет всю перенастройку без частичной подписки. */ + if ((region->flags & PCAN_GAS_WRONLY) != 0U || (region->read == NULL && region->storage == NULL)) return SET_GAS_WATCH_ACCESS; /* Требует разрешённое чтение и реальный обработчик либо RAM. */ + } /* Завершает проверку полного набора выбранных адресов. */ + } /* Завершает проверку карты для непустой подписки. */ + *watch = proposed; /* Фиксирует целую проверенную конфигурацию; от конкурентного доступа защищает lock приложения. */ + return SET_GAS_WATCH_OK; /* Разрешает отправить полное подтверждение применённого списка. */ +} /* Завершает транзакцию настройки. */ + +size_t set_gas_watch_encode_ack(const set_gas_watch_t *watch, uint8_t *out, size_t capacity) /* Строит эхо из фактически применённого списка, а не из неподтверждённого запроса. */ +{ /* Открывает кодирование подтверждения. */ + if (watch == NULL) return 0U; /* Не читает поля отсутствующего экземпляра. */ + return set_gas_watch_request(watch->config_id, watch->period_ms, watch->address, watch->count, out, capacity); /* Делегирует формат единственному кодировщику конфигурации. */ +} /* Завершает кодирование подтверждения без отдельного wire-формата. */ + +int set_gas_watch_ack(const uint8_t *payload, size_t size, uint32_t config_id, uint16_t period_ms, const uint16_t *addresses, size_t count) /* Проверяет весь список, а не только количество принятых слов. */ +{ /* Открывает host-проверку подтверждения настройки. */ + uint8_t expected[SET_GAS_WATCH_CONFIG_MAX]; /* Ограниченный стековый буфер содержит каноническое представление ожидаемой команды. */ + size_t expected_size = set_gas_watch_request(config_id, period_ms, addresses, count, expected, sizeof(expected)); /* Строит ожидаемый пакет тем же C-кодировщиком. */ + return payload != NULL && expected_size != 0U && size == expected_size && memcmp(payload, expected, size) == 0; /* Принимает только побайтовое совпадение версии, поколения, периода и всех адресов. */ +} /* Завершает точную проверку эхо-ответа. */ + +bool set_gas_watch_due(const set_gas_watch_t *watch, uint32_t now_ms) /* Проверяет расписание захвата относительно локального времени MCU. */ +{ /* Открывает неблокирующую проверку таймера. */ + return active(watch) && (watch->scheduled == 0U || (uint32_t)(now_ms - watch->next_ms) < 0x80000000UL); /* Первая выборка немедленная; полуинтервал 2^31 корректно обрабатывает переполнение u32. */ +} /* Завершает проверку срока без изменения состояния. */ + +bool set_gas_watch_capture(set_gas_watch_t *watch, const pcan_gas_map_t *map, uint32_t now_ms, set_gas_watch_sample_t *sample) /* Снимает согласованный кэш в памяти под lock, предоставленным приложением. */ +{ /* Открывает захват одной самостоятельной выборки. */ + set_gas_watch_sample_t captured; /* Временная выборка не позволяет частично изменить выход при неверных аргументах. */ + if (!active(watch) || sample == NULL || !pcan_gas_map_validate(map)) return false; /* Отклоняет остановленный поток, отсутствующий выход и повреждённую карту. */ + memset(&captured, 0, sizeof(captured)); /* Ошибочные и неиспользуемые позиции заранее получают нулевые значения и признаки. */ + captured.config_id = watch->config_id; /* Закрепляет поколение списка вместе с набором значений. */ + captured.sequence = watch->sequence; /* Первая выборка имеет номер 0; номер увеличивается после успешного захвата структуры. */ + captured.timestamp_ms = now_ms; /* Фиксирует переданное время начала выборки, не время отправки пакета. */ + captured.count = watch->count; /* Закрепляет число позиций независимо от последующей перенастройки. */ + for (size_t i = 0U; i < watch->count; ++i) { /* Читает разрозненные GAS-адреса в согласованном порядке списка. */ + uint16_t value = 0U; /* Не позволяет неуспешному callback протащить мусор или частичное значение. */ + if (pcan_gas_read(map, watch->address[i], &value) == PCAN_GAS_OK) { /* Достоверность означает успешное чтение локального источника, не свежесть удалённого измерения. */ + captured.values[i] = value; /* Копирует прочитанное слово только после подтверждения источником. */ + captured.valid[i] = 1U; /* Отмечает в модели, что слово пригодно для графика и архива. */ + } /* При ошибке источник оставляет и значение, и признак нулевыми. */ + } /* Завершает чтение всех каналов даже при отказе одного из них. */ + *sample = captured; /* Передаёт неизменяемый по отношению к карте снимок приложениям-потребителям. */ + watch->sequence++; /* Учитывает каждый захват, в том числе потерянный позднее из-за занятой линии. */ + watch->next_ms = now_ms + watch->period_ms; /* Планирует следующий захват от текущего времени без пачки догоняющих выборок. */ + watch->scheduled = 1U; /* Включает проверку next_ms после первой выборки. */ + return true; /* Готовая выборка доступна независимо от ошибок отдельных регистров. */ +} /* Завершает захват; транспорт вызывается приложением после снятия lock. */ + +size_t set_gas_watch_encode_sample(const set_gas_watch_sample_t *sample, uint8_t *out, size_t capacity) /* Упаковывает сохранённую выборку без повторных обращений к источникам. */ +{ /* Открывает сериализацию пакета значений. */ + if (sample == NULL || out == NULL || sample->config_id == 0U || sample->count == 0U || sample->count > SET_GAS_WATCH_MAX) return 0U; /* Проверяет модель до вычисления размера и обращения к массивам. */ + size_t mask_size = ((size_t)sample->count + 7U) / 8U; /* Округляет число флагов до байтов, восемь каналов на один байт маски. */ + size_t values_offset = SET_GAS_WATCH_SAMPLE_HEADER + mask_size; /* Значения идут сразу после переменной по длине маски достоверности. */ + size_t total = values_offset + 2U * sample->count; /* Каждое значение занимает два байта без зависимости от выравнивания структур. */ + if (capacity < total) return 0U; /* Недостаточный выходной буфер остаётся полностью неизменным. */ + for (size_t i = 0U; i < sample->count; ++i) if (sample->valid[i] > 1U) return 0U; /* Запрещает неканонические признаки до записи заголовка. */ + setp_put_u16(out, SET_GAS_WATCH_VERSION); /* Сохраняет версию payload 2 в первых двух байтах. */ + setp_put_u16(out + 2U, sample->count); /* Помещает число слов перед поколением конфигурации. */ + setp_put_u32(out + 4U, sample->config_id); /* Позволяет клиенту отклонить пакет предыдущего списка той же длины. */ + setp_put_u32(out + 8U, sample->sequence); /* Номер захвата занимает байты 8..11 и передаётся без знакового преобразования. */ + setp_put_u32(out + 12U, sample->timestamp_ms); /* Время устройства в миллисекундах занимает байты 12..15. */ + memset(out + SET_GAS_WATCH_SAMPLE_HEADER, 0, mask_size); /* Обнуляет также свободные старшие биты последнего байта маски. */ + for (size_t i = 0U; i < sample->count; ++i) { /* Заполняет значения и соответствующие им биты одной позиции списка. */ + if (sample->valid[i] != 0U) out[SET_GAS_WATCH_SAMPLE_HEADER + i / 8U] |= (uint8_t)(1U << (i % 8U)); /* Младший бит байта соответствует первому из восьми каналов. */ + setp_put_u16(out + values_offset + 2U * i, sample->valid[i] != 0U ? sample->values[i] : 0U); /* Недостоверный канал всегда кодируется нулём независимо от содержимого модели. */ + } /* Завершает построение канонического payload выборки. */ + return total; /* Возвращает число готовых к передаче байтов без внешнего кадрирования. */ +} /* Завершает сериализацию самостоятельной выборки. */ + +int set_gas_watch_decode(const uint8_t *payload, size_t size, uint32_t expected_config_id, size_t expected_count, uint32_t *sequence, uint32_t *timestamp_ms, uint16_t *values, uint8_t *valid, size_t capacity) /* Проверяет полный пакет прежде, чем открыть его данным графика или архива. */ +{ /* Открывает стабильный host-декодер payload выборки. */ + if (payload == NULL || size < SET_GAS_WATCH_SAMPLE_HEADER || size > SET_GAS_WATCH_SAMPLE_MAX || expected_config_id == 0U || expected_count == 0U || expected_count > SET_GAS_WATCH_MAX) return -1; /* Исключает неверные границы и отсутствие активной конфигурации до чтения payload. */ + size_t count = setp_get_u16(payload + 2U); /* Читает число слов из проверенного фиксированного заголовка. */ + if (setp_get_u16(payload) != SET_GAS_WATCH_VERSION || setp_get_u32(payload + 4U) != expected_config_id || count != expected_count || count > capacity || values == NULL || valid == NULL) return -1; /* Отбрасывает устаревшую конфигурацию и неподходящие выходные массивы. */ + size_t mask_size = (count + 7U) / 8U; /* Вычисляет единственный допустимый размер маски для ожидаемого числа слов. */ + size_t values_offset = SET_GAS_WATCH_SAMPLE_HEADER + mask_size; /* Находит начало значений после bitmap в байтах. */ + if (size != values_offset + 2U * count) return -1; /* Не принимает ни усечённый пакет, ни добавленные после значений байты. */ + if (count % 8U != 0U && (payload[values_offset - 1U] >> (count % 8U)) != 0U) return -1; /* Требует нулевые неиспользуемые старшие биты маски последнего байта. */ + for (size_t i = 0U; i < count; ++i) { /* Сначала проверяет каноничность всех каналов, ничего не публикуя вызывающему. */ + if ((payload[SET_GAS_WATCH_SAMPLE_HEADER + i / 8U] & (1U << (i % 8U))) == 0U && setp_get_u16(payload + values_offset + 2U * i) != 0U) return -1; /* Ошибочный канал обязан содержать нулевое слово, иначе пакет отвергается целиком. */ + } /* Завершает полную проверку до первой записи в выходные аргументы. */ + for (size_t i = 0U; i < count; ++i) { /* Публикует проверенные значения и их достоверность в одинаковом порядке. */ + values[i] = setp_get_u16(payload + values_offset + 2U * i); /* Копирует сырое 16-битное слово без изменения знаковости. */ + valid[i] = (uint8_t)((payload[SET_GAS_WATCH_SAMPLE_HEADER + i / 8U] >> (i % 8U)) & 1U); /* Раскрывает один бит в 0 или 1 для простого ctypes/JNI ABI. */ + } /* Завершает публикацию массивов после успешной проверки пакета. */ + if (sequence != NULL) *sequence = setp_get_u32(payload + 8U); /* Возвращает номер захвата, если клиент запросил метаданные. */ + if (timestamp_ms != NULL) *timestamp_ms = setp_get_u32(payload + 12U); /* Возвращает приборное время без привязки к часам компьютера. */ + return (int)count; /* Положительный результат сообщает точное число достоверно разобранных позиций, включая помеченные ошибкой. */ +} /* Завершает единый C-декодер для всех языковых портов. */ diff --git a/c/set-protocol/src/set_igbt_realtime.c b/c/set-protocol/src/set_igbt_realtime.c new file mode 100644 index 0000000..830a93f --- /dev/null +++ b/c/set-protocol/src/set_igbt_realtime.c @@ -0,0 +1,109 @@ +#include "set_igbt_realtime.h" /* Подключает независимый протокол аппаратных импульсов с временами в наносекундах. */ +#include /* Использует определённое обнуление состояния и сравнение подготовленных конфигураций. */ +void set_igbt_rt_init(set_igbt_rt *s, const set_igbt_rt_port *port, void *context) /* Инициализация выполняется только при остановленном аппаратном порте. */ +{ /* Начинает создание полностью выключенного сервиса версии 4. */ + unsigned i; /* Обходит восемь каналов в порядке битов протокола. */ + memset(s, 0, sizeof(*s)); s->port = *port; s->context = context; /* Сбрасывает также padding, чтобы последующее сравнение конфигураций было воспроизводимым. */ + for (i = 0; i < SET_IGBT_RT_CHANNELS; ++i) { /* Назначает профиль 1SP0635 каждому независимому каналу. */ + set_igbt_rt_channel *c = &s->staged.channel[i]; /* Изменяет только подготовленные задания, не включая выходы. */ + c->flags = 3; c->edges = 3; /* Разрешает обработку Vin и выдачу ACK на оба фронта после явного применения. */ + c->on_delay = c->off_delay = 250; c->on_width = c->off_width = 700; /* Использует типичные задержку и ширину из паспорта 1SP0635x2x1-33, нс. */ + c->tx_width = 10000; /* Одиночный физический TX по умолчанию длится 10 мкс, заданные как 10000 нс. */ + } /* Завершает подготовку восьми одинаковых, но независимо изменяемых каналов. */ + s->active = s->staged; /* Начальный применённый профиль также выключен, поэтому инициализация не создаёт фронтов. */ +} /* Завершает инициализацию без вызова аппаратных callbacks. */ +unsigned set_igbt_rt_validate(const set_igbt_rt_config *cfg) /* Проверяет полный профиль перед атомарным применением оборудования. */ +{ /* Все проверки выполняются до остановки или перенастройки работающих таймеров. */ + unsigned i; /* Номер проверяемого независимого канала. */ + if (!cfg || cfg->enabled > 1 || cfg->source > 1 || cfg->tx > 255 || cfg->fault > 255) return 3; /* Отклоняет неверные переключатели и маски шире восьми каналов кодом Illegal Value. */ + for (i = 0; i < SET_IGBT_RT_CHANNELS; ++i) { /* Проверяет даже выключенные каналы, чтобы последующее разрешение имело однозначные параметры. */ + const set_igbt_rt_channel *c = &cfg->channel[i]; /* Читает подготовленные поля без изменения профиля. */ + if (c->flags > 7 || c->mode > 3 || c->edges > 3 || c->compensation > 1000) return 3; /* Ограничивает битовые поля и измеренную компенсацию величиной 1000 нс. */ + if (c->on_delay < SET_IGBT_RT_MIN_NS || c->on_delay > SET_IGBT_RT_MAX_NS || c->off_delay < SET_IGBT_RT_MIN_NS || c->off_delay > SET_IGBT_RT_MAX_NS) return 3; /* Задержки находятся в аппаратном диапазоне 50…60000 нс. */ + if (c->on_width < SET_IGBT_RT_MIN_NS || c->on_width > SET_IGBT_RT_MAX_NS || c->off_width < SET_IGBT_RT_MIN_NS || c->off_width > SET_IGBT_RT_MAX_NS) return 3; /* Любая ширина ACK также должна выдерживать ограничения аппаратных compare. */ + if (c->tx_width < SET_IGBT_RT_MIN_NS || c->tx_width > SET_IGBT_RT_MAX_NS || c->fault_width > SET_IGBT_RT_MAX_NS) return 3; /* TX длится 50…60000 нс; нулевой FAULT означает удержание ответа. */ + if (c->fault_width && c->fault_width < SET_IGBT_RT_MIN_NS) return 3; /* Запрещает конечный FAULT короче минимального аппаратного импульса. */ + if ((c->edges & 1) && c->on_delay < c->compensation + SET_IGBT_RT_MIN_NS) return 3; /* После вычитания измеренной задержки входа для ON остаётся минимум 50 нс таймерного интервала. */ + if ((c->edges & 2) && c->off_delay < c->compensation + SET_IGBT_RT_MIN_NS) return 3; /* Применяет то же ограничение к реально разрешённому OFF-фронту. */ + if (!cfg->source && c->edges == 3 && (c->on_delay != c->off_delay || c->on_width != c->off_width)) return 3; /* Один аппаратный триггер обоих фронтов требует одинаковых ON/OFF; обработчик ISR не подменяет точные времена. */ + if (cfg->source && (cfg->tx & (1u << i)) && !(c->flags & 1)) return 3; /* Удержание физического TX допускается только у разрешённого передающего канала. */ + } /* Завершает предварительную проверку без побочных эффектов. */ + return 0; /* Разрешает аппаратному порту применить весь согласованный профиль. */ +} /* Завершает проверку протокольных и общих аппаратных ограничений. */ +unsigned set_igbt_rt_read(void *context, uint16_t offset, uint16_t count, uint16_t *out) /* Возвращает задания и один согласованный аппаратный снимок. */ +{ /* Чтение одинаково доступно в выбранном IGBT и в остальных режимах платы. */ + set_igbt_rt *s = (set_igbt_rt *)context; set_igbt_rt_snapshot snap = {0}; /* Снимок по умолчанию нулевой, включая отсутствующие аппаратные счётчики. */ + uint16_t words[SET_IGBT_RT_WORDS] = {0}; unsigned i; /* Формирует прежние 112 слов без увеличения максимального кадра RTU. */ + if (!s || !out || !count || (uint32_t)offset + count > SET_IGBT_RT_WORDS) return 2; /* Проверяет весь диапазон до обращения к аппаратному порту. */ + s->port.sample(s->context, &snap); /* Читает GPIO и счётчики, не формируя импульсы и не сбрасывая события. */ + words[0] = 0x4947; words[1] = 4; words[2] = s->active.enabled; /* Сигнатура IG и версия 4 запрещают старому GUI трактовать наносекунды как миллисекунды. */ + words[3] = snap.tx; words[4] = snap.rx; words[5] = (uint16_t)(31u | (memcmp(&s->staged, &s->active, sizeof(s->active)) ? 0x8000u : 0u)); /* Возможности дополняет старший бит наличия неприменённых заданий. */ + words[6] = s->staged.fault; words[7] = SET_IGBT_RT_MIN_NS; words[8] = SET_IGBT_RT_MAX_NS; /* Публикует подготовленную маску FAULT и диапазон времён в наносекундах. */ + words[10] = SET_IGBT_RT_CHANNELS; words[11] = 0; words[12] = s->staged.source; /* Восемь каналов; код единиц 0 означает наносекунды только для версии 4. */ + words[13] = s->active.tx; words[14] = snap.busy; words[15] = 12; /* Возвращает удерживаемый TX, занятость одиночных импульсов и размер блока канала. */ + for (i = 0; i < SET_IGBT_RT_CHANNELS; ++i) { /* Упаковывает каждый канал без зависимости от выравнивания структуры C. */ + const set_igbt_rt_channel *c = &s->staged.channel[i]; unsigned b = 16 + 12 * i; /* Вычисляет протокольное смещение канала в 16-битных словах. */ + words[b] = c->flags; words[b + 1] = c->mode; words[b + 2] = c->on_delay; words[b + 3] = c->on_width; /* Сохраняет прежние смещения флагов, режима и ON-времён. */ + words[b + 4] = c->off_delay; words[b + 5] = c->off_width; words[b + 6] = c->tx_width; /* OFF и физический TX передаются целыми наносекундами. */ + words[b + 7] = c->edges; words[b + 8] = c->fault_width; words[b + 9] = snap.count[i]; /* Маска фронтов, FAULT и счётчик фактически захваченных событий. */ + words[b + 10] = c->compensation; words[b + 11] = snap.overrun[i]; /* Последние слова версии 4 означают компенсацию, нс, и потери захвата, а не остатки миллисекунд. */ + words[9] = (uint16_t)(words[9] + snap.count[i]); /* Общий счётчик складывает события восьми каналов по модулю 65536. */ + } /* Завершает сборку одного снимка регистрами. */ + for (i = 0; i < count; ++i) out[i] = words[offset + i]; /* Копирует только предварительно проверенный диапазон в буфер вызывающего транспорта. */ + return 0; /* Подтверждает чтение без изменения заданий или выхода. */ +} /* Завершает обработчик FC03 для аппаратного IGBT. */ +unsigned set_igbt_rt_write(void *context, uint16_t offset, uint16_t value) /* Разделяет подготовку конфигурации и команды с физическим действием. */ +{ /* Вызывается последовательно из общего сервера, аппаратные ISR меняют только счётчики. */ + set_igbt_rt *s = (set_igbt_rt *)context; unsigned error, i; /* Общий код ошибки не скрывает аппаратный отказ настройки. */ + if (!s) return 3; /* Не обращается к callbacks отсутствующего экземпляра. */ + if (offset == 2 && value == 0) { s->port.stop(s->context); s->active.enabled = s->staged.enabled = 0; s->active.tx = s->staged.tx = 0; if (!set_igbt_rt_validate(&s->staged)) s->active = s->staged; return 0; } /* Явный останов всегда доступен; корректные выключенные задания сохраняются без включения оборудования. */ + if (!s->port.selected(s->context)) return 6; /* Запрещает запуск и подготовку аппаратного IGBT из другого режима платы. */ + if (offset >= 16) { /* Поканальные записи изменяют только подготовленную копию до команды применения. */ + unsigned ch = (offset - 16) / 12, field = (offset - 16) % 12; uint16_t *target = 0; /* Раскладывает смещение на номер канала и поле, не полагаясь на layout структуры. */ + set_igbt_rt_channel *c; /* Выбирается только после проверки границ массива каналов. */ + if (ch >= SET_IGBT_RT_CHANNELS) return 2; /* Область за восьмым каналом не должна изменять память сервиса. */ + c = &s->staged.channel[ch]; /* Выбирает подготовленный канал только после проверки границ массива. */ + switch (field) { /* Явно сопоставляет доступные на запись поля протоколу версии 4. */ + case 0: if (value > 7) return 3; target = &c->flags; break; /* Разрешает только три флага TX/RX/инверсии ACK. */ + case 1: if (value > 3) return 3; target = &c->mode; break; /* Ограничивает режимы автоматическим ACK, 0, 1 и пропуском ответа. */ + case 2: target = &c->on_delay; break; /* Подготавливает задержку ACK после фронта ON, нс. */ + case 3: target = &c->on_width; break; /* Подготавливает ширину ACK после фронта ON, нс. */ + case 4: target = &c->off_delay; break; /* Подготавливает задержку ACK после фронта OFF, нс. */ + case 5: target = &c->off_width; break; /* Подготавливает ширину ACK после фронта OFF, нс. */ + case 6: target = &c->tx_width; break; /* Подготавливает длительность одиночного физического TX, нс. */ + case 7: if (value > 3) return 3; target = &c->edges; break; /* Выбирает ни одного, ON, OFF либо оба фронта внешнего Vin. */ + case 8: target = &c->fault_width; break; /* Нуль означает удержание FAULT; остальные допустимые значения задают длительность в нс. */ + case 10: if (value > 1000) return 3; target = &c->compensation; break; /* Измеренная компенсация входного тракта не превышает 1000 нс. */ + default: return 2; /* Счётчики и диагностика потерь доступны только на чтение. */ + } /* Завершает выбор единственного изменяемого подготовленного поля. */ + if ((field >= 2 && field <= 6) && (value < SET_IGBT_RT_MIN_NS || value > SET_IGBT_RT_MAX_NS)) return 3; /* Проверяет диапазон наносекунд до изменения задания. */ + if (field == 8 && (value > SET_IGBT_RT_MAX_NS || (value && value < SET_IGBT_RT_MIN_NS))) return 3; /* Разрешает только удерживаемый либо воспроизводимый аппаратный FAULT. */ + *target = value; return 0; /* Сохраняет подготовленное значение, не перенастраивая ни один работающий таймер. */ + } /* Завершает обработку поканальных заданий. */ + switch (offset) { /* Общие регистры отделяют подготовку масок от физического пуска. */ + case 2: /* Единица в регистре включения является завершающей командой применения всего профиля. */ + if (value != 1) return 3; /* Отклоняет неизвестную команду включения до изменения подготовленного профиля. */ + s->staged.enabled = 1; /* Подготавливает включение только после проверки значения команды. */ + error = set_igbt_rt_validate(&s->staged); if (error) return error; /* Проверяет весь профиль до передачи его аппаратуре. */ + error = s->port.apply(s->context, &s->staged); if (error) return error; /* Аппаратный порт также проверяет выполнимость перед изменением выходов. */ + s->active = s->staged; return 0; /* Подтверждает включение только после успешной настройки всех восьми каналов. */ + case 6: if (value > 255) return 3; s->staged.fault = value; return 0; /* Маска неисправностей применяется вместе с последней командой включения. */ + case 9: if (value) return 3; s->port.clear(s->context); return 0; /* Нулевая запись очищает счётчики без изменения формы сигнала. */ + case 12: if (value > 1) return 3; s->staged.source = value; return 0; /* Выбор внешнего Vin либо физического TX вступает в силу при применении. */ + case 13: { /* Постоянные уровни TX доступны только в уже применённом режиме физического генератора. */ + set_igbt_rt_snapshot snap = {0}; /* Получает занятость аппаратных импульсов перед ручным изменением уровней. */ + if (value > 255) return 3; /* Маска ручных уровней не может выходить за восемь физических каналов. */ + if (!s->active.enabled || !s->active.source) return 6; /* Исключает ручное управление ACK и выключенными выходами. */ + s->port.sample(s->context, &snap); if (snap.busy) return 6; /* Не обрывает аппаратный импульс командой удержания уровня. */ + for (i = 0; i < SET_IGBT_RT_CHANNELS; ++i) if ((value & (1u << i)) && !(s->active.channel[i].flags & 1)) return 3; /* Удерживаемые высокие уровни требуют разрешённого TX. */ + s->port.levels(s->context, (uint8_t)value); s->active.tx = s->staged.tx = value; return 0; /* Изменяет только постоянные уровни, сохраняя применённые длительности. */ + } /* Завершает команду ручных уровней генератора. */ + case 14: /* Одиночный импульс запускается только из согласованного применённого профиля. */ + if (!value || value > 255) return 3; /* Требует хотя бы один из восьми физических каналов без старших битов. */ + if (!s->active.enabled || !s->active.source) return 6; /* Импульс возможен только у включённого аппаратного генератора. */ + if (memcmp(&s->staged, &s->active, sizeof(s->active)) != 0 || (value & s->active.tx)) return 6; /* Запрещает пуск с неприменёнными заданиями и повторный фронт при удерживаемом TX=1. */ + for (i = 0; i < SET_IGBT_RT_CHANNELS; ++i) if ((value & (1u << i)) && !(s->active.channel[i].flags & 1)) return 6; /* Предварительно проверяет все выбранные каналы до первого физического пуска. */ + return s->port.pulse(s->context, (uint8_t)value); /* Старт разрешённых каналов выполняется аппаратным портом, GUI не отмеряет длительность. */ + default: return 2; /* Версия, возможности, снимки и прежние глобальные миллисекундные поля недоступны на запись. */ + } /* Завершает маршрутизацию команды общего регистра. */ +} /* Завершает обработчик FC06 аппаратного IGBT. */ diff --git a/c/set-protocol/src/set_invertor_gas.c b/c/set-protocol/src/set_invertor_gas.c new file mode 100644 index 0000000..5f2c90d --- /dev/null +++ b/c/set-protocol/src/set_invertor_gas.c @@ -0,0 +1,175 @@ +#include "set_invertor_gas.h" /* Переиспользуем общий регистровый и масочный GAS вместо нового wire-кодека. */ +#include "pcan_id.h" /* Поля идентификатора упаковываются и проверяются существующей реализацией ProtoCAN. */ +#include /* NULL позволяет явно различать отсутствующие callbacks и выходные кадры. */ +typedef struct { /* Небольшая локальная транзакция существует только во время обработки одного CAN-кадра. */ + const set_invertor_gas_port_t *port; /* Provider остаётся единственным владельцем состояния изделия. */ + uint16_t addresses[PCAN_GAS_REGS_PER_FRAME]; /* Восемь октетов типа 0x3 содержат максимум четыре адресованных значения. */ + uint16_t values[PCAN_GAS_REGS_PER_FRAME]; /* Сначала собираем все изменения без обращения к write-provider. */ + unsigned count; /* Количество подготовленных слов не превышает фиксированные массивы. */ +} invertor_transaction; /* Нет глобального состояния, heap или обращения к HAL из переносимого модуля. */ +int32_t set_invertor_gas_register(unsigned slot, unsigned word) /* Отображение одинаково для прошивки и всех клиентов общей библиотеки. */ +{ /* Word0 содержит маску и исключён из полезной регистровой карты. */ + if (slot >= SET_INVERTOR_GAS_SLOT_COUNT || word == 0U || word > SET_INVERTOR_GAS_WORDS_PER_SLOT) { return -1; } /* Отвергаем несуществующие координаты до вычисления смещения. */ + return (int32_t)(slot * SET_INVERTOR_GAS_WORDS_PER_SLOT + word - 1U); /* Три значения каждого слота занимают три последовательных регистра. */ +} /* Максимальная координата слот 249/Word3 соответствует регистру 749. */ +int set_invertor_gas_coordinate(unsigned address, uint16_t *slot, uint16_t *word) /* Переводим отдельный регистр в слот и полезное слово без усечения адреса. */ +{ /* Проверяем оба выхода до первого изменения состояния вызывающего кода. */ + if (address >= SET_INVERTOR_GAS_REGISTER_COUNT || slot == NULL || word == NULL || slot == word) { return 0; } /* Алиас двух выходов не может дать корректную пару координат. */ + *slot = (uint16_t)(address / SET_INVERTOR_GAS_WORDS_PER_SLOT); /* Целая часть выбирает один из 250 слотов отдельного узла. */ + *word = (uint16_t)(1U + address % SET_INVERTOR_GAS_WORDS_PER_SLOT); /* Остаток выбирает Word1…Word3, пропуская служебную маску. */ + return 1; /* Оба выхода опубликованы после проверки всех аргументов. */ +} /* Заканчиваем единственную общую формулу преобразования координат. */ +uint32_t set_invertor_gas_request_id(unsigned message_type, unsigned address, unsigned route) /* Функция не назначает другой DeviceID по номеру слота. */ +{ /* Ноль является признаком отказа, а не допустимым ID этого устройства. */ + pcan_id_t id = {0}; /* Заполняем официальную структуру общего кодека без собственных сдвигов битов. */ + if (route > PCAN_ROUTE_FROM_DEVICE || address > UINT16_MAX) { return 0U; } /* Не допускаем усечения маршрута или адреса. */ + if (message_type == PCAN_MSG_GAS_SLOT) { /* Слотный тип проверяется по собственной ёмкости, а не по числу регистров. */ + if (address >= SET_INVERTOR_GAS_SLOT_COUNT) { return 0U; } /* Адрес 250 уже находится за выделенным блоком 0…249. */ + return pcan_gas_slot_id(SET_INVERTOR_DEVICE_TYPE, SET_INVERTOR_DEVICE_ID, address, route); /* Существующий кодек 0x4 задаёт нужные поля без нового формата. */ + } /* Другие типы не должны автоматически трактоваться как слоты. */ + if (message_type != PCAN_MSG_GAS || address >= SET_INVERTOR_GAS_REGISTER_COUNT) { return 0U; } /* Для типа 0x3 разрешены только 750 отдельных регистров. */ + id.priority = PCAN_PRIORITY_STANDARD; /* Обычная настройка и телеметрия используют стандартный приоритет протокола. */ + id.route = (uint_least8_t)route; /* Route явно различает команду верхнего уровня и ответ прибора. */ + id.device_type = SET_INVERTOR_DEVICE_TYPE; /* Пользователь выбрал класс устройств 0x7. */ + id.device_id = SET_INVERTOR_DEVICE_ID; /* Проверенный свободный экземпляр 0xE не меняет назначений 0xD/0xF. */ + id.msg_type = PCAN_MSG_GAS; /* Тип 0x3 обозначает отдельные регистры согласно новой инструкции Templates. */ + id.msg_body = (uint16_t)address; /* Уже проверенное значение помещается в 16-битный MsgBody. */ + return pcan_id_pack(&id); /* Публикуем ID единственной реализацией существующей битовой раскладки. */ +} /* Конец построения адресуемого идентификатора. */ +static pcan_gas_status_t ReadRegister(const pcan_gas_region_t *region, uint16_t offset, uint16_t *value) /* Связываем общий GAS-регион с данными приложения. */ +{ /* Offset региона равен адресу, поскольку начало отдельной карты равно нулю. */ + invertor_transaction *transaction = (invertor_transaction *)region->user; /* Контекст принадлежит только текущему кадру. */ + if (transaction->port->read == NULL || transaction->port->read(transaction->port->context, offset, value) != 0) { return PCAN_GAS_NO_REG; } /* Недоступное или недостоверное значение останавливает последовательное чтение. */ + return PCAN_GAS_OK; /* Достоверный ноль остаётся обычным успешным результатом provider. */ +} /* Чтение не обращается к write-provider и не изменяет уставки. */ +static pcan_gas_status_t StageRegister(const pcan_gas_region_t *region, uint16_t offset, uint16_t value) /* Откладываем применение всего входного блока до завершения общего декодера. */ +{ /* Callback вызывается существующим pcan_gas_handle для каждого разобранного слова. */ + invertor_transaction *transaction = (invertor_transaction *)region->user; /* Указатель не сохраняется за пределами текущего вызова. */ + if (transaction->port->write == NULL) { return PCAN_GAS_READ_ONLY; } /* Отсутствующий write-provider означает явный запрет записи. */ + if (transaction->count >= PCAN_GAS_REGS_PER_FRAME) { return PCAN_GAS_REJECTED; } /* Фиксированный массив не может переполниться от ошибочного callback. */ + transaction->addresses[transaction->count] = offset; /* Запоминаем отдельный логический адрес без арифметики указателей RAM. */ + transaction->values[transaction->count] = value; /* Значение ещё не попадает в рабочее состояние устройства. */ + transaction->count++; /* Следующее слово использует следующую свободную позицию локальной транзакции. */ + return PCAN_GAS_OK; /* Успех означает подготовку, а окончательное применение происходит после проверки всего кадра. */ +} /* Конец подготовки одного слова. */ +static int HandleRegisters(const set_invertor_gas_port_t *port, const pcan_frame_t *request, pcan_frame_t *response) /* Используем регистровый GAS 0x3 без повторного endian-разбора payload. */ +{ /* Все локальные структуры живут до возвращения общего обработчика. */ + invertor_transaction transaction = {0}; /* Пустая транзакция не может случайно повторить предыдущую запись. */ + pcan_gas_region_t region = {0}; /* Один логический регион не требует физического массива из 750 слов. */ + pcan_gas_map_t map; /* Карта ссылается на локальный регион только на время обработки. */ + pcan_frame_t out = {0}; /* Ошибка или запись не изменяет переданный вызывающим выходной кадр. */ + transaction.port = port; /* Все callbacks используют один согласованный источник данных приложения. */ + region.base = SET_INVERTOR_GAS_REGISTER_FIRST; /* Нулевое начало относится только к отдельному узлу инвертора 7/E. */ + region.count = SET_INVERTOR_GAS_REGISTER_COUNT; /* Последний действующий регистр имеет адрес 0x02ED, то есть 749. */ + region.read = ReadRegister; /* Общая библиотека проверяет диапазон прежде, чем читать приложение. */ + region.write = StageRegister; /* Ни одно слово не применяется до окончания подготовки всего блока. */ + region.user = &transaction; /* Provider получает контекст без глобальной памяти и зависимостей от ОС. */ + map.regions = ®ion; /* Единственный регион не пересекается с картами других CAN-узлов. */ + map.count = 1U; /* Карта содержит ровно один подключённый диапазон значений. */ + if (request->dlc == 0U) { /* Чтение использует стандартное правило ответа до четырёх последовательных регистров. */ + if (response == NULL || !pcan_gas_handle(&map, request, &out)) { return -1; } /* Пустой или недоступный диапазон не превращается в фиктивный ответ. */ + *response = out; return 1; /* Публикуем полностью сформированный существующим кодеком ответ. */ + } /* Непустой payload далее является только запросом записи. */ + if (request->dlc > PCAN_DATA_MAX || (request->dlc & 1U) != 0U) { return -1; } /* Отбрасываем нечётную длину и превышение восьми октетов до подготовки слов. */ + (void)pcan_gas_handle(&map, request, &out); /* Весь wire-пакет разбирает тот же кодек, который используется другими устройствами. */ + if (port->write == NULL || transaction.count != request->dlc / 2U) { return -1; } /* Частично попавший в карту блок не меняет даже свои первые корректные адреса. */ + return port->write(port->context, transaction.addresses, transaction.values, transaction.count) == 0 ? 0 : -1; /* Provider проверяет весь набор прав/значений и применяет его одним вызовом без скрытого ACK. */ +} /* Конец регистрового пути с единым состоянием приложения. */ +static int ReadSlot(void *context, uint16_t slot, uint16_t words[4]) /* Масочный ответ проецирует те же значения в Word1…Word3. */ +{ /* Word0 формируется только из реально прочитанных значений. */ + const set_invertor_gas_port_t *port = (const set_invertor_gas_port_t *)context; /* Указатель относится к тому же provider, что используется обычным GAS. */ + unsigned word; /* Индекс перебирает три полезных позиции, исключая маску. */ + if (slot >= SET_INVERTOR_GAS_SLOT_COUNT || port->read == NULL) { return -1; } /* Слот вне выделенного блока либо отсутствующий источник не порождает нулевую телеметрию. */ + words[0] = 0U; /* До успешного чтения ни одно поле не отмечено достоверным. */ + for (word = 1U; word <= SET_INVERTOR_GAS_WORDS_PER_SLOT; ++word) { /* Каждое полезное слово получает независимую проверку доступности. */ + uint16_t value = 0U; /* Неиспользуемое место кадра заполняется нулём без утверждения его достоверности. */ + const uint16_t address = (uint16_t)set_invertor_gas_register(slot, word); /* Проверенные координаты отображаются единственной общей формулой. */ + words[word] = 0U; /* Не допускаем утечки неинициализированного значения в ответ CAN. */ + if (port->read(port->context, address, &value) == 0) { /* Только положительный результат provider разрешает соответствующий бит. */ + words[0] |= (uint16_t)(1U << word); /* Биты 1…3 имеют смысл, заданный новым контрактом GAS SLOT 0x4. */ + words[word] = value; /* Сохраняем достоверное значение, в том числе корректный числовой ноль. */ + } /* Недоступный сосед не делает доступные значения ошибочными. */ + } /* Полностью неподключённый слот имеет пустую маску и не публикуется. */ + return words[0] != 0U ? 0 : -1; /* Общий кодек отправляет только ответ с непустой разрешённой маской. */ +} /* Чтение слота не создаёт второе хранилище значений. */ +static int WriteSlot(void *context, uint16_t slot, const uint16_t words[4]) /* Запись передаёт provider только выбранные маской позиции. */ +{ /* Предварительное чтение соседних readonly-полей не требуется. */ + const set_invertor_gas_port_t *port = (const set_invertor_gas_port_t *)context; /* Используем единственный источник состояния обоих типов GAS. */ + uint16_t addresses[PCAN_GAS_SLOT_DATA_WORDS], values[PCAN_GAS_SLOT_DATA_WORDS]; /* Один слот содержит максимум три изменяемых значения. */ + unsigned count = 0U, word; /* Подготавливаем компактный список только отмеченных слов. */ + if (slot >= SET_INVERTOR_GAS_SLOT_COUNT || port->write == NULL) { return -1; } /* Слот вне диапазона и отсутствие права записи не вызывают приложение. */ + for (word = 1U; word <= SET_INVERTOR_GAS_WORDS_PER_SLOT; ++word) { /* Маска уже полностью проверена общим кодеком 0x4. */ + if ((words[0] & (1U << word)) != 0U) { /* Неотмеченные поля сохраняются и не участвуют в проверке прав записи. */ + addresses[count] = (uint16_t)set_invertor_gas_register(slot, word); /* Переводим полезное слово в общий регистровый адрес. */ + values[count] = words[word]; /* Значение передаётся без изменения знака или масштаба поля. */ + count++; /* Число выбранных позиций ограничено тремя размерами маски. */ + } /* readonly-сосед не запрещает запись другой отмеченной позиции слота. */ + } /* До этого места ни одно значение приложения не изменялось. */ + return port->write(port->context, addresses, values, count) == 0 ? 0 : -1; /* Provider целиком проверяет выбранную транзакцию перед применением. */ +} /* Успех записи не создаёт не предусмотренный базовым протоколом ответ ACK. */ +int set_invertor_gas_handle(const set_invertor_gas_port_t *port, const pcan_frame_t *request, pcan_frame_t *response) /* Публичный диспетчер выбирает формат исключительно по MsgType. */ +{ /* Все проверки адреса узла выполняются раньше callbacks приложения. */ + pcan_id_t id; /* Поля извлекает существующая общая реализация ProtoCAN. */ + pcan_gas_slot_frame_t slot_request = {0}, slot_response = {0}; /* Масочный путь переиспользует готовый тип независимого Classic CAN-кодека. */ + pcan_gas_slot_port_t slot_port; /* Локальный адаптер соединяет три значения слота с единой картой. */ + pcan_frame_t out = {0}; /* Ошибка оставляет выходной кадр вызывающего без изменений. */ + unsigned i; int result; /* Размеры всех копируемых буферов заранее ограничены восемью октетами. */ + if (port == NULL || request == NULL || request->dlc > PCAN_DATA_MAX || (request->id & ~PCAN_ID_MASK) != 0U || (request->flags & PCAN_FLAG_IDE) == 0U || (request->flags & (PCAN_FLAG_RTR | PCAN_FLAG_ERR)) != 0U) { return -1; } /* Отвергаем нецелевые типы физических кадров и неверный размер до разбора данных. */ + pcan_id_unpack(request->id, &id); /* Не дублируем битовые сдвиги адресации в адаптере изделия. */ + if (id.device_type != SET_INVERTOR_DEVICE_TYPE || id.device_id != SET_INVERTOR_DEVICE_ID || id.route != PCAN_ROUTE_FROM_PM) { return -1; } /* Ответы других приборов и запросы к соседям не могут менять состояние инвертора. */ + if (id.msg_type == PCAN_MSG_GAS) { return HandleRegisters(port, request, response); } /* Тип 0x3 интерпретирует MsgBody как отдельный регистр. */ + if (id.msg_type != PCAN_MSG_GAS_SLOT || id.msg_body >= SET_INVERTOR_GAS_SLOT_COUNT || (request->dlc == 0U && response == NULL)) { return -1; } /* Тип 0x4 использует только выделенные 250 слотов; других форматов или fallback нет. */ + slot_port.context = (void *)port; /* Callback не изменяет структуру порта и не сохраняет указатель после возврата. */ + slot_port.read = ReadSlot; /* Общий слотный кодек получает маску достоверности от нашего отображения данных. */ + slot_port.write = WriteSlot; /* Общая проверка wire-маски предшествует вызову прикладной записи. */ + slot_request.id = request->id; /* Адрес узла и MsgType сохраняются без повторной упаковки. */ + slot_request.flags = request->flags; /* Служебные признаки уже проверены публичной границей. */ + slot_request.dlc = request->dlc; /* Длина остаётся количеством октетов физического кадра. */ + for (i = 0U; i < request->dlc; ++i) { slot_request.data[i] = request->data[i]; } /* Копируем готовые октеты, не разбирая их вторым endian-кодеком. */ + result = pcan_gas_slot_handle_address(SET_INVERTOR_DEVICE_TYPE, SET_INVERTOR_DEVICE_ID, &slot_port, &slot_request, &slot_response); /* Существующий C-кодек проверяет маску и строит ответ 0x4. */ + if (result == 1) { /* Только завершённое чтение публикует CAN-ответ. */ + out.id = slot_response.id; out.flags = (uint8_t)slot_response.flags; out.dlc = (uint8_t)slot_response.dlc; /* Переносим проверенный транспортный результат без изменения его смысла. */ + for (i = 0U; i < out.dlc; ++i) { out.data[i] = (uint8_t)slot_response.data[i]; } /* Восемь готовых октетов копируются в обычный кадр проекта STM32/host. */ + *response = out; /* Выход изменяется только после успешного выполнения всех общих проверок. */ + } /* Запись и ошибка сохраняют предыдущий выход вызывающего кода. */ + return result; /* 1 означает ответ, 0 — запись, -1 — отказ без изменения соседнего протокольного профиля. */ +} /* Конец общего адаптера двух GAS-интерфейсов одного инвертора. */ +unsigned set_invertor_gas_limit(unsigned message_type) /* Единый C-источник границ не допускает расхождения Python, прошивки и другого GUI. */ +{ /* Значение ноль обозначает неизвестный тип, а не пустой действующий блок. */ + if (message_type == PCAN_MSG_GAS) { return SET_INVERTOR_GAS_REGISTER_COUNT; } /* Обычный GAS адресует каждое из 750 значений отдельно. */ + return message_type == PCAN_MSG_GAS_SLOT ? SET_INVERTOR_GAS_SLOT_COUNT : 0U; /* Масочный GAS имеет 250 слотов, остальные типы не поддерживаются этим профилем. */ +} /* Завершаем получение размера карты без аппаратных зависимостей. */ +int set_invertor_gas_build(unsigned message_type, unsigned address, const uint16_t *words, unsigned count, uint32_t *identifier, uint8_t data[8]) /* Все endian-преобразования остаются внутри общего C-кодека. */ +{ /* При отказе не меняем ни идентификатор, ни выходные октеты вызывающего кода. */ + pcan_frame_t frame = {0}; uint_least8_t slot_data[8] = {0}; unsigned i; int length; /* Временный результат ограничен одним восьмиоктетным кадром. */ + const uint32_t id = set_invertor_gas_request_id(message_type, address, PCAN_ROUTE_FROM_PM); /* Проверяем тип, узел и соответствующую единицу адресации централизованно. */ + if (id == 0U || identifier == NULL || data == NULL || count > 4U || (count != 0U && words == NULL)) { return -1; } /* Проверяем буферы и число слов до обращения к существующим builders. */ + if (message_type == PCAN_MSG_GAS) { /* У типа 0x3 допустима запись от одного до четырёх последовательных значений. */ + if (address + count > SET_INVERTOR_GAS_REGISTER_COUNT) { return -1; } /* Даже начало последнего регистра не позволяет записать несуществующего соседа. */ + pcan_gas_regs_to_frame(&frame, id, (uint16_t)address, words, (uint16_t)count); length = frame.dlc; /* Полностью переиспользуем существующую сериализацию обычного GAS. */ + } else { /* Оставшийся проверенный тип равен GAS SLOT 0x4. */ + length = pcan_gas_slot_encode(words, count, slot_data); if (length < 0) { return -1; } /* Общий кодек требует четыре wire-слова с корректной маской либо пустой запрос. */ + for (i = 0U; i < (unsigned)length; ++i) { frame.data[i] = (uint8_t)slot_data[i]; } /* Копируем готовые октеты без повторного разбора расположения слов. */ + } /* После успешного кодирования можно публиковать результат вызывающему. */ + *identifier = id; for (i = 0U; i < 8U; ++i) { data[i] = frame.data[i]; } /* Выход всегда полностью инициализирован, включая неиспользуемый хвост. */ + return length; /* Ноль обозначает корректное чтение с DLC=0, отрицательное значение — отказ. */ +} /* Конец builder для тонких ctypes/JNI-портов. */ +int set_invertor_gas_decode(uint32_t identifier, unsigned flags, const uint8_t *data, unsigned length, unsigned metadata[2], uint16_t words[4]) /* Клиент получает уже проверенные значения без собственной битовой и endian-логики. */ +{ /* Временные выходы защищают данные вызывающего при некорректном ответе. */ + pcan_frame_t frame = {0}; pcan_id_t id; uint16_t decoded[4] = {0}; uint_least8_t slot_data[8]; unsigned i; int count; /* Все структуры локальны и имеют фиксированную вместимость. */ + if (metadata == NULL || words == NULL || data == NULL || length == 0U || length > 8U || flags > UINT8_MAX || (identifier & ~PCAN_ID_MASK) != 0U || (flags & PCAN_FLAG_IDE) == 0U || (flags & (PCAN_FLAG_RTR | PCAN_FLAG_ERR)) != 0U) { return -1; } /* Ответ должен быть непустым допустимым Extended data frame. */ + pcan_id_unpack(identifier, &id); /* Существующий кодек раскрывает поля идентификатора. */ + if (id.device_type != SET_INVERTOR_DEVICE_TYPE || id.device_id != SET_INVERTOR_DEVICE_ID || id.route != PCAN_ROUTE_FROM_DEVICE) { return -1; } /* Эхо запроса или ответ другого узла не обновляет телеметрию инвертора. */ + if (id.msg_type == PCAN_MSG_GAS) { /* Обычный GAS допускает один, два, три или четыре значения. */ + frame.id = identifier; frame.flags = (uint8_t)flags; frame.dlc = (uint8_t)length; /* Устанавливаем проверенные транспортные метаданные существующего frame-кодека. */ + for (i = 0U; i < length; ++i) { frame.data[i] = data[i]; } /* Исходные октеты не разбираются повторно на языковой стороне. */ + count = (int)pcan_gas_frame_to_regs(&frame, decoded, 4U); /* Длину и little-endian проверяет существующая реализация GAS. */ + if (count == 0 || (unsigned)id.msg_body + (unsigned)count > SET_INVERTOR_GAS_REGISTER_COUNT) { return -1; } /* Не публикуем нечётный payload либо блок, пересекающий конец 750 регистров. */ + } else if (id.msg_type == PCAN_MSG_GAS_SLOT && id.msg_body < SET_INVERTOR_GAS_SLOT_COUNT) { /* Масочный ответ проверяется по собственной карте 250 слотов. */ + for (i = 0U; i < length; ++i) { slot_data[i] = data[i]; } /* Передаём готовые октеты общему слотному декодеру. */ + count = pcan_gas_slot_decode_words(identifier, flags, slot_data, length, decoded); if (count != 4) { return -1; } /* Проверяем DLC=8 и допустимую непустую маску Word0. */ + } else { return -1; } /* Другой MsgType или несуществующий слот не вызывают fallback к обычным регистрам. */ + metadata[0] = id.msg_type; metadata[1] = id.msg_body; /* Публикуем тип и адрес только после проверки всего ответа. */ + for (i = 0U; i < (unsigned)count; ++i) { words[i] = decoded[i]; } /* Передаём только реально декодированные wire-слова. */ + return count; /* GUI работает со словами и типом, а не повторяет wire-протокол. */ +} /* Завершаем единый клиентский декодер нового профиля. */ diff --git a/c/set-protocol/src/ump_protocol.c b/c/set-protocol/src/ump_protocol.c index 0aaf7e9..e4e3cc2 100644 --- a/c/set-protocol/src/ump_protocol.c +++ b/c/set-protocol/src/ump_protocol.c @@ -18,7 +18,8 @@ unsigned ump_validate(unsigned fn, uint16_t a, uint16_t n, int can) return can ? ((a == UMP_FIRMWARE_INFO && n == UMP_FIRMWARE_INFO_WORDS) ? 0 : 2) : ((n && n <= UMP_FIRMWARE_INFO + UMP_FIRMWARE_INFO_WORDS - a) ? 0 : 2); if (can) return ((a == UMP_BASE && n == 16) || - (a == UMP_DATA && (n == 40 || n == 80 || n == 120 || n == 42 || n == 84)) || + /* Разрешает целые 12-словные записи v4 до 120 слов; размеры v2/v3 сохраняются для прежних устройств. */ + (a == UMP_DATA && (n == 40 || n == 80 || n == 42 || n == 84 || (n && n <= 120 && !(n % 12U)))) || (a == UMP_LIVE && n == 124)) ? 0 : 2; if (!n || n > 125) return 2; return ((a >= UMP_BASE && a < UMP_BASE+16 && n <= UMP_BASE+16-a) || diff --git a/c/set-protocol/tests/fixtures/deif-xdi-v1.tsv b/c/set-protocol/tests/fixtures/deif-xdi-v1.tsv new file mode 100644 index 0000000..3f8633e --- /dev/null +++ b/c/set-protocol/tests/fixtures/deif-xdi-v1.tsv @@ -0,0 +1,15 @@ +# COB-ID payload flags result RAW index subindex +201 0101300784030000 0 1 900 3001 7 +201 0101300284030000 0 1 900 3001 2 +201 0181300239FC0000 0 1 -967 3081 2 +201 0191300203FE0000 0 1 -509 3091 2 +201 01213402CEF70000 0 1 -2098 3421 2 +201 01313402D4FE0000 0 1 -300 3431 2 +30D 8D01300784030000 0 1 900 3001 7 +201 0101300784030000 1 -1 0 0 0 +201 0101300784030000 2 -1 0 0 0 +202 0101300784030000 0 -5 900 3001 7 +201 0181 0 -4 0 0 0 +701 05 0 2 0 0 0 +70D 00 0 2 0 0 0 +70D 7F 0 2 0 0 0 diff --git a/c/set-protocol/tests/fixtures/gas-watch-v2.json b/c/set-protocol/tests/fixtures/gas-watch-v2.json new file mode 100644 index 0000000..014e37f --- /dev/null +++ b/c/set-protocol/tests/fixtures/gas-watch-v2.json @@ -0,0 +1,13 @@ +{ + "description": "Общие эталонные байты GAS_WATCH2 для C, Python и JVM; порядок адресов сохраняет позиции значений.", + "version": 2, + "config_id": 305419896, + "period_ms": 100, + "addresses": [0, 1, 65281], + "request_hex": "0200640078563412030000000000010001ff", + "sequence": 4294967295, + "timestamp_ms": 4294967280, + "values": [123, 65534, 0], + "valid": [1, 1, 0], + "sample_hex": "0200030078563412fffffffff0ffffff037b00feff0000" +} diff --git a/c/set-protocol/tests/test_deif_xdi.c b/c/set-protocol/tests/test_deif_xdi.c new file mode 100644 index 0000000..39b253c --- /dev/null +++ b/c/set-protocol/tests/test_deif_xdi.c @@ -0,0 +1,26 @@ +#include "deif_xdi.h" /* Эталонные векторы проверяют непосредственно единственное C-ядро. */ +#include /* Любое расхождение байтов или сроков делает тест неуспешным. */ +#include /* Файловый ввод нужен только хостовому тесту, не переносимому ядру. */ +#include /* Выравнивание контекста обеспечивает стандартный хостовый allocator. */ +#include /* Сравниваются точные CAN-последовательности. */ +int main(int argc,char **argv) { /* Один набор векторов используется также Python и Android/JVM. */ + FILE *input; char line[160],hex[17]; unsigned id,flags,index,sub,byte,i; int expected,raw; int32_t meta[12]; uint8_t data[8]; size_t n; void *state; double value; setp_deif_frame_t out[16]; /* Все размеры ограничены форматом Classic CAN и ABI. */ + assert(argc==2); input=fopen(argv[1],"r"); assert(input); /* Путь fixtures передаётся сборщиком без зависимости от cwd. */ + while(fgets(line,sizeof line,input)) { /* Таблица содержит положительные и ошибочные кадры. */ + if(line[0]=='#') continue; assert(sscanf(line,"%x %16s %u %d %d %x %x",&id,hex,&flags,&expected,&raw,&index,&sub)==7); /* Это чтение текстовой fixture, а не второй CAN-декодер. */ + n=strlen(hex)/2U; for(i=0;i /* Release-сборка сохраняет проверки и сообщения ошибок. */ +#define CHECK(x) do { if (!(x)) { printf("gas_register:%d: %s\n", __LINE__, #x); return 1; } } while (0) /* Любое нарушение возвращает ненулевой код теста. */ +int main(void) /* Проверяем точечную запись, все допустимые длины и границу полного пространства. */ +{ /* Массивы карты принадлежат тестовому приложению и не требуют выделения всей памяти 0…FFFF. */ + uint16_t low[8] = {100U, 200U, 300U, 400U, 500U, 600U, 700U, 800U}, high[2] = {11U, 22U}; /* Отличающиеся соседние слова обнаруживают лишнюю запись или переход через FFFF. */ + pcan_gas_region_t regions[] = {{0U, 8U, low, NULL, NULL, 0U, NULL, NULL}, {0xFFFEU, 2U, high, NULL, NULL, 0U, NULL, NULL}}; /* Два небольших региона покрывают начало и конец 16-битного пространства. */ + pcan_gas_map_t map = {regions, 2U}; pcan_frame_t request = {0}, response; pcan_id_t id = {1U, PCAN_MSG_GAS, 5U, 1U, PCAN_ROUTE_FROM_PM, PCAN_PRIORITY_STANDARD}; unsigned count, i; /* Запрос адресует второе слово без слота или дополнительного индекса. */ + CHECK(pcan_gas_map_validate(&map)); request.id = pcan_id_pack(&id); request.flags = PCAN_FLAG_IDE; /* Проверяем карту и формируем обычный extended data frame. */ + request.dlc = 2U; request.data[0] = 0x34U; request.data[1] = 0x12U; CHECK(!pcan_gas_handle(&map, &request, &response)); /* Два октета записывают ровно один регистр и не порождают несуществующий ACK. */ + CHECK(low[0] == 100U && low[1] == 0x1234U && low[2] == 300U && low[3] == 400U); /* Соседние уставки остаются прежними без предварительного чтения на клиенте. */ + for (count = 1U; count <= 4U; ++count) { /* Все четыре допустимые длины должны изменять только заданный последовательный диапазон. */ + for (i = 0U; i < 8U; ++i) low[i] = (uint16_t)(100U + i); /* Возвращаем различимые исходные значения перед каждой длиной записи. */ + for (i = 0U; i < count; ++i) { request.data[2U * i] = (uint8_t)(10U + i); request.data[2U * i + 1U] = 0U; } /* Значения 10…13 не совпадают с фоновыми данными карты. */ + request.dlc = (uint8_t)(count * 2U); CHECK(!pcan_gas_handle(&map, &request, &response)); /* DLC определяет один, два, три или четыре слова начиная с MsgBody. */ + for (i = 0U; i < 8U; ++i) CHECK(low[i] == ((i >= 1U && i <= count) ? 9U + i : 100U + i)); /* Любая запись вне выбранного диапазона является ошибкой. */ + } /* Завершаем проверку допустимых коротких и полных payload. */ + for (i = 1U; i <= 9U; i += 2U) { request.dlc = (uint8_t)i; CHECK(!pcan_gas_handle(&map, &request, &response)); CHECK(low[1] == 10U); } /* Нечётный или превышающий восемь октетов payload не записывает даже первый полный регистр. */ + request.dlc = 2U; id.msg_type = PCAN_MSG_GAS_SLOT; request.id = pcan_id_pack(&id); CHECK(!pcan_gas_handle(&map, &request, &response)); CHECK(low[1] == 10U); /* Тип 0x4 изолирован от адресации отдельных регистров. */ + id.msg_type = PCAN_MSG_GAS; id.route = PCAN_ROUTE_FROM_DEVICE; request.id = pcan_id_pack(&id); CHECK(!pcan_gas_handle(&map, &request, &response)); CHECK(low[1] == 10U); /* Ответ прибора не исполняется повторно как запись. */ + id.route = PCAN_ROUTE_FROM_PM; id.msg_body = 0xFFFFU; request.id = pcan_id_pack(&id); request.data[0] = 0x78U; request.data[1] = 0x56U; /* Выбираем максимальный адрес без потери старших битов. */ + CHECK(!pcan_gas_handle(&map, &request, &response)); CHECK(high[0] == 11U && high[1] == 0x5678U); /* Одно слово по адресу FFFF допустимо и не меняет предыдущий регистр. */ + request.dlc = 4U; request.data[0] = 1U; CHECK(!pcan_gas_handle(&map, &request, &response)); CHECK(high[1] == 0x5678U && low[0] == 100U); /* Блок через верхнюю границу отвергается целиком, не оборачиваясь к адресу ноль. */ + request.dlc = 0U; CHECK(pcan_gas_handle(&map, &request, &response)); CHECK(response.dlc == 2U && response.data[0] == 0x78U && response.data[1] == 0x56U); /* Чтение максимального адреса возвращает одно существующее слово. */ + request.dlc = 2U; for (i = 0U; i <= 8U; i += 2U) { request.flags = (uint8_t)(PCAN_FLAG_IDE | i); if (i == 0U || i == 4U || i == 6U) continue; CHECK(!pcan_gas_handle(&map, &request, &response)); CHECK(high[1] == 0x5678U); } /* RTR и ERR не вызывают запись карты. */ + request.flags = 0U; CHECK(!pcan_gas_handle(&map, &request, &response)); CHECK(!pcan_gas_handle(&map, NULL, &response)); /* Стандартный ID и отсутствующий запрос безопасно отвергаются. */ + puts("GAS register addressing: OK"); return 0; /* Подтверждаем успешную проверку всех контрактов отдельного регистра. */ +} /* Конец теста безслотового GAS. */ diff --git a/c/set-protocol/tests/test_gas_slot.c b/c/set-protocol/tests/test_gas_slot.c new file mode 100644 index 0000000..819d9b9 --- /dev/null +++ b/c/set-protocol/tests/test_gas_slot.c @@ -0,0 +1,61 @@ +#include "pcan_gas_slot.h" /* Проверяем реальный публичный кодек и MCU-обработчик слотного GAS. */ +#include "pcan_id.h" /* Независимо проверяем разделение типов 0x3 и 0x4. */ +#include /* Диагностика CHECK работает также в release-сборке без assert. */ +#include /* Сравниваем точные октеты и сохранность невыбранных значений. */ +#define CHECK(x) do { if (!(x)) { printf("gas_slot:%d: %s\n", __LINE__, #x); return 1; } } while (0) /* Ненулевой код делает любое нарушение видимым сборщику тестов. */ +static unsigned reads, writes; /* Счётчики обнаруживают вызов provider для отвергнутого кадра. */ +static uint16_t state[3] = {0x1234U, 0xABCDU, 0xFFFFU}; /* Три независимых значения позволяют проверить, что частичная запись сохраняет соседей. */ +static int read_slot(void *context, uint16_t address, uint16_t words[4]) /* Provider реализует данные, не повторяя формат CAN ID или endian. */ +{ /* Чтение возвращает Word0 с маской достоверности и три фиксированные позиции. */ + unsigned i; (void)context; ++reads; if (address != 0x0500U && address != 0xFFFFU && address != 0x0542U) return 1; /* Только три адреса существуют в тестовом источнике. */ + words[0] = address == 0x0542U ? 0x0006U : PCAN_GAS_SLOT_MASK; /* Последний слот PERIPH содержит два действующих значения, общий адрес FFFF содержит три. */ + for (i = 0U; i < 3U; ++i) words[i + 1U] = state[i]; /* Служебная маска не подменяет первое хранимое значение. */ + return 0; /* Успех сообщается после заполнения всех wire-позиций. */ +} /* Конец источника чтения. */ +static int write_slot(void *context, uint16_t address, const uint16_t words[4]) /* Проверяем рекомендуемый контракт provider с общей предварительной валидацией. */ +{ /* В реальном устройстве обе фазы выполняются под одной блокировкой данных приложения. */ + unsigned i; (void)context; if (address != 0x0500U && address != 0xFFFFU) return 1; /* Несуществующий адрес не изменяет состояние. */ + for (i = 1U; i < 4U; ++i) if ((words[0] & (1U << i)) != 0U && words[i] == 0xDEADU) return 1; /* Отвергаем весь набор до первого изменения выбранных слов. */ + for (i = 1U; i < 4U; ++i) if ((words[0] & (1U << i)) != 0U) state[i - 1U] = words[i]; /* Меняем только отмеченные позиции; остальные остаются текущими значениями устройства. */ + ++writes; return 0; /* Считаем только полностью проверенную и применённую команду. */ +} /* Конец тестового provider записи. */ +int main(void) /* Охватываем wire-контракт, изоляцию типов, масочную запись и все границы адресации. */ +{ /* Все буферы ограничены размером одного classic CAN кадра. */ + unsigned mode, local, i, mask; uint16_t native, words[4] = {0x000EU, 0x1234U, 0xABCDU, 0xFFFFU}, decoded[4]; /* Маска занимает нулевое слово, а не младшие биты адреса. */ + uint_least8_t data[8], expected[8] = {0x0E, 0, 0x34, 0x12, 0xCD, 0xAB, 0xFF, 0xFF}; /* Независимый эталон показывает порядок маски и трёх значений. */ + pcan_gas_slot_port_t port = {NULL, read_slot, write_slot}; pcan_gas_slot_frame_t request = {0}, response; /* Используем тот же входной API, который вызывает прошивка устройства. */ + CHECK(pcan_gas_slot_request_id(5, 0, 0) == 0x11540500UL); CHECK(pcan_gas_slot_request_id(6, 0, 0) == 0x11640600UL); /* В ID заменён только MsgType, адреса узлов PERIPH сохранены. */ + CHECK(pcan_gas_slot_request_id(7, 0, 0) == 0x11740700UL); CHECK(pcan_gas_slot_request_id(8, 0, 0) == 0x11840800UL); /* Проверяем ранее опубликованные адреса соседних mode. */ + CHECK(pcan_gas_slot_request_id(16, 0, 0) == 0x12041000UL); CHECK(pcan_gas_slot_request_id(31, 66, 0) == 0x12F41F42UL); /* Проверяем смену DeviceType и неполный последний слот страницы. */ + CHECK(pcan_gas_slot_address(32, 0) == -1); CHECK(pcan_gas_slot_address(5, 67) == -1); CHECK(pcan_gas_slot_request_id(5, 0, 2) == 0U); /* Резерв, чужой mode и неверный Route не маскируются. */ + CHECK(pcan_gas_slot_encode(words, 4, data) == 8); CHECK(memcmp(data, expected, sizeof(data)) == 0); /* Сопоставляем все восемь wire-октетов, включая маску. */ + CHECK(pcan_gas_slot_decode(0x19540500UL, 1, data, 8, &mode, &local, decoded) == 4); CHECK(mode == 5 && local == 0 && memcmp(words, decoded, sizeof(words)) == 0); /* Обратное преобразование сохраняет маску и значения. */ + CHECK(pcan_gas_slot_encode(words, 3, data) == -1); CHECK(pcan_gas_slot_encode(NULL, 0, NULL) == 0); /* Частичная запись имеет полный payload с маской; чтение остаётся пустым. */ + for (i = 1U; i < 8U; ++i) CHECK(pcan_gas_slot_decode_words(0x11540500UL, 1, data, i, decoded) == -1); /* Ни одна усечённая длина не обращается к provider. */ + for (i = 0U; i < 4U; ++i) { /* Проверяем пустую маску, бит нулевого слова и зарезервированные старшие биты. */ + uint16_t invalid[] = {0U, 1U, 0x10U, 0xFFFFU}; words[0] = invalid[i]; CHECK(pcan_gas_slot_encode(words, 4, data) == -1); /* Недопустимый набор отвергается до изменения выходного буфера. */ + } /* Завершаем проверку каноничности Word0. */ + words[0] = PCAN_GAS_SLOT_MASK; CHECK(pcan_gas_slot_encode(words, 4, data) == 8); /* Восстанавливаем корректный полный набор для последующих проверок. */ + CHECK(pcan_gas_slot_decode_words(0x19530500UL, 1, data, 8, decoded) == -1); /* Тип 0x3 никогда не трактуется как слотный даже при подходящих первых байтах. */ + CHECK(pcan_gas_slot_decode(0x19540600UL, 1, data, 8, &mode, &local, decoded) == -1); /* Устройство mode 5 не обслуживает страницу mode 6. */ + CHECK(pcan_gas_slot_decode(0x19540542UL, 1, data, 8, &mode, &local, decoded) == -1); /* Третье значение последнего слота не существует и не принимается через маску. */ + words[0] = 0x0006U; CHECK(pcan_gas_slot_encode(words, 4, data) == 8); CHECK(pcan_gas_slot_decode(0x19540542UL, 1, data, 8, &mode, &local, decoded) == 4); /* Два действующих значения последнего слота сохраняют допустимость. */ + request.id = 0x11540500UL; request.flags = PCAN_GAS_SLOT_FLAG_IDE; CHECK(pcan_gas_slot_handle(5, &port, &request, &response) == 1); /* Чтение не содержит фиктивной маски в запросе. */ + CHECK(response.id == 0x19540500UL && response.dlc == 8U && reads == 1U); CHECK(memcmp(response.data, expected, sizeof(expected)) == 0); /* Ответ содержит маску достоверности и исходные три значения. */ + for (mask = 2U; mask <= PCAN_GAS_SLOT_MASK; mask += 2U) { /* Все семь непустых комбинаций трёх битов должны сохранять невыбранные позиции. */ + unsigned before = writes; state[0] = 10U; state[1] = 20U; state[2] = 30U; words[0] = (uint16_t)mask; words[1] = 101U; words[2] = 202U; words[3] = 303U; /* Отличающиеся старые и новые значения обнаруживают лишнюю запись соседей. */ + request.dlc = 8U; CHECK(pcan_gas_slot_encode(words, 4, request.data) == 8); CHECK(pcan_gas_slot_handle(5, &port, &request, &response) == 0); /* Одна команда вызывает provider один раз без предварительного чтения слота на хосте. */ + CHECK(writes == before + 1U); CHECK(state[0] == ((mask & 2U) ? 101U : 10U)); CHECK(state[1] == ((mask & 4U) ? 202U : 20U)); CHECK(state[2] == ((mask & 8U) ? 303U : 30U)); /* Проверяем каждую позицию отдельно для всех масок. */ + } /* Конец исчерпывающей проверки выбора трёх значений. */ + words[0] = 6U; words[1] = 7U; words[2] = 0xDEADU; CHECK(pcan_gas_slot_encode(words, 4, request.data) == 8); CHECK(pcan_gas_slot_handle(5, &port, &request, &response) == -1); CHECK(state[0] == 101U && state[1] == 202U); /* Отказ второго выбранного значения не должен менять первое. */ + request.flags = 3U; CHECK(pcan_gas_slot_handle(5, &port, &request, &response) == -1); request.flags = 0U; CHECK(pcan_gas_slot_handle(5, &port, &request, &response) == -1); /* RTR и стандартный ID отвергаются до записи. */ + request.flags = 1U; request.id = 0x19540500UL; CHECK(pcan_gas_slot_handle(5, &port, &request, &response) == -1); /* Ответ прибора не исполняется как команда мастера. */ + CHECK(pcan_gas_slot_id(7, 14, 65535U, 0) == 0x17E4FFFFUL); CHECK(pcan_gas_slot_id(7, 14, 65536UL, 0) == 0U); /* Общий слотный API сохраняет адрес FFFF и отвергает выход за 16 бит. */ + request.id = 0x17E4FFFFUL; request.dlc = 0U; CHECK(pcan_gas_slot_handle_address(7, 14, &port, &request, &response) == 1); CHECK(response.id == 0x1FE4FFFFUL); /* Отдельный инвертор не привязан к геометрии PERIPH. */ + CHECK(pcan_gas_slot_handle_address(7, 13, &port, &request, &response) == -1); /* Соседний узел не обслуживает чужой запрос. */ + CHECK(pcan_gas_slot_native(42, 2, 0, &native) == 1 && native == 127U); CHECK(pcan_gas_slot_native(42, 3, 0, &native) == 1 && native == 0x1000U); /* Граница технологических слов проходит внутри слота и не меняет native-адреса. */ + CHECK(pcan_gas_slot_native(48, 1, 0, &native) == 1 && native == 0x1200U); CHECK(pcan_gas_slot_native(52, 3, 1, &native) == 1 && native == 0x1302U); /* Паспорт и разрешённое поле защиты сохраняют исходное назначение. */ + CHECK(pcan_gas_slot_native(42, 3, 1, &native) == 0); CHECK(pcan_gas_slot_native(52, 1, 1, &native) == 0); CHECK(pcan_gas_slot_native(0, 0, 0, &native) == 0); /* Readonly-слова и служебная маска не записываются как технологические данные. */ + CHECK(pcan_gas_slot_native(56, 1, 0, &native) == 0); CHECK(pcan_gas_slot_native(66, 3, 0, &native) == 0); /* Резерв и лишняя 201-я позиция не становятся фиктивными регистрами. */ + puts("GAS SLOT masks: OK"); return 0; /* Успех означает прохождение всех позитивных, отрицательных и граничных случаев. */ +} /* Конец регрессионного теста масочного слота. */ diff --git a/c/set-protocol/tests/test_gas_watch.c b/c/set-protocol/tests/test_gas_watch.c new file mode 100644 index 0000000..ed2d8d2 --- /dev/null +++ b/c/set-protocol/tests/test_gas_watch.c @@ -0,0 +1,370 @@ +/* Контракт GAS_WATCH2: атомарная подписка, самостоятельный снимок и проверка входящих пакетов. */ +#include /* Целочисленные типы фиксируют размеры полей и переполнение счётчиков протокола. */ +#include /* Диагностика сообщает конкретное нарушенное условие и строку теста. */ +#include /* Побайтовые сравнения проверяют эталонный формат и отсутствие частичных изменений. */ +#include "set_gas_watch.h" /* Проверяем только публичный интерфейс общего ядра и его хостовые функции. */ + +static unsigned failures; /* Число нарушений накапливается, чтобы один запуск показал все независимые ошибки. */ +static void check(int condition, const char *expression, int line) /* Обёртка сохраняет проверки даже при определённом NDEBUG. */ +{ /* Начало общей диагностики проверяемого условия. */ + if (!condition) { /* Записываем только нарушения, чтобы успешный прогон оставался коротким. */ + printf("FAIL gas_watch:%d: %s\n", line, expression); /* Исходная строка позволяет быстро найти нарушенный контракт. */ + ++failures; /* Каждое отдельное нарушение делает итоговый код возврата ненулевым. */ + } /* Завершение обработки одного нарушения. */ +} /* Завершение функции диагностики. */ +#define CHECK(condition) check((condition), #condition, __LINE__) /* Макрос сохраняет выражение и его исходную строку без зависимости от assert. */ + +typedef struct { /* Состояние обработчика позволяет отличить проверку карты от реального чтения. */ + unsigned calls; /* Счётчик фиксирует любое обращение к провайдеру регистра. */ + uint16_t rejected_offset; /* Смещение 0xFFFF означает, что ни один из двух тестовых регистров не отвергается. */ + uint16_t base_value; /* Начальное значение добавляется к смещению, сохраняя различимость соседних каналов. */ +} read_context_t; /* Один экземпляр контекста обслуживает вычисляемый регион карты. */ + +static pcan_gas_status_t read_value(const pcan_gas_region_t *region, uint16_t offset, uint16_t *value) /* Подменяем приборный провайдер воспроизводимым обработчиком. */ +{ /* Начало имитации чтения одного 16-битного регистра. */ + read_context_t *context = (read_context_t *)region->user; /* Контекст берём из публичного пользовательского поля GAS-региона. */ + ++context->calls; /* Считаем в том числе неудачные чтения, чтобы проверить продолжение после ошибки. */ + *value = (uint16_t)(context->base_value + offset); /* Записываем ненулевой результат и при отказе: ядро обязано его обнулить. */ + return offset == context->rejected_offset ? PCAN_GAS_REJECTED : PCAN_GAS_OK; /* Выбранное смещение имитирует недостоверное значение устройства. */ +} /* Завершение подмены чтения. */ + +static pcan_gas_status_t write_value(const pcan_gas_region_t *region, uint16_t offset, uint16_t value) /* Провайдер записи создаёт корректный регион без возможности чтения. */ +{ /* Начало обработчика, используемого только для описания карты. */ + (void)region; /* Тесту достаточно наличия обработчика: состояние региона не изменяем. */ + (void)offset; /* Адрес записи не нужен, потому что операции записи здесь не выполняются. */ + (void)value; /* Значение записи не используется в проверках подписки только на чтение. */ + return PCAN_GAS_OK; /* Наличие рабочего обработчика записи делает регион допустимым для общей карты GAS. */ +} /* Завершение провайдера записи. */ + +static uint16_t storage[] = {123U, 65534U, 456U, 789U}; /* Значения включают отрицательное INT16 в исходном представлении 0xFFFE. */ +static read_context_t context; /* Общий контекст даёт доступ к счётчику обращений из разных сценариев. */ +static const pcan_gas_region_t regions[] = { /* Разрозненные адреса повторяют реальное сочетание памяти и вычисляемых регистров. */ + {0x0000U, 4U, storage, NULL, NULL, PCAN_GAS_RDONLY, NULL, "memory"}, /* Первые четыре адреса доступны напрямую, без обработчиков. */ + {0x0100U, 2U, NULL, read_value, NULL, PCAN_GAS_RDONLY, &context, "provider"}, /* Два вычисляемых канала позволяют отказать первому и успешно прочитать следующий. */ + {0x0200U, 1U, storage, NULL, NULL, PCAN_GAS_WRONLY, NULL, "write-only"}, /* Явный запрет чтения должен отвергаться до сбора выборки. */ + {0x0300U, 1U, NULL, NULL, write_value, 0U, NULL, "writer"}, /* Отсутствие провайдера чтения должно отвергаться и без флага WRONLY. */ + {0xFF01U, 1U, storage + 2U, NULL, NULL, PCAN_GAS_RDONLY, NULL, "uptime"} /* Высокий адрес проверяет отсутствие требований к непрерывности списка. */ +}; /* Конец отсортированной карты без пересечений. */ +static const pcan_gas_map_t map = {regions, 5U}; /* Пять регионов образуют валидную карту для основных сценариев. */ +static const uint16_t reference_addresses[] = {0x0000U, 0x0001U, 0xFF01U}; /* Порядок адресов совпадает с общим JSON-эталоном портов. */ +static const uint8_t reference_config[] = { /* Эталон соответствует tests/fixtures/gas-watch-v2.json и little-endian полям. */ + 0x02U, 0x00U, 0x64U, 0x00U, 0x78U, 0x56U, 0x34U, 0x12U, 0x03U, 0x00U, 0x00U, 0x00U, /* Версия 2, период 100 мс, идентификатор 0x12345678, три адреса и нулевой резерв. */ + 0x00U, 0x00U, 0x01U, 0x00U, 0x01U, 0xFFU /* Адреса 0x0000, 0x0001 и 0xFF01 сохраняют исходный порядок запроса. */ +}; /* Конец эталона запроса, который одновременно является точным ACK. */ +static const uint8_t reference_sample[] = { /* Эталон фиксирует полный диапазон беззнаковых счётчиков и недостоверный третий канал. */ + 0x02U, 0x00U, 0x03U, 0x00U, 0x78U, 0x56U, 0x34U, 0x12U, /* Версия 2, три значения и идентификатор 0x12345678. */ + 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U, 0xFFU, 0xFFU, 0xFFU, /* Номер 0xFFFFFFFF и приборное время 0xFFFFFFF0 мс сохраняются без знакового искажения. */ + 0x03U, 0x7BU, 0x00U, 0xFEU, 0xFFU, 0x00U, 0x00U /* Биты 0 и 1 отмечают достоверность значений 123 и 65534; недостоверное значение передаётся нулём. */ +}; /* Конец эталонной выборки длиной 23 байта. */ + +static void reject_unchanged(set_gas_watch_t *watch, const pcan_gas_map_t *active_map, const uint8_t *payload, size_t size, int expected) /* Общая проверка атомарного отказа на стороне устройства. */ +{ /* Начало вспомогательного сценария ошибочного применения конфигурации. */ + set_gas_watch_t before = *watch; /* Сохраняем весь объект, включая адреса, счётчики и срок очередной выборки. */ + unsigned calls = context.calls; /* Проверка доступности регистров не должна запускать приборные чтения. */ + CHECK(set_gas_watch_apply(watch, active_map, payload, size) == expected); /* Код ошибки отличает формат, отсутствующий адрес, доступ и конфликт идентификатора. */ + CHECK(memcmp(watch, &before, sizeof before) == 0); /* Ошибка любого адреса оставляет подписку целиком прежней. */ + CHECK(context.calls == calls); /* Отклонение запроса не вызывает побочных действий провайдера. */ +} /* Завершение атомарной проверки отказа. */ + +static void test_reference(void) /* Проверяем точные байты обеих сторон контракта на общей эталонной конфигурации. */ +{ /* Начало сценария совместимости wire-формата. */ + set_gas_watch_t watch; /* Устройство хранит подписку в памяти вызывающего приложения. */ + set_gas_watch_sample_t sample; /* Выборка хранится отдельно и не зависит от последующей перенастройки. */ + uint8_t output[SET_GAS_WATCH_SAMPLE_MAX]; /* Размер обеспечивает место для максимально разрешённого пакета. */ + uint16_t values[3] = {0U, 0U, 0U}; /* Декодер получает ровно три ячейки для значений эталона. */ + uint8_t valid[3] = {0U, 0U, 0U}; /* Признаки достоверности возвращаются отдельно от значений. */ + uint32_t sequence = 0U; /* Выходной счётчик должен принять максимальное беззнаковое значение. */ + uint32_t timestamp = 0U; /* Выходная отметка должна сохранить приборные миллисекунды. */ + set_gas_watch_init(&watch); /* Пустое состояние явно инициализируется до первого применения. */ + CHECK(!set_gas_watch_due(&watch, 0U)); /* До настройки устройство не считает сбор активным. */ + CHECK(set_gas_watch_request(0x12345678UL, 100U, reference_addresses, 3U, output, sizeof output) == sizeof reference_config); /* Запрос содержит ровно заголовок 12 байт и три 16-битных адреса. */ + CHECK(memcmp(output, reference_config, sizeof reference_config) == 0); /* Сравнение фиксирует порядок байтов, резерв и порядок адресов. */ + CHECK(set_gas_watch_apply(&watch, &map, output, sizeof reference_config) == SET_GAS_WATCH_OK); /* Полный валидный список принимается одной транзакцией. */ + CHECK(set_gas_watch_encode_ack(&watch, output, sizeof output) == sizeof reference_config); /* Подтверждение возвращает весь принятый список. */ + CHECK(memcmp(output, reference_config, sizeof reference_config) == 0); /* ACK подтверждает адреса точно, а не только совпадение числа каналов. */ + CHECK(set_gas_watch_ack(output, sizeof reference_config, 0x12345678UL, 100U, reference_addresses, 3U) == 1); /* Хост принимает точное подтверждение текущего запроса. */ + CHECK(set_gas_watch_ack(output, sizeof reference_config, 0x12345679UL, 100U, reference_addresses, 3U) == 0); /* Подтверждение предыдущей конфигурации не подтверждает новую. */ + CHECK(set_gas_watch_ack(output, sizeof reference_config, 0x12345678UL, 101U, reference_addresses, 3U) == 0); /* Подтверждённый период тоже является частью конфигурации. */ + const uint16_t reordered[] = {0x0001U, 0x0000U, 0xFF01U}; /* Перестановка сохраняет размер и состав множества, но меняет смысл позиций. */ + CHECK(set_gas_watch_ack(output, sizeof reference_config, 0x12345678UL, 100U, reordered, 3U) == 0); /* ACK обязан подтверждать порядок списка, а не только его множество. */ + CHECK(set_gas_watch_ack(NULL, sizeof reference_config, 0x12345678UL, 100U, reference_addresses, 3U) == 0); /* Нулевой вход ACK безопасно отвергается до сравнения содержимого. */ + CHECK(set_gas_watch_ack(output, sizeof reference_config - 1U, 0x12345678UL, 100U, reference_addresses, 3U) == 0); /* Усечённое подтверждение не подтверждает даже совпадающий префикс. */ + memset(&sample, 0, sizeof sample); /* Обнуляем запасные каналы, чтобы эталон не зависел от содержимого стека. */ + sample.config_id = 0x12345678UL; /* Идентификатор связывает выборку с конкретным списком адресов. */ + sample.sequence = UINT32_MAX; /* Максимальный номер проверяет сохранение всех 32 бит. */ + sample.timestamp_ms = 0xFFFFFFF0UL; /* Время в 16 мс до переполнения проверяет беззнаковую передачу. */ + sample.count = 3U; /* В эталон включены два достоверных и один недостоверный канал. */ + sample.values[0] = 123U; /* Первый регистр передаётся как обычный UINT16. */ + sample.values[1] = 65534U; /* Второй регистр передаётся как сырое слово 0xFFFE без интерпретации типа GUI. */ + sample.values[2] = 0xCAFEU; /* Ненулевое недостоверное значение обязано превратиться в ноль при сериализации. */ + sample.valid[0] = 1U; /* Первый бит маски подтверждает первый канал. */ + sample.valid[1] = 1U; /* Второй бит маски подтверждает второй канал. */ + CHECK(set_gas_watch_encode_sample(&sample, output, sizeof output) == sizeof reference_sample); /* Размер включает заголовок 16 байт, один байт маски и шесть байт значений. */ + CHECK(memcmp(output, reference_sample, sizeof reference_sample) == 0); /* Эталон проверяет каноническое обнуление и отсутствие лишних битов маски. */ + CHECK(sample.values[2] == 0xCAFEU); /* Кодирование не изменяет исходный самостоятельный снимок. */ + CHECK(set_gas_watch_decode(output, sizeof reference_sample, sample.config_id, 3U, &sequence, ×tamp, values, valid, 3U) == 3); /* Хост возвращает число успешно распознанных каналов. */ + CHECK(sequence == UINT32_MAX && timestamp == 0xFFFFFFF0UL); /* Номер и время сохраняются при прохождении через ABI. */ + CHECK(values[0] == 123U && values[1] == 65534U && values[2] == 0U); /* Значения возвращаются в порядке адресов, включая нулевое недостоверное. */ + CHECK(valid[0] == 1U && valid[1] == 1U && valid[2] == 0U); /* Маска распаковывается в отдельные признаки каналов. */ +} /* Завершение проверки эталонных байтов. */ + +static void test_atomic_apply(void) /* Проверяем отказ без частичной замены списка и работу идентификаторов конфигурации. */ +{ /* Начало сценария транзакционной настройки. */ + set_gas_watch_t watch; /* Состояние будет многократно получать ошибочные и корректные запросы. */ + uint8_t payload[SET_GAS_WATCH_CONFIG_MAX + 1U]; /* Дополнительный байт позволяет проверить отказ от лишнего хвоста. */ + uint16_t addresses[] = {0x0000U, 0x0100U}; /* Второй канал принадлежит провайдеру, который нельзя вызывать при настройке. */ + size_t size = set_gas_watch_request(1U, 32U, addresses, 2U, payload, sizeof payload); /* Первая конфигурация запускает два разрозненных регистра с периодом 32 мс. */ + set_gas_watch_init(&watch); /* В исходном состоянии нет принятого идентификатора. */ + context.calls = 0U; /* Счётчик отделяет настройку от всех предыдущих сценариев. */ + CHECK(set_gas_watch_apply(&watch, &map, payload, size) == SET_GAS_WATCH_OK); /* Валидный запрос устанавливает сразу весь список. */ + CHECK(context.calls == 0U); /* Проверка наличия обработчика не должна читать устройство. */ + watch.sequence = 77U; /* Ненулевой номер помогает заметить ошибочный сброс при повторе запроса. */ + watch.next_ms = 12345U; /* Установленный срок должен сохраниться при идемпотентном повторе. */ + watch.scheduled = 1U; /* Состояние уже выполнявшегося сбора не должно превращаться в новый старт. */ + set_gas_watch_t before = watch; /* Копия фиксирует все поля до повторной доставки одного запроса. */ + CHECK(set_gas_watch_apply(&watch, &map, payload, size) == SET_GAS_WATCH_OK); /* Повтор принятой конфигурации является успешным повтором подтверждения. */ + CHECK(memcmp(&watch, &before, sizeof watch) == 0); /* Идемпотентный повтор не меняет номера, расписание и адреса. */ + payload[2] = 33U; /* При прежнем идентификаторе изменяем период с 32 на 33 мс. */ + reject_unchanged(&watch, &map, payload, size, SET_GAS_WATCH_CONFLICT); /* Один идентификатор не может обозначать две разные конфигурации. */ + payload[2] = 32U; /* Восстанавливаем канонический период исходной конфигурации. */ + payload[0] = 3U; /* Неподдерживаемая версия не может интерпретироваться как текущий формат. */ + reject_unchanged(&watch, &map, payload, size, SET_GAS_WATCH_INVALID); /* Неверная версия оставляет рабочий сбор действующим. */ + payload[0] = 2U; /* Возвращаем версию 2 перед проверкой следующего поля. */ + payload[10] = 1U; /* Зарезервированное поле должно оставаться нулевым в версии 2. */ + reject_unchanged(&watch, &map, payload, size, SET_GAS_WATCH_INVALID); /* Неизвестные расширения не принимаются молча. */ + payload[10] = 0U; /* Убираем нарушение резерва для независимой проверки длины. */ + reject_unchanged(&watch, &map, payload, size - 1U, SET_GAS_WATCH_INVALID); /* Оборванный адрес не приводит к усечённой подписке. */ + reject_unchanged(&watch, &map, payload, size + 1U, SET_GAS_WATCH_INVALID); /* Лишний байт исключает неоднозначное принятие пакета. */ + reject_unchanged(&watch, &map, payload, SET_GAS_WATCH_CONFIG_HEADER - 1U, SET_GAS_WATCH_INVALID); /* До чтения полей должен присутствовать весь фиксированный заголовок. */ + reject_unchanged(&watch, &map, payload, sizeof payload, SET_GAS_WATCH_INVALID); /* Пакет больше 140 байт не может содержать допустимую конфигурацию версии 2. */ + reject_unchanged(&watch, &map, NULL, size, SET_GAS_WATCH_INVALID); /* Нулевой указатель с ненулевой длиной обрабатывается безопасно. */ + addresses[1] = 0x0042U; /* Адрес 0x0042 расположен в промежутке между регионами тестовой карты. */ + size = set_gas_watch_request(2U, 32U, addresses, 2U, payload, sizeof payload); /* Новый идентификатор исключает смешение ошибки адреса с конфликтом номера. */ + reject_unchanged(&watch, NULL, payload, size, SET_GAS_WATCH_INVALID); /* Без карты невозможно подтвердить доступность каналов нового списка. */ + reject_unchanged(&watch, &map, payload, size, SET_GAS_WATCH_NO_REG); /* Отсутствующий регистр отвергает весь список. */ + addresses[1] = 0x0200U; /* Этот адрес существует, но помечен как доступный только для записи. */ + size = set_gas_watch_request(2U, 32U, addresses, 2U, payload, sizeof payload); /* Сохраняем корректный wire-формат для проверки прав доступа. */ + reject_unchanged(&watch, &map, payload, size, SET_GAS_WATCH_ACCESS); /* Явный запрет чтения не превращается в постоянно недостоверный канал. */ + addresses[1] = 0x0300U; /* У этого региона есть только провайдер записи без флага WRONLY. */ + size = set_gas_watch_request(2U, 32U, addresses, 2U, payload, sizeof payload); /* Подписка проверяет реальную возможность чтения, а не один флаг. */ + reject_unchanged(&watch, &map, payload, size, SET_GAS_WATCH_ACCESS); /* Отсутствие хранилища и провайдера чтения тоже означает запрет. */ + addresses[1] = 0x0101U; /* Корректная замена сохраняет число каналов, но меняет второй адрес. */ + size = set_gas_watch_request(2U, 32U, addresses, 2U, payload, sizeof payload); /* Новая конфигурация имеет отдельный идентификатор. */ + CHECK(set_gas_watch_apply(&watch, &map, payload, size) == SET_GAS_WATCH_OK); /* Устройство принимает новый список целиком. */ + CHECK(watch.config_id == 2U && watch.address[1] == 0x0101U); /* Равное число каналов не скрывает замену их содержимого. */ + CHECK(watch.sequence == 0U && watch.scheduled == 0U); /* Новый список начинает отдельную последовательность и готов к немедленному сбору. */ + size = set_gas_watch_request(1U, 32U, addresses, 2U, payload, sizeof payload); /* Возвращаем устаревший идентификатор с тем же числом каналов. */ + reject_unchanged(&watch, &map, payload, size, SET_GAS_WATCH_CONFLICT); /* Задержавшийся запрос не откатывает устройство назад. */ + size = set_gas_watch_request(0x80000002UL, 32U, addresses, 2U, payload, sizeof payload); /* Разность ровно половины диапазона uint32 неоднозначна для порядка номеров. */ + reject_unchanged(&watch, &map, payload, size, SET_GAS_WATCH_CONFLICT); /* Граница 2^31 не признаётся более новой конфигурацией. */ + payload[4] = 0U; /* Первые четыре байта идентификатора заменяем нулями для запрещённого номера. */ + payload[5] = 0U; /* Убираем второй байт идентификатора, сохраняя длину и адреса. */ + payload[6] = 0U; /* Убираем третий байт идентификатора без изменения других полей. */ + payload[7] = 0U; /* Завершаем формирование зарезервированного идентификатора 0. */ + reject_unchanged(&watch, &map, payload, size, SET_GAS_WATCH_INVALID); /* Нулевой номер запрещён и не используется как команда обхода порядка. */ + size = set_gas_watch_request(3U, 32U, addresses, 2U, payload, sizeof payload); /* Создаём валидный пакет перед намеренным дублированием адреса на линии. */ + payload[14] = payload[12]; /* Второй адрес получает младший байт первого адреса. */ + payload[15] = payload[13]; /* Второй адрес получает старший байт первого адреса. */ + reject_unchanged(&watch, &map, payload, size, SET_GAS_WATCH_INVALID); /* Дубликаты отвергаются и на устройстве, даже если хостовый builder их запрещает. */ + pcan_gas_region_t overlap[] = {regions[0], regions[0]}; /* Перекрывающиеся регионы создают неоднозначное отображение GAS-адресов. */ + pcan_gas_map_t invalid_map = {overlap, 2U}; /* Некорректная карта не должна обходить проверку через удачный первый поиск. */ + size = set_gas_watch_request(3U, 32U, addresses, 2U, payload, sizeof payload); /* Убираем дубликат из запроса, оставляя единственным нарушением карту. */ + reject_unchanged(&watch, &invalid_map, payload, size, SET_GAS_WATCH_INVALID); /* Применение проверяет целостность карты до принятия подписки. */ + set_gas_watch_init(&watch); /* Новое состояние позволяет отдельно проверить перенос идентификатора через uint32. */ + size = set_gas_watch_request(UINT32_MAX, 32U, addresses, 2U, payload, sizeof payload); /* Любой ненулевой номер разрешён для самой первой конфигурации. */ + CHECK(set_gas_watch_apply(&watch, &map, payload, size) == SET_GAS_WATCH_OK); /* Максимальный номер не отвергается из-за его старшего знакового бита. */ + size = set_gas_watch_request(1U, 32U, addresses, 2U, payload, sizeof payload); /* После максимального номера хост пропускает запрещённый ноль. */ + CHECK(set_gas_watch_apply(&watch, &map, payload, size) == SET_GAS_WATCH_OK); /* Модульное сравнение распознаёт номер 1 как новый после 0xFFFFFFFF. */ +} /* Завершение атомарных и порядковых проверок. */ + +static void test_capture_and_timing(void) /* Проверяем приборное время, единичное чтение и независимость уже полученной выборки. */ +{ /* Начало сценария сбора и сериализации самостоятельного снимка. */ + set_gas_watch_t watch; /* Подписка управляет периодом и последовательностью выборок. */ + set_gas_watch_sample_t sample; /* Снимок принадлежит вызывающему приложению и переживает изменение подписки. */ + uint16_t addresses[] = {0x0100U, 0x0101U, 0x0000U}; /* После отказавшего провайдера остаются ещё два канала для чтения. */ + uint8_t payload[SET_GAS_WATCH_CONFIG_MAX]; /* Буфер переносит только конфигурацию адресов. */ + uint8_t encoded[SET_GAS_WATCH_SAMPLE_MAX]; /* Первый результат кодирования сохраняется для проверки повторной передачи. */ + uint8_t repeated[SET_GAS_WATCH_SAMPLE_MAX]; /* Повторное кодирование обязано совпадать даже после изменений карты. */ + context.calls = 0U; /* Изолируем число приборных обращений текущего сценария. */ + context.base_value = 1000U; /* Вычисляемые значения отличаются от памяти GAS. */ + context.rejected_offset = 0U; /* Первый вычисляемый канал вернёт отказ уже после записи ненулевого результата. */ + set_gas_watch_init(&watch); /* Начинаем без активной подписки и расписания. */ + size_t size = set_gas_watch_request(1U, 32U, addresses, 3U, payload, sizeof payload); /* Три канала должны собираться одним снимком каждые 32 мс. */ + CHECK(set_gas_watch_apply(&watch, &map, payload, size) == SET_GAS_WATCH_OK); /* Проверяем, что наличие провайдера достаточно независимо от его будущего результата. */ + CHECK(context.calls == 0U); /* Настройка не вызывает провайдер даже для заведомо отказавшего чтения. */ + CHECK(set_gas_watch_due(&watch, 0xFFFFFFF0UL)); /* Новый список готов к сбору сразу и около переполнения времени. */ + CHECK(set_gas_watch_capture(&watch, &map, 0xFFFFFFF0UL, &sample)); /* Одна операция фиксирует все каналы и приборную отметку времени. */ + CHECK(context.calls == 2U); /* Оба провайдера прочитаны ровно по одному разу, несмотря на отказ первого. */ + CHECK(sample.config_id == 1U && sample.sequence == 0U && watch.sequence == 1U); /* Первая выборка имеет номер 0, после неё счётчик увеличивается один раз. */ + CHECK(sample.timestamp_ms == 0xFFFFFFF0UL && sample.count == 3U); /* Метка относится ко всей выборке и не подменяется временем отправки. */ + CHECK(sample.valid[0] == 0U && sample.values[0] == 0U); /* Неудачное чтение не выпускает записанное провайдером мусорное значение. */ + CHECK(sample.valid[1] == 1U && sample.values[1] == 1001U); /* Отказ одного адреса не прерывает чтение следующего провайдера. */ + CHECK(sample.valid[2] == 1U && sample.values[2] == storage[0]); /* Последний канал памяти остаётся достоверным после ошибки другого канала. */ + CHECK(watch.scheduled == 1U && watch.next_ms == 16U); /* Прибавление 32 мс к 0xFFFFFFF0 корректно переносит срок в следующий оборот таймера. */ + CHECK(!set_gas_watch_due(&watch, 0xFFFFFFF1UL)); /* Через 1 мс после выборки период ещё не истёк. */ + CHECK(!set_gas_watch_due(&watch, 0U)); /* После переполнения до срока остаётся 16 мс. */ + CHECK(!set_gas_watch_due(&watch, 15U)); /* В последнюю миллисекунду перед сроком чтение ещё не требуется. */ + CHECK(set_gas_watch_due(&watch, 16U)); /* Равенство приборного времени сроку означает готовность новой выборки. */ + watch.sequence = UINT32_MAX; /* Устанавливаем границу, которую нельзя дождаться перебором миллиардов выборок. */ + CHECK(set_gas_watch_capture(&watch, &map, 0U, &sample)); /* Явный сбор разрешён и до очередного срока: due остаётся решением вызывающего кода. */ + CHECK(sample.sequence == UINT32_MAX && watch.sequence == 0U); /* Последовательность переносится через uint32 без потери последнего номера. */ + size_t encoded_size = set_gas_watch_encode_sample(&sample, encoded, sizeof encoded); /* Кодируем зафиксированный снимок до изменения окружения. */ + unsigned calls = context.calls; /* Запоминаем количество чтений, чтобы выявить скрытое перечитывание при сериализации. */ + storage[0] = 999U; /* Модель прибора меняется после фиксации снимка. */ + context.base_value = 2000U; /* Вычисляемый провайдер тоже теперь вернул бы другие значения. */ + size = set_gas_watch_request(2U, 100U, reference_addresses, 3U, payload, sizeof payload); /* Меняем подписку на другой список при сохранении числа каналов. */ + CHECK(set_gas_watch_apply(&watch, &map, payload, size) == SET_GAS_WATCH_OK); /* Перенастройка должна быть независима от уже созданного пакета. */ + CHECK(set_gas_watch_encode_sample(&sample, repeated, sizeof repeated) == encoded_size); /* Повторная передача использует прежний размер самостоятельного снимка. */ + CHECK(memcmp(encoded, repeated, encoded_size) == 0); /* Ни значения карты, ни новые адреса не изменяют старую выборку. */ + CHECK(context.calls == calls); /* Подтверждение настройки и повторное кодирование не читают приборные регистры. */ + pcan_gas_region_t changed_regions[5]; /* Подмена карты моделирует исчезновение или изменение прав после успешной настройки. */ + memcpy(changed_regions, regions, sizeof changed_regions); /* Остальные свойства регионов сохраняются, чтобы карта оставалась структурно корректной. */ + changed_regions[0].flags = PCAN_GAS_WRONLY; /* Выбранные адреса 0 и 1 теперь запрещены для чтения. */ + changed_regions[4].base = 0xFF02U; /* Ранее выбранный адрес 0xFF01 больше не покрывается картой. */ + pcan_gas_map_t changed_map = {changed_regions, 5U}; /* Изменённая карта остаётся отсортированной и без перекрытий. */ + CHECK(set_gas_watch_capture(&watch, &changed_map, 1U, &sample)); /* Потеря отдельных каналов не отменяет номер и время всей выборки. */ + CHECK(sample.valid[0] == 0U && sample.valid[1] == 0U && sample.valid[2] == 0U); /* Изменение прав и исчезновение адреса явно отражаются недостоверностью. */ + CHECK(sample.values[0] == 0U && sample.values[1] == 0U && sample.values[2] == 0U); /* Ни старые значения, ни указатели исчезнувших каналов не попадают в новый пакет. */ + pcan_gas_map_t invalid_map = {NULL, 1U}; /* Ненулевое число регионов без массива является структурной ошибкой карты. */ + set_gas_watch_t before_watch = watch; /* Ошибка всей карты не должна расходовать номер выборки или сдвигать расписание. */ + set_gas_watch_sample_t before_sample = sample; /* Ошибка аргументов не должна повреждать уже полученный снимок. */ + CHECK(!set_gas_watch_capture(&watch, &invalid_map, 2U, &sample)); /* Структурно неверная карта отличается от ошибки отдельного читаемого канала. */ + CHECK(memcmp(&watch, &before_watch, sizeof watch) == 0); /* Состояние подписки полностью сохраняется при невозможности захвата. */ + CHECK(memcmp(&sample, &before_sample, sizeof sample) == 0); /* Выходной снимок полностью сохраняется при невозможности захвата. */ + size = set_gas_watch_request(3U, 0U, NULL, 0U, payload, sizeof payload); /* Остановка выражается пустым списком с периодом 0 мс и новым идентификатором. */ + CHECK(size == SET_GAS_WATCH_CONFIG_HEADER); /* Пакет остановки состоит только из заголовка конфигурации. */ + CHECK(set_gas_watch_apply(&watch, &map, payload, size) == SET_GAS_WATCH_OK); /* Остановка применяется такой же транзакцией, как активная конфигурация. */ + set_gas_watch_sample_t before = sample; /* Сохраняем старую выборку перед попыткой собрать неактивный поток. */ + CHECK(!set_gas_watch_due(&watch, UINT32_MAX)); /* Остановленный поток не становится активным из-за переполнения времени. */ + CHECK(!set_gas_watch_capture(&watch, &map, 1U, &sample)); /* Пустая подписка не создаёт новый пакет. */ + CHECK(memcmp(&sample, &before, sizeof sample) == 0); /* Неудачный сбор сохраняет уже готовую выборку в буфере вызывающего кода. */ + storage[0] = 123U; /* Возвращаем общее значение эталона для независимости следующих сценариев. */ +} /* Завершение проверки снимка и расписания. */ + +static void decode_rejected(const uint8_t *payload, size_t size, uint32_t config_id, size_t count, size_t capacity) /* Проверяем единый контракт отсутствия частичного результата на стороне хоста. */ +{ /* Начало вспомогательной проверки отказа декодера. */ + uint16_t values[SET_GAS_WATCH_MAX]; /* Полный буфер отделяет недостаточную объявленную ёмкость от реального выхода за память. */ + uint8_t valid[SET_GAS_WATCH_MAX]; /* Маска хранится в собственном буфере с отличимым заполнителем. */ + uint16_t before_values[SET_GAS_WATCH_MAX]; /* Копия выявляет изменение любого канала, включая запасные ячейки. */ + uint8_t before_valid[SET_GAS_WATCH_MAX]; /* Копия маски выявляет раннюю запись до полной валидации payload. */ + uint32_t sequence = 0x11223344UL; /* Отличимая исходная последовательность не должна меняться при отказе. */ + uint32_t timestamp = 0x55667788UL; /* Отличимая исходная метка не должна меняться при отказе. */ + memset(values, 0xA5, sizeof values); /* Все значения получают заполнитель, отличный от эталонного payload. */ + memset(valid, 0x5A, sizeof valid); /* Признаки достоверности получают отдельный заполнитель. */ + memcpy(before_values, values, sizeof values); /* Сохраняем массив значений для полного побайтового сравнения. */ + memcpy(before_valid, valid, sizeof valid); /* Сохраняем все ячейки маски до вызова декодера. */ + CHECK(set_gas_watch_decode(payload, size, config_id, count, &sequence, ×tamp, values, valid, capacity) == -1); /* Любая ошибка возвращает единый отрицательный результат. */ + CHECK(sequence == 0x11223344UL && timestamp == 0x55667788UL); /* Скалярные выходы обновляются только после полного принятия пакета. */ + CHECK(memcmp(values, before_values, sizeof values) == 0); /* Декодер не оставляет частично декодированные значения. */ + CHECK(memcmp(valid, before_valid, sizeof valid) == 0); /* Декодер не оставляет частично распакованные признаки. */ +} /* Завершение проверки транзакционного декодирования. */ + +static void test_malformed_and_limits(void) /* Проверяем границы буферов, максимальный список и канонический bitmap. */ +{ /* Начало сценария валидации публичной границы данных. */ + uint8_t payload[SET_GAS_WATCH_SAMPLE_MAX + 1U]; /* Дополнительный байт используется только для проверки лишнего хвоста. */ + uint8_t before[sizeof payload]; /* Заполнитель позволяет доказать отсутствие записи при отказе builder. */ + uint16_t duplicates[] = {1U, 1U}; /* Повтор одного адреса запрещён независимо от его реального существования в карте. */ + memset(payload, 0xA5, sizeof payload); /* Начинаем с различимого содержимого выходного буфера. */ + memcpy(before, payload, sizeof payload); /* Снимок буфера позволит выявить даже частично записанный заголовок. */ + CHECK(set_gas_watch_request(0U, 100U, reference_addresses, 3U, payload, sizeof payload) == 0U); /* Нулевой идентификатор конфигурации запрещён хостовому builder. */ + CHECK(set_gas_watch_request(1U, 0U, reference_addresses, 3U, payload, sizeof payload) == 0U); /* Ненулевой список требует ненулевого периода. */ + CHECK(set_gas_watch_request(1U, 100U, NULL, 0U, payload, sizeof payload) == 0U); /* Пустой список требует нулевого периода и означает остановку. */ + CHECK(set_gas_watch_request(1U, 100U, duplicates, 2U, payload, sizeof payload) == 0U); /* Дубликаты не должны выпускаться builder на линию. */ + CHECK(set_gas_watch_request(1U, 100U, NULL, 3U, payload, sizeof payload) == 0U); /* Ненулевое количество требует доступного массива адресов. */ + CHECK(set_gas_watch_request(1U, 100U, reference_addresses, 65U, payload, sizeof payload) == 0U); /* Проверка предела 64 выполняется до чтения указанного массива. */ + CHECK(set_gas_watch_request(1U, 100U, reference_addresses, 3U, payload, sizeof reference_config - 1U) == 0U); /* Недостаточная ёмкость не допускает усечённого запроса. */ + CHECK(set_gas_watch_request(1U, 100U, reference_addresses, 3U, NULL, sizeof payload) == 0U); /* Нулевой выходной указатель возвращает отказ без записи. */ + CHECK(memcmp(payload, before, sizeof payload) == 0); /* Ни один ошибочный запрос не должен частично менять переданный буфер. */ + memcpy(payload, reference_sample, sizeof reference_sample); /* Берём правильный пакет и независимо повреждаем отдельные части. */ + decode_rejected(payload, sizeof reference_sample, 0x12345679UL, 3U, 3U); /* Задержавшаяся выборка прежнего списка отвергается даже при том же количестве каналов. */ + decode_rejected(payload, sizeof reference_sample, 0x12345678UL, 2U, 3U); /* Число каналов должно совпадать с подтверждённой подпиской. */ + decode_rejected(payload, sizeof reference_sample, 0x12345678UL, 3U, 2U); /* Недостаточное число выходных ячеек не оставляет частичного результата. */ + decode_rejected(NULL, sizeof reference_sample, 0x12345678UL, 3U, 3U); /* Нулевой входной указатель обрабатывается как некорректный пакет. */ + decode_rejected(payload, SET_GAS_WATCH_SAMPLE_HEADER - 1U, 0x12345678UL, 3U, 3U); /* Не хватает даже фиксированного заголовка выборки. */ + decode_rejected(payload, sizeof reference_sample - 1U, 0x12345678UL, 3U, 3U); /* Оборванное последнее значение не может обновить первые каналы. */ + decode_rejected(payload, sizeof reference_sample + 1U, 0x12345678UL, 3U, 3U); /* Избыточный хвост исключает неверную интерпретацию следующего сообщения. */ + payload[0] = 3U; /* Изменяем версию при сохранении всех остальных эталонных полей. */ + decode_rejected(payload, sizeof reference_sample, 0x12345678UL, 3U, 3U); /* Неподдерживаемый формат не обновляет выходы. */ + payload[0] = 2U; /* Возвращаем действующую версию перед повреждением bitmap. */ + payload[16] = 0x83U; /* Бит 7 находится за пределами трёх каналов и обязан быть нулевым. */ + decode_rejected(payload, sizeof reference_sample, 0x12345678UL, 3U, 3U); /* Неиспользуемые биты маски проверяются для канонического представления. */ + payload[16] = 3U; /* Восстанавливаем корректную маску двух достоверных каналов. */ + payload[21] = 1U; /* Третий канал остаётся недостоверным, но его слово становится ненулевым. */ + decode_rejected(payload, sizeof reference_sample, 0x12345678UL, 3U, 3U); /* Неканоническое ненулевое слово недостоверного канала отвергается. */ + payload[21] = 0U; /* Восстанавливаем эталон перед проверкой чрезмерного количества. */ + payload[2] = 65U; /* Заголовок требует больше максимальных 64 каналов. */ + decode_rejected(payload, sizeof reference_sample, 0x12345678UL, 65U, 64U); /* Ограничение количества проверяется до обращения к выходным массивам. */ + uint16_t addresses[SET_GAS_WATCH_MAX]; /* Максимальный список хранит уникальные адреса единого региона. */ + uint16_t words[SET_GAS_WATCH_MAX]; /* Модель карты содержит достаточно реальных слов для всех 64 каналов. */ + for (size_t i = 0U; i < SET_GAS_WATCH_MAX; ++i) { /* Заполняем все разрешённые позиции без фиксации размера в теле цикла. */ + addresses[i] = (uint16_t)i; /* Диапазон 0..63 создаёт уникальный отсортированный список регистров. */ + words[i] = (uint16_t)(1000U + i); /* Ненулевой возрастающий рисунок делает перестановки значений заметными. */ + } /* Завершение подготовки максимального списка. */ + pcan_gas_region_t full_region = {0U, SET_GAS_WATCH_MAX, words, NULL, NULL, PCAN_GAS_RDONLY, NULL, "full"}; /* Один читаемый регион покрывает все 64 адреса. */ + pcan_gas_map_t full_map = {&full_region, 1U}; /* Карта максимального списка остаётся простой и однозначной. */ + set_gas_watch_t watch; /* Состояние максимального потока проверяет размеры публичных структур. */ + set_gas_watch_sample_t sample; /* Выборка должна вместить все значения и признаки без динамической памяти. */ + set_gas_watch_init(&watch); /* Создаём пустое состояние для независимого граничного сценария. */ + size_t config_size = set_gas_watch_request(1U, 1U, addresses, SET_GAS_WATCH_MAX, payload, sizeof payload); /* Минимальный ненулевой период 1 мс остаётся разрешённым. */ + CHECK(config_size == SET_GAS_WATCH_CONFIG_MAX && config_size == 140U); /* Максимальная конфигурация занимает 12 + 64*2 байта. */ + CHECK(set_gas_watch_apply(&watch, &full_map, payload, config_size) == SET_GAS_WATCH_OK); /* Устройство принимает ровно предельные 64 уникальных адреса. */ + CHECK(set_gas_watch_capture(&watch, &full_map, 42U, &sample)); /* Максимальная выборка собирается за один вызов. */ + size_t sample_size = set_gas_watch_encode_sample(&sample, payload, sizeof payload); /* Кодируем весь снимок с восемью байтами bitmap. */ + CHECK(sample_size == SET_GAS_WATCH_SAMPLE_MAX && sample_size == 152U); /* Полный пакет занимает 16 + 8 + 64*2 байта. */ + uint16_t decoded[SET_GAS_WATCH_MAX]; /* Выходные значения хоста имеют ровно предельную ёмкость. */ + uint8_t valid[SET_GAS_WATCH_MAX]; /* Один признак на каждый из 64 каналов проверяет все восемь байтов bitmap. */ + uint32_t sequence = UINT32_MAX; /* Отличимое исходное значение должно замениться нулём первой выборки. */ + uint32_t timestamp = 0U; /* Метка должна получить приборное значение 42 мс. */ + CHECK(set_gas_watch_decode(payload, sample_size, 1U, SET_GAS_WATCH_MAX, &sequence, ×tamp, decoded, valid, SET_GAS_WATCH_MAX) == (int)SET_GAS_WATCH_MAX); /* Декодер принимает предельный размер без усечения. */ + CHECK(sequence == 0U && timestamp == 42U && memcmp(decoded, words, sizeof words) == 0); /* Все значения и скалярные поля максимального пакета сохраняются. */ + for (size_t i = 0U; i < SET_GAS_WATCH_MAX; ++i) { /* Проверяем каждую позицию вместо одной средней маски. */ + CHECK(valid[i] == 1U); /* Читаемый массив делает достоверными все 64 канала, включая последние биты bitmap. */ + } /* Завершение проверки полного bitmap. */ + CHECK(set_gas_watch_decode(payload, sample_size, 1U, SET_GAS_WATCH_MAX, NULL, ×tamp, decoded, valid, SET_GAS_WATCH_MAX) == (int)SET_GAS_WATCH_MAX); /* Вызывающий код может отказаться от получения необязательного счётчика последовательности. */ + CHECK(set_gas_watch_decode(payload, sample_size, 1U, SET_GAS_WATCH_MAX, &sequence, NULL, decoded, valid, SET_GAS_WATCH_MAX) == (int)SET_GAS_WATCH_MAX); /* Вызывающий код может отказаться от получения необязательной отметки времени. */ + CHECK(set_gas_watch_decode(payload, sample_size, 1U, SET_GAS_WATCH_MAX, &sequence, ×tamp, NULL, valid, SET_GAS_WATCH_MAX) == -1); /* Обязательный массив значений проверяется до записи результата. */ + CHECK(set_gas_watch_decode(payload, sample_size, 1U, SET_GAS_WATCH_MAX, &sequence, ×tamp, decoded, NULL, SET_GAS_WATCH_MAX) == -1); /* Обязательный массив достоверности проверяется до записи результата. */ + CHECK(set_gas_watch_encode_sample(&sample, NULL, sizeof payload) == 0U); /* Нулевой буфер сериализации приводит к безопасному отказу. */ + CHECK(set_gas_watch_encode_sample(&sample, payload, sample_size - 1U) == 0U); /* Сериализация никогда не выпускает частичный пакет. */ + CHECK(set_gas_watch_encode_sample(NULL, payload, sizeof payload) == 0U); /* Отсутствующий снимок нельзя заменить чтением какой-либо глобальной карты. */ + CHECK(set_gas_watch_encode_ack(NULL, payload, sizeof payload) == 0U); /* Отсутствующая подписка не образует корректного подтверждения. */ + CHECK(set_gas_watch_encode_ack(&watch, NULL, sizeof payload) == 0U); /* Нулевой буфер ACK безопасно отвергается. */ + CHECK(set_gas_watch_encode_ack(&watch, payload, config_size - 1U) == 0U); /* Подтверждение не сокращается до одного заголовка из-за малого буфера. */ + CHECK(set_gas_watch_apply(NULL, &full_map, payload, config_size) == SET_GAS_WATCH_INVALID); /* Пустой указатель состояния не должен разыменовываться. */ + CHECK(!set_gas_watch_due(NULL, 1U)); /* Запрос расписания без состояния возвращает отсутствие готовности. */ + CHECK(!set_gas_watch_capture(NULL, &full_map, 1U, &sample)); /* Сбор без состояния возвращает отказ. */ + CHECK(!set_gas_watch_capture(&watch, NULL, 1U, &sample)); /* Сбор без карты не обращается к несуществующим провайдерам. */ + CHECK(!set_gas_watch_capture(&watch, &full_map, 1U, NULL)); /* Сбор без выходного снимка не выполняется. */ + set_gas_watch_init(NULL); /* Инициализация проверяется на безопасное поведение с нулевым указателем. */ + sample.valid[0] = 0U; /* Отключаем первый канал, чтобы проверить младший бит первого байта bitmap. */ + sample.valid[7] = 0U; /* Отключаем последний канал первого байта bitmap. */ + sample.valid[8] = 0U; /* Отключаем первый канал второго байта bitmap, проверяя перенос границы восьми каналов. */ + sample.valid[63] = 0U; /* Отключаем последний разрешённый канал в старшем бите восьмого байта. */ + CHECK(set_gas_watch_encode_sample(&sample, payload, sizeof payload) == sample_size); /* Изменение достоверности сохраняет длину максимального пакета. */ + CHECK(payload[16] == 0x7EU && payload[17] == 0xFEU && payload[23] == 0x7FU); /* Раскладка bitmap соответствует индексам 0, 7, 8 и 63 без смещения. */ + CHECK(set_gas_watch_decode(payload, sample_size, 1U, SET_GAS_WATCH_MAX, &sequence, ×tamp, decoded, valid, SET_GAS_WATCH_MAX) == (int)SET_GAS_WATCH_MAX); /* Максимальный пакет с разреженной маской остаётся допустимым. */ + CHECK(decoded[0] == 0U && decoded[7] == 0U && decoded[8] == 0U && decoded[63] == 0U); /* Недостоверные слова принудительно обнуляются на всех проверенных границах маски. */ + CHECK(sample.values[0] == 1000U && sample.values[63] == 1063U); /* Каноническое обнуление относится к wire-пакету и не меняет исходный снимок. */ + memcpy(before, payload, sizeof payload); /* Сохраняем полный выход перед ошибками модели сериализации. */ + sample.valid[63] = 2U; /* Признак достоверности допускает только значения 0 и 1. */ + CHECK(set_gas_watch_encode_sample(&sample, payload, sizeof payload) == 0U); /* Неверный признак в последнем канале проверяется до записи первого байта заголовка. */ + CHECK(memcmp(payload, before, sizeof payload) == 0); /* Поздняя ошибка модели не оставляет частично записанный пакет. */ + sample.valid[63] = 0U; /* Восстанавливаем двоичный признак перед проверкой неверного количества каналов. */ + sample.count = SET_GAS_WATCH_MAX + 1U; /* Число 65 находится за пределами обоих встроенных массивов снимка. */ + CHECK(set_gas_watch_encode_sample(&sample, payload, sizeof payload) == 0U); /* Проверка количества предотвращает выход за границу даже при достаточном output. */ + CHECK(memcmp(payload, before, sizeof payload) == 0); /* Неверное количество тоже не меняет выходной буфер. */ +} /* Завершение проверок некорректных входов и предельных размеров. */ + +int main(void) /* Один независимый исполняемый тест запускается общей системой CTest. */ +{ /* Начало последовательного запуска контрактных сценариев. */ + test_reference(); /* Эталонные байты фиксируют совместимость C, Python и JVM. */ + test_atomic_apply(); /* Ошибки настройки и повторные запросы не должны повреждать подписку. */ + test_capture_and_timing(); /* Снимок и приборный таймер проверяются отдельно от транспорта. */ + test_malformed_and_limits(); /* Входные границы проверяются и на устройстве, и в хостовом ABI. */ + if (failures != 0U) { /* Любое нарушение делает запуск неуспешным для CTest и CI. */ + printf("GAS_WATCH2: %u failures\n", failures); /* Итог сообщает число обнаруженных нарушений контракта. */ + return 1; /* Ненулевой код обозначает, что хотя бы одна контрактная проверка не прошла. */ + } /* Завершение ветки ошибочного результата. */ + puts("GAS_WATCH2 contract tests passed"); /* Краткая строка подтверждает завершение всех сценариев. */ + return 0; /* Нулевой код передаёт общий успех системе сборки. */ +} /* Завершение тестового исполняемого файла. */ diff --git a/c/set-protocol/tests/test_invertor_gas.c b/c/set-protocol/tests/test_invertor_gas.c new file mode 100644 index 0000000..cda145b --- /dev/null +++ b/c/set-protocol/tests/test_invertor_gas.c @@ -0,0 +1,103 @@ +#include "set_invertor_gas.h" /* Проверяем два публичных представления одной карты инвертора. */ +#include "pcan_id.h" /* Некорректные адреса узлов строятся тем же существующим кодеком ProtoCAN. */ +#include /* Ошибка теста выводит строку и возвращает ненулевой код также в Release. */ +#include /* Сравниваем исходные данные и неизменность выходного кадра при отказе. */ +#define CHECK(condition) do { if (!(condition)) { printf("invertor_gas:%d: %s\n", __LINE__, #condition); return 1; } } while (0) /* Проверки не зависят от assert или NDEBUG. */ +typedef struct { /* Этот массив существует только в тесте и не задаёт способ хранения прошивки. */ + uint16_t values[SET_INVERTOR_GAS_REGISTER_COUNT]; /* Отличимые значения позволяют обнаружить запись лишнего соседа. */ + unsigned reads; /* Счётчик выявляет скрытый read-modify-write при масочной записи. */ + unsigned commits; /* Каждая успешная запись должна иметь один вызов прикладной транзакции. */ + int unavailable; /* Отдельный адрес моделирует отсутствующее или недостоверное измерение. */ + int readonly; /* Независимый адрес запрещён для записи, но остаётся доступен для чтения. */ +} model; /* Все данные принадлежат тесту и отделены от общего wire-кодека. */ +static int Read(void *context, uint16_t address, uint16_t *value) /* Моделируем provider одного значения с явным отказом. */ +{ /* Чтение не меняет сами значения карты. */ + model *state = (model *)context; state->reads++; /* Считаем обращения независимо от успеха для проверки пути записи. */ + if (address >= SET_INVERTOR_GAS_REGISTER_COUNT || (int)address == state->unavailable) { return -1; } /* Отсутствие значения отличается от достоверного нуля. */ + *value = state->values[address]; return 0; /* Возвращаем текущее значение общей модели. */ +} /* Конец диагностического read-provider. */ +static int Write(void *context, const uint16_t *addresses, const uint16_t *values, unsigned count) /* Выполняем согласованное применение только полностью проверенного набора. */ +{ /* Тестовый provider реализует обязательный контракт проверки до изменения данных. */ + model *state = (model *)context; unsigned i; /* Контекст и индекс не обращаются к аппаратуре или динамической памяти. */ + if (count == 0U || count > PCAN_GAS_REGS_PER_FRAME) { return -1; } /* Пустая транзакция не считается успешной командой. */ + for (i = 0U; i < count; ++i) { if (addresses[i] >= SET_INVERTOR_GAS_REGISTER_COUNT || (int)addresses[i] == state->readonly || values[i] == UINT16_MAX) { return -1; } } /* Граница, readonly и запрещённое тестовое значение проверяются для всего набора до первой записи. */ + for (i = 0U; i < count; ++i) { state->values[addresses[i]] = values[i]; } /* Только полностью валидная транзакция изменяет выбранные адреса. */ + state->commits++; return 0; /* Подтверждаем ровно одно применение набора без протокольного ACK. */ +} /* Завершаем тестовый write-provider. */ +static pcan_frame_t RegisterFrame(unsigned address, const uint16_t *values, unsigned count) /* Сериализация обычного GAS выполняется существующей функцией Templates. */ +{ /* Нулевое число слов обозначает запрос чтения. */ + pcan_frame_t frame = {0}; /* Избегаем неинициализированных флагов и неиспользуемых октетов. */ + pcan_gas_regs_to_frame(&frame, set_invertor_gas_request_id(PCAN_MSG_GAS, address, 0U), (uint16_t)address, values, (uint16_t)count); /* Кодек задаёт little-endian и точную длину 0/2/4/6/8. */ + return frame; /* Возвращаем готовый транспортный кадр без второго wire-builder в тесте. */ +} /* Конец создания регистрового запроса. */ +static pcan_frame_t SlotFrame(unsigned slot, const uint16_t words[4]) /* Масочный payload формируется тем же общим кодеком, что используют клиенты. */ +{ /* NULL обозначает чтение слота без данных. */ + pcan_frame_t frame = {0}; uint_least8_t data[8] = {0}; unsigned i; /* Локальные буферы ограничены одним Classic CAN-кадром. */ + frame.id = set_invertor_gas_request_id(PCAN_MSG_GAS_SLOT, slot, 0U); frame.flags = PCAN_FLAG_IDE; /* Выбираем тип 0x4 отдельно от типа 0x3. */ + frame.dlc = (uint8_t)pcan_gas_slot_encode(words, words == NULL ? 0U : 4U, data); /* Существующий кодек проверяет непустую маску перед формированием октетов. */ + for (i = 0U; i < frame.dlc; ++i) { frame.data[i] = (uint8_t)data[i]; } /* Переносим готовые октеты в стандартный кадр тестового транспорта. */ + return frame; /* Ни одной формулы endian или CRC здесь нет. */ +} /* Конец создания слотного запроса. */ +int main(void) /* Проверяем согласованность, границы, права и отсутствие fallback между двумя типами. */ +{ /* Модель используется без подключения силовой электроники. */ + model state = {0}; set_invertor_gas_port_t port = {&state, Read, Write}; /* Оба типа GAS используют один и тот же provider. */ + pcan_frame_t request, response, unchanged; uint16_t pair[2], words[4], slot, word; unsigned i, reads, commits; pcan_id_t id; /* Все временные данные имеют фиксированные размеры. */ + state.unavailable = -1; state.readonly = -1; /* В начале все значения доступны и разрешены для тестовой записи. */ + for (i = 0U; i < SET_INVERTOR_GAS_REGISTER_COUNT; ++i) { state.values[i] = (uint16_t)(1000U + i); } /* Отличающиеся соседи показывают любую лишнюю запись. */ + CHECK(SET_INVERTOR_GAS_REGISTER_COUNT == 750U && SET_INVERTOR_GAS_SLOT_COUNT == 250U); /* Word0-маски не считаются дополнительными хранимыми значениями. */ + CHECK(set_invertor_gas_request_id(PCAN_MSG_GAS, 0U, 0U) == UINT32_C(0x17E30000)); /* Проверяем эталон первого запроса обычного GAS к узлу 7/E. */ + CHECK(set_invertor_gas_request_id(PCAN_MSG_GAS_SLOT, 0U, 0U) == UINT32_C(0x17E40000)); /* Тип слота отличается только назначенным полем MsgType. */ + CHECK(set_invertor_gas_request_id(PCAN_MSG_GAS, 749U, 1U) == UINT32_C(0x1FE302ED)); /* Проверяем последний регистр и направление ответа. */ + CHECK(set_invertor_gas_request_id(PCAN_MSG_GAS, 750U, 0U) == 0U && set_invertor_gas_request_id(PCAN_MSG_GAS_SLOT, 250U, 0U) == 0U); /* Первые адреса за двумя картами отвергаются без усечения. */ + CHECK(set_invertor_gas_request_id(5U, 0U, 0U) == 0U && set_invertor_gas_request_id(3U, 0U, 2U) == 0U); /* Другой MsgType и недопустимый Route не подменяются GAS. */ + CHECK(set_invertor_gas_register(249U, 3U) == 749 && set_invertor_gas_register(250U, 1U) == -1 && set_invertor_gas_register(0U, 0U) == -1); /* Маска не адресует регистр, а последняя полезная координата существует. */ + for (i = 0U; i < SET_INVERTOR_GAS_REGISTER_COUNT; ++i) { CHECK(set_invertor_gas_coordinate(i, &slot, &word)); CHECK(set_invertor_gas_register(slot, word) == (int32_t)i); } /* У каждой из 750 позиций есть ровно согласованная полезная координата. */ + slot = 99U; word = 88U; CHECK(!set_invertor_gas_coordinate(750U, &slot, &word)); CHECK(slot == 99U && word == 88U); /* Ошибка координат не изменяет выходы вызывающего. */ + pair[0] = 0x1234U; request = RegisterFrame(1U, pair, 1U); reads = state.reads; /* Одна уставка записывается обычным GAS без выбора слота. */ + CHECK(set_invertor_gas_handle(&port, &request, NULL) == 0); CHECK(state.values[0] == 1000U && state.values[1] == 0x1234U && state.values[2] == 1002U); CHECK(state.reads == reads); /* Соседние регистры не меняются и предварительное чтение не выполняется. */ + request = SlotFrame(0U, NULL); CHECK(set_invertor_gas_handle(&port, &request, &response) == 1); /* Тот же результат сразу виден через слотный доступ. */ + CHECK(pcan_gas_slot_decode_words(response.id, response.flags, response.data, response.dlc, words) == 4); CHECK(words[0] == 0xEU && words[1] == 1000U && words[2] == 0x1234U && words[3] == 1002U); /* Маска и три значения не создают второй копии данных. */ + words[0] = 4U; words[1] = 55U; words[2] = 4321U; words[3] = 66U; request = SlotFrame(0U, words); reads = state.reads; /* Выбираем только Word2; ненужные значения специально отличаются от текущих. */ + CHECK(set_invertor_gas_handle(&port, &request, NULL) == 0); CHECK(state.values[0] == 1000U && state.values[1] == 4321U && state.values[2] == 1002U && state.reads == reads); /* Неотмеченные поля сохраняются без чтения слота на клиенте. */ + request = RegisterFrame(1U, NULL, 0U); CHECK(set_invertor_gas_handle(&port, &request, &response) == 1); CHECK(pcan_gas_frame_to_regs(&response, words, 4U) == 4U && words[0] == 4321U); /* Изменение через 0x4 видно через обычный GAS 0x3. */ + state.readonly = 3; words[0] = 4U; words[2] = 2222U; request = SlotFrame(1U, words); /* В слоте 1 Word1 соответствует readonly-регистру 3, но маска выбирает регистр 4. */ + CHECK(set_invertor_gas_handle(&port, &request, NULL) == 0 && state.values[3] == 1003U && state.values[4] == 2222U); /* Неотмеченный readonly-сосед не мешает разрешённой записи. */ + pair[0] = 77U; pair[1] = 88U; state.readonly = 7; commits = state.commits; request = RegisterFrame(6U, pair, 2U); /* Второе слово блока намеренно запрещено для записи. */ + CHECK(set_invertor_gas_handle(&port, &request, NULL) == -1 && state.values[6] == 1006U && state.values[7] == 1007U && state.commits == commits); /* Весь блок отклоняется до применения первого корректного слова. */ + state.readonly = -1; request = RegisterFrame(749U, pair, 2U); CHECK(set_invertor_gas_handle(&port, &request, NULL) == -1 && state.values[749] == 1749U && state.commits == commits); /* Пересечение конца карты не вызывает частичную запись. */ + request = RegisterFrame(749U, NULL, 0U); CHECK(set_invertor_gas_handle(&port, &request, &response) == 1 && response.dlc == 2U); /* Конец обычной карты читается коротким корректным ответом из одного слова. */ + request = SlotFrame(249U, NULL); CHECK(set_invertor_gas_handle(&port, &request, &response) == 1 && response.dlc == 8U); /* Последний слот содержит все три реальные позиции 747…749. */ + state.unavailable = 1; request = SlotFrame(0U, NULL); CHECK(set_invertor_gas_handle(&port, &request, &response) == 1); /* Частичный ответ отмечает только реально доступные значения. */ + CHECK(pcan_gas_slot_decode_words(response.id, response.flags, response.data, response.dlc, words) == 4 && words[0] == 10U && words[2] == 0U); /* Недостоверный Word2 отличается от достоверного числового нуля отсутствием бита 2. */ + state.unavailable = -1; memset(&unchanged, 0xA5, sizeof(unchanged)); response = unchanged; /* Отмечаем выходной кадр для проверки всех отказов. */ + words[0] = 4U; words[2] = 200U; request = SlotFrame(0U, words); request.data[0] = 0x10U; commits = state.commits; /* Устанавливаем зарезервированный бит маски в заранее корректном wire-кадре. */ + CHECK(set_invertor_gas_handle(&port, &request, &response) == -1 && state.commits == commits && memcmp(&response, &unchanged, sizeof(response)) == 0); /* Отказ не меняет ни данные, ни предыдущий ответ. */ + request = SlotFrame(0U, words); request.dlc = 2U; CHECK(set_invertor_gas_handle(&port, &request, &response) == -1); /* У типа 0x4 нет формата короткой записи отдельного значения. */ + request = RegisterFrame(0U, pair, 1U); request.dlc = 1U; CHECK(set_invertor_gas_handle(&port, &request, &response) == -1); /* Нечётный обычный GAS не обрабатывается как корректное первое слово. */ + request.dlc = 9U; CHECK(set_invertor_gas_handle(&port, &request, &response) == -1); /* Payload больше Classic CAN не выходит за фиксированные массивы. */ + request = RegisterFrame(0U, pair, 1U); request.flags |= PCAN_FLAG_RTR; CHECK(set_invertor_gas_handle(&port, &request, &response) == -1); /* RTR не является командой записи. */ + request.flags = PCAN_FLAG_IDE | PCAN_FLAG_ERR; CHECK(set_invertor_gas_handle(&port, &request, &response) == -1); /* Ошибка транспорта не становится прикладной командой. */ + request.flags = 0U; CHECK(set_invertor_gas_handle(&port, &request, &response) == -1); /* Стандартный 11-битный кадр не совпадает с расширенным адресом инвертора. */ + request.flags = PCAN_FLAG_IDE; pcan_id_unpack(request.id, &id); id.device_id = 13U; request.id = pcan_id_pack(&id); /* Меняем адрес на существующий конфигуратор 7/D. */ + CHECK(set_invertor_gas_handle(&port, &request, &response) == -1 && state.commits == commits); /* Инвертор не исполняет запросы соседнего прибора. */ + request = RegisterFrame(0U, pair, 1U); pcan_id_unpack(request.id, &id); id.route = PCAN_ROUTE_FROM_DEVICE; request.id = pcan_id_pack(&id); /* Ответ другого прибора не должен исполняться повторно как запись. */ + CHECK(set_invertor_gas_handle(&port, &request, &response) == -1); /* Запросом считается только направление от верхнего уровня. */ + request = RegisterFrame(0U, NULL, 0U); CHECK(set_invertor_gas_handle(&port, &request, NULL) == -1); CHECK(set_invertor_gas_handle(NULL, &request, &response) == -1); /* Проверяем отсутствие буфера ответа и отсутствующий provider. */ + port.write = NULL; request = RegisterFrame(0U, pair, 1U); CHECK(set_invertor_gas_handle(&port, &request, NULL) == -1); /* Readonly-порт запрещает запись обоими представлениями данных. */ + request = SlotFrame(0U, words); CHECK(set_invertor_gas_handle(&port, &request, NULL) == -1); /* Слотная маска не обходит отсутствие write-provider. */ + { /* Клиентский ABI использует те же wire-векторы, не создавая второго кодека для GUI. */ + uint32_t identifier = 0U; uint8_t data[8] = {0}; unsigned metadata[2] = {99U, 88U}; int length; /* Буферы имеют точные пределы Classic CAN и одного ответа. */ + CHECK(set_invertor_gas_limit(3U) == 750U && set_invertor_gas_limit(4U) == 250U && set_invertor_gas_limit(5U) == 0U); /* Размеры берутся из единственного профиля, а не дублируются клиентом. */ + pair[0] = 0x1234U; length = set_invertor_gas_build(3U, 1U, pair, 1U, &identifier, data); /* Одна обычная уставка передаётся двумя октетами. */ + CHECK(length == 2 && identifier == UINT32_C(0x17E30001) && data[0] == 0x34U && data[1] == 0x12U && data[2] == 0U); /* Проверяем эталонные ID, little-endian и очищенный хвост. */ + CHECK(set_invertor_gas_decode(UINT32_C(0x1FE30001), 1U, data, 2U, metadata, words) == 1 && metadata[0] == 3U && metadata[1] == 1U && words[0] == 0x1234U); /* Клиентский разбор восстанавливает тот же тип, адрес и значение. */ + words[0] = 4U; words[1] = 0U; words[2] = 0x1234U; words[3] = 0U; /* Масочный wire-набор выбирает только второе полезное значение. */ + CHECK(set_invertor_gas_build(4U, 0U, words, 4U, &identifier, data) == 8 && identifier == UINT32_C(0x17E40000)); /* Builder использует именно слотный MsgType 0x4. */ + CHECK(data[0] == 4U && data[1] == 0U && data[4] == 0x34U && data[5] == 0x12U); /* Фиксированный тестовый вектор подтверждает положение маски и Word2. */ + CHECK(set_invertor_gas_decode(UINT32_C(0x1FE40000), 1U, data, 8U, metadata, words) == 4 && words[0] == 4U && words[2] == 0x1234U); /* Ответ проверяется тем же масочным кодеком. */ + CHECK(set_invertor_gas_build(4U, 0U, words, 3U, &identifier, data) == -1); /* Неполный масочный payload не упаковывается как обычный GAS. */ + CHECK(set_invertor_gas_decode(UINT32_C(0x17E40000), 1U, data, 8U, metadata, words) == -1); /* Эхо исходящего запроса не считается обновлением телеметрии. */ + CHECK(set_invertor_gas_decode(UINT32_C(0x1FE30000), 1U, data, 3U, metadata, words) == -1); /* Нечётный обычный payload отвергается клиентской границей. */ + } /* Клиентская проверка не обращается к реальному устройству. */ + puts("invertor GAS 0x3 + GAS SLOT 0x4: OK"); return 0; /* Все проверки выполнены на реальном общем C-кодеке без оборудования. */ +} /* Конец сценариев согласованности и защиты границ новой карты инвертора. */ diff --git a/c/set-protocol/tests/test_modbus_server.c b/c/set-protocol/tests/test_modbus_server.c index eb264cc..55b9189 100644 --- a/c/set-protocol/tests/test_modbus_server.c +++ b/c/set-protocol/tests/test_modbus_server.c @@ -10,18 +10,20 @@ #include "pcan_id.h" #include "pcan_modbus_server.h" -static uint16_t holding[32]; -static uint16_t input[32]; -static uint16_t coils; +static uint16_t holding[4096]; /* Полная 12-битная карта позволяет проверить последний допустимый адрес 0xFFF. */ +static uint16_t input[4096]; /* Входной банк имеет тот же размер 4096 адресов, что поле StrAdr. */ +static uint16_t coils = 0x000AU; /* Чередующиеся выходы 1 и 3 отличают функцию Coil=1 от Discrete=2. */ +static uint16_t discretes = 0x0014U; /* Входы 2 и 4 установлены для проверки сохранённого битового чтения типа 0x5. */ static bool read_word(void *user, pcan_modbus_bank_t bank, uint16_t address, uint16_t *value) { (void)user; - if (address >= 32U) return false; + if (address >= 4096U) return false; /* Provider не принимает адреса вне 12-битной карты. */ if (bank == PCAN_MODBUS_HOLDING) *value = holding[address]; else if (bank == PCAN_MODBUS_INPUT) *value = input[address]; - else if (bank == PCAN_MODBUS_COIL) *value = (uint16_t)((coils >> address) & 1U); + else if (bank == PCAN_MODBUS_DISCRETE && address < 16U) *value = (uint16_t)((discretes >> address) & 1U); /* Не сдвигаем 16-битное поле на недопустимое число позиций. */ + else if (bank == PCAN_MODBUS_COIL && address < 16U) *value = (uint16_t)((coils >> address) & 1U); /* Функция 1 читает независимую маску выходов. */ else return false; return true; } @@ -30,16 +32,14 @@ static bool write_word(void *user, pcan_modbus_bank_t bank, uint16_t address, uint16_t value) { (void)user; - if (address >= 32U) return false; + if (address >= 4096U) return false; /* Запись ограничена тем же адресным пространством, что чтение. */ if (bank == PCAN_MODBUS_HOLDING) holding[address] = value; - else if (bank == PCAN_MODBUS_COIL && address < 16U) { - if (value) coils |= (uint16_t)(1U << address); - else coils &= (uint16_t)~(1U << address); - } else return false; + else if (bank == PCAN_MODBUS_COIL && address < 16U) coils = (uint16_t)((coils & ~(1U << address)) | ((value & 1U) << address)); /* Один callback изменяет ровно выбранный выход. */ + else return false; /* Входные банки Discrete/Input недоступны для записи. */ return true; } -static pcan_frame_t request(uint8_t type, uint16_t address, uint8_t count) +static pcan_frame_t request(uint8_t function, uint16_t address, uint8_t count) /* Функция задаёт банк независимо от единого MsgType=0x5. */ { pcan_id_t id = {0}; pcan_frame_t frame = {0}; @@ -47,8 +47,8 @@ static pcan_frame_t request(uint8_t type, uint16_t address, uint8_t count) id.route = PCAN_ROUTE_FROM_PM; id.device_type = 7U; id.device_id = 3U; - id.msg_type = type; - id.msg_body = pcan_body_modbus(address, count); + id.msg_type = PCAN_MSG_MODBUS; /* Все четыре функции используют один код сообщения 0x5. */ + id.msg_body = pcan_body_modbus(address, count, function); /* Передаём физические значения функции и количества 1…4 общему упаковщику. */ frame.id = pcan_id_pack(&id); frame.flags = PCAN_FLAG_IDE; return frame; @@ -84,13 +84,47 @@ int main(void) CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_RESPONSE); CHECK(holding[3] == 0x1122U && holding[4] == 0x3344U); - req = request(PCAN_MODBUS_COIL, 2U, 3U); - req.dlc = 2U; req.data[0] = 0x05U; req.data[1] = 0U; + req = request(PCAN_MODBUS_DISCRETE, 2U, 3U); /* Читаем три входа 2…4 через сохранённый тип 0x5. */ CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_RESPONSE); - CHECK(coils == 0x0014U); + CHECK(rsp.dlc == 1U && rsp.data[0] == 0x05U); /* Три входа передаются младшими битами одного октета. */ + req.id = (req.id & ~0xF0000UL) | ((uint32_t)PCAN_MSG_GAS_SLOT << 16U); /* Подменяем MsgType на независимый GAS SLOT 0x4, сохраняя остальные поля. */ + CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_NOT_FOR_US); /* Слотный кадр не должен вызывать Modbus provider и менять его счётчики. */ - req = request(PCAN_MODBUS_INPUT, 0U, 5U); + req = request(PCAN_MODBUS_INPUT, 0xFFFU, 2U); /* Двухрегистровое окно с последнего адреса должно быть отвергнуто до обращения к карте. */ CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_HANDLED_NO_RESPONSE); CHECK(server.requests == 4U && server.responses == 3U && server.rejected == 1U); + for (uint8_t function = 1U; function <= 4U; ++function) { /* Покрываем все четыре банка единого сообщения. */ + for (uint8_t count = 1U; count <= 4U; ++count) { /* Каждая функция проверяется с каждым допустимым количеством. */ + uint16_t expected = (uint16_t)(0x20U | ((function - 1U) << 2U) | (count - 1U)); /* Адрес 2 остаётся в старших 12 битах, функция и количество независимо занимают по два бита. */ + CHECK(pcan_body_modbus(2U, count, function) == expected); /* Проверяем эталонную битовую раскладку всех 16 сочетаний. */ + CHECK(pcan_modbus_count(expected) == count && pcan_modbus_function(expected) == function); /* Декодирование возвращает исходные физические значения 1…4. */ + req = request(function, 2U, count); /* Запрашиваем окно в пределах тестовых битовых и регистровых банков. */ + CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_RESPONSE); /* Все допустимые сочетания обслуживаются сервером. */ + CHECK(rsp.dlc == (function <= 2U ? 1U : count * 2U)); /* Функции 1/2 возвращают октет, 3/4 — два октета на слово. */ + pcan_id_unpack(rsp.id, &id); /* Ответ должен сохранять банк и количество исходного запроса. */ + CHECK(id.msg_type == PCAN_MSG_MODBUS && id.msg_body == expected && id.route == PCAN_ROUTE_FROM_DEVICE); /* Меняется только направление сообщения. */ + if (function <= 2U) CHECK(rsp.data[0] == (((function == 1U ? coils : discretes) >> 2U) & ((1U << count) - 1U))); /* Сверяем каждый бит с независимым источником банка. */ + } /* Завершаем перебор количеств для текущей функции. */ + } /* Проверены все шестнадцать вариантов. */ + input[4095] = 0xFEDCU; /* Последний адрес карты содержит отличимое 16-битное значение. */ + req = request(PCAN_MODBUS_INPUT, 4095U, 1U); /* Окно из одного регистра на границе допустимо. */ + CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_RESPONSE && rsp.data[0] == 0xDCU && rsp.data[1] == 0xFEU); /* Верхняя граница и little-endian проверяются одновременно. */ + req = request(PCAN_MODBUS_COIL, 2U, 4U); /* Записываем четыре последовательных выхода отдельными битами. */ + req.dlc = 1U; req.data[0] = 0x09U; /* Выходы addr+0 и addr+3 включены, промежуточные выключены. */ + CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_RESPONSE && ((coils >> 2U) & 15U) == 9U); /* Provider получает правильные адреса и значения каждого выхода. */ + req.data[0] = 0x10U; /* Пятый бит не входит в заявленное четырёхбитное окно. */ + CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_HANDLED_NO_RESPONSE && ((coils >> 2U) & 15U) == 9U); /* Неверная маска отклоняется до изменения выходов. */ + req = request(PCAN_MODBUS_HOLDING, 3U, 2U); req.dlc = 3U; /* Двум регистрам нужны четыре октета; три являются неполным payload. */ + CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_HANDLED_NO_RESPONSE && holding[3] == 0x1122U); /* Неверная длина не меняет уже записанные значения. */ + for (uint8_t function = 2U; function <= 4U; function += 2U) { /* Функции входных банков 2 и 4 доступны только для чтения. */ + req = request(function, 2U, 1U); req.dlc = function == 2U ? 1U : 2U; /* Подготавливаем формально правильный payload записи readonly-банка. */ + CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_HANDLED_NO_RESPONSE); /* Сервер отвергает запись независимо от длины данных. */ + } /* Оба входных банка защищены. */ + req = request(PCAN_MODBUS_HOLDING, 0U, 1U); req.flags |= PCAN_FLAG_RTR; /* Remote frame не несёт разрешённого data payload ProtoCAN. */ + CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_HANDLED_NO_RESPONSE); /* RTR отвергается до чтения банка. */ + for (uint8_t type = 6U; type <= 7U; ++type) { /* Старые отдельные типы Holding/Input освобождены. */ + req = request(PCAN_MODBUS_HOLDING, 0U, 1U); req.id = (req.id & ~0xF0000UL) | ((uint32_t)type << 16U); /* Сохраняем адрес и Body, изменяя только номер сервиса. */ + CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_NOT_FOR_US); /* Освобождённые типы не маршрутизируются в Modbus. */ + } /* Проверены оба освобождённых номера. */ return 0; } diff --git a/c/set-protocol/tests/test_transport.c b/c/set-protocol/tests/test_transport.c index b25bcc3..5ce3b64 100644 --- a/c/set-protocol/tests/test_transport.c +++ b/c/set-protocol/tests/test_transport.c @@ -207,7 +207,7 @@ static void test_id(void) /* Раскладки MsgBody из protocan.h */ CHECK(pcan_body_broadcast(3U, 0U) == 0x0030U); CHECK(pcan_body_typed(4U, 17U) == 0x4011U); - CHECK(pcan_body_modbus(0x100U, 3U) == 0x1003U); + CHECK(pcan_body_modbus(0x100U, 3U, 4U) == 0x100EU); /* Адрес 0x100, функция Input=4 и три регистра дают wire-коды функции 3 и количества 2. */ CHECK(pcan_body_error(0U, 0xFFU) == 0x00FFU); } diff --git a/c/set-protocol/tools/build_host.py b/c/set-protocol/tools/build_host.py index 911da88..c587c88 100644 --- a/c/set-protocol/tools/build_host.py +++ b/c/set-protocol/tools/build_host.py @@ -24,13 +24,17 @@ INCLUDE = ROOT / "include" JNI_INCLUDES: list[Path] = [] SOURCES = [ ROOT / "src" / name for name in ( + "deif_xdi.c", # Общий DEIF входит в host-библиотеку. + "set_invertor_gas.c", # Собирает общий адаптер двух GAS для STM Invertor при прямом запуске host-builder. "set_regmap.c", "set_emu_ump.c", "set_emu_tms.c", "set_emu_igbt.c", "set_emu_server.c", "set_boot.c", "firmware_image.c", "altera_logic.c", "altera_stream.c", + "set_gas_watch.c", # Добавляет общий GAS_WATCH2 в прямые MSVC/CC сборки, чтобы новые ctypes/JNI символы были доступны. "set_protocol.c", "set_can.c", "set_firmware.c", "set_telemetry.c", "set_plot.c", "set_trends.c", "set_spectrum.c", "set_signal.c", "set_wavegen.c", "balsam_can.c", "set_crc.c", "periph28335.c", "tms2812.c", "gui_catalog.c", "gui_frame.c", "pcan_abi.c", "pcan_crc.c", "pcan_frame.c", "pcan_id.c", "pcan_link.c", "pcan_ring.c", "pcan_gas.c", "pcan_modbus_server.c", + "pcan_gas_slot.c", # Собирает единый слотный кодек также при прямой MSVC/CC сборке для ctypes и JNI. ) ] @@ -93,7 +97,9 @@ def main() -> int: JNI_INCLUDES.extend([include, include / {"Windows": "win32", "Darwin": "darwin"}.get(platform.system(), "linux")]) SOURCES.extend([ ROOT / "ports" / "android" / "set_plot_jni.c", + ROOT / "ports" / "android" / "set_deif_jni.c", # JNI общего протокольного ядра для JVM-тестов. ROOT / "ports" / "android" / "setprotocol_jni.c", + ROOT / "ports" / "android" / "gas_slots_jni.c", # Даёт host JVM тот же адаптер слотной адресации, который используется Android. ]) output = args.output.resolve() output.parent.mkdir(parents=True, exist_ok=True) diff --git a/c/st7789/st7789_disabled.h b/c/st7789/st7789_disabled.h new file mode 100644 index 0000000..c2e770c --- /dev/null +++ b/c/st7789/st7789_disabled.h @@ -0,0 +1,6 @@ +#ifndef ST7789_DISABLED_H /* Защищает отключённый аппаратный интерфейс от повторного включения. */ +#define ST7789_DISABLED_H /* Позволяет общему main обслуживать одинаковый API на плате без подключённого дисплея. */ +#include /* Время общего опроса передаётся как 32-битное число миллисекунд. */ +static inline void ST7789_BoardInit(void) { } /* Профиль без дисплея не включает SPI и не занимает GPIO, сохраняя работу всех моделей DEIF. */ +static inline void ST7789_BoardPoll(uint32_t now_ms) { (void)now_ms; } /* Опрос без экрана не блокирует UART/CAN/USB и не требует графических исходников в прошивке. */ +#endif /* Завершает отключённый backend общего интерфейса дисплея. */ diff --git a/doc/setcan/ALTERA_LOGIC_STREAM.md b/doc/setcan/ALTERA_LOGIC_STREAM.md index 13b6078..acf8e55 100644 --- a/doc/setcan/ALTERA_LOGIC_STREAM.md +++ b/doc/setcan/ALTERA_LOGIC_STREAM.md @@ -1,5 +1,7 @@ # Altera Logic — ONLINE через SETCAN / GAS / UART +> GAS `0x3` использует адреса отдельных 16-битных регистров. GAS SLOT `0x4` — отдельный сервис с маской в Word0 и тремя значениями Word1…Word3. Спецификация: `doc/setcan/protocan/OAP.md`; адреса этого документа остаются регистровыми. + Версия профиля: **1**. Реализация, порты и тесты принадлежат `templates`. Это профиль существующего classic SETCAN/ProtoCAN с 29-битным ID; он не подменяется кадром SETP v2 и не использует старые команды `A5 CMD` FPGA. diff --git a/doc/setcan/DEVICE_REGISTRY.md b/doc/setcan/DEVICE_REGISTRY.md index 62df0ec..c9dc88e 100644 --- a/doc/setcan/DEVICE_REGISTRY.md +++ b/doc/setcan/DEVICE_REGISTRY.md @@ -7,11 +7,24 @@ Device Name — отображаемое имя адреса, а не допол | DeviceType | DeviceID | Device Name | Назначение | |---|---|---|---| | `0x0` | существующие | Верхний уровень | Существующие адреса исходной таблицы | -| `0x3` | `0x7` | **F28335-M95M02** | Загрузка прошивки по ProtoCAN в EEPROM M95M02 платы TMS320F28335; ProductType `0x2833` | -| `0x6` | `0xE` | **Altera Logic** | Онлайн-анализатор 16 цифровых каналов | +| `0x1` | `0x0…0xF` | PERIPH 0–15 | Первая группа периферии по обновлённому листу «Интерфейс протокола» | +| `0x2` | `0x0…0xF` | PERIPH 16–31 | Вторая группа; номер PERIPH = 16 + DeviceID | +| `0x1` | `0x5` | **УМП1** | PERIPH 5, собственный адрес обычного обмена ProtoCAN и загрузчика | +| `0x1` | `0x6` | УМП2 | PERIPH 6, GAS 0x3 — регистры; GAS SLOT 0x4 — слоты 0x0600…0x0642 | +| `0x6` | `0xE` | Altera Logic | Отдельный существующий потоковый профиль FE00/FF00 | | `0x7` | `0xD` | configurator | Существующий конфигуратор | +| `0x7` | `0xE` | **STM Invertor** | Самостоятельный ПЧ STM32G474VET6; отдельный GAS-профиль на 250 слотов 0x4, 750 значений; Word0 — маска | | `0x7` | `0xF` | KONOR / SETTINGS | Существующий профиль SETCAN и привязка датчиков | +Источник PERIPH: [Протокол CAN и ОАП.xlsx](Протокол%20CAN%20и%20ОАП.xlsx), +лист «Интерфейс протокола», A44:F79. Формула: Type = 1 + ID PERIPH / 16 +(целая часть), DeviceID = ID PERIPH mod 16. Зарезервированные номера не получают +назначений по аналогии со старым Бальзам CAN. Общий Boot-адрес `3/7` отменён. +В ПМ35 приложение использует аппаратный Mode, постоянный загрузчик читает те же +GPIO21/20/22/51; на существующей плате четыре перемычки задают номера 1–16. +Для номеров 0 и 17–31 требуется соответствующий источник аппаратного номера. +Старые CAN ID `0x00BA0007`/`0x00BA0017` задатчика остаются отдельным legacy-форматом. + Для Altera Logic выбран предпоследний тип `0x6` и предпоследний экземпляр `0xE`: эта пара не была назначена в проверенных локальных таблицах и исходниках. Тип `0x7` уже используется. Наличие другого физического узла с тем же адресом @@ -20,3 +33,9 @@ Device Name — отображаемое имя адреса, а не допол Числовые константы устройства: `c/set-protocol/include/altera_stream.h`. Отображаемые имена: `python/protocan/protocan.py`. Контракт потока: [ALTERA_LOGIC_STREAM.md](ALTERA_LOGIC_STREAM.md). + +## Mode и два типа GAS + +Таблица назначений и правила: [OAP.md](protocan/OAP.md). Mode 1/2 — трансформаторы; 3/4 — силовые узлы; 5/6 — УМП; 7 — ENG1; 8 — задатчик/пульт (`adr_PULT`); 9 — шкаф. 10 и 11 — служебные роли общего адреса и терминала. Остальные назначения не выводятся по аналогии со старым Бальзам CAN. + +GAS 0x3 адресует отдельные регистры 0…65535. GAS SLOT 0x4: `Slot=(mode<<8)|LocalSlot`, LocalSlot `0x00…0x42`; Word0 — маска, Word1…Word3 — значения. На mode сохранены 200 значений; последний слот содержит два. Прибор 5 не обслуживает страницу 0x06xx. diff --git a/doc/setcan/README.md b/doc/setcan/README.md index 734ab80..e6987ea 100644 --- a/doc/setcan/README.md +++ b/doc/setcan/README.md @@ -36,3 +36,7 @@ - [Реестр устройств SETCAN](DEVICE_REGISTRY.md). - [ONLINE-поток Altera Logic через GAS и UART](ALTERA_LOGIC_STREAM.md). + +## GAS: регистры 0x3 и слоты 0x4 + +[Адресация GAS](protocan/OAP.md): `0x3` — отдельные 16-битные регистры `0…65535`, запись 1…4 слов. `0x4` — слот с Word0-маской и тремя значениями; PERIPH сохраняет 200 слов в 67 слотах `0xMM00…0xMM42`. Формат определяется MsgType, без настройки профиля. diff --git a/doc/setcan/index.html b/doc/setcan/index.html index bc83213..0cffed8 100644 --- a/doc/setcan/index.html +++ b/doc/setcan/index.html @@ -134,7 +134,7 @@ └── doc/index.html эта страница
Зависимости

Что ожидает модуль

  • main.h и can.h из CubeMX
  • STM32 HAL CAN, RTC и TIM
  • CAN FIFO0 и Extended ID
  • STM32 GCC ABI для C bit-fields
Входящие

Путь кадра

IRQ вычитывает FIFO0. Pulse обрабатывается сразу, остальные Extended-кадры попадают в кольцевой буфер и разбираются в основном цикле.

-
Исходящие

Единая точка отправки

PROTOCAN_SEND() выбирает упаковщик по MsgType. GAS и Modbus автоматически разбиваются на кадры до 8 байт.

+
Исходящие

Единая точка отправки

PROTOCAN_SEND() выбирает упаковщик по MsgType. GAS разбивается на кадры до 8 байт; единый Modbus передаёт одно окно из 1–4 битов или регистров.

Граница

Что приложение реализует само

Прикладные действия, хранение SETTINGS, EEPROM, DS18B20, таймаут online/offline и полноценный bootloader не входят в ядро.

@@ -157,7 +157,7 @@ ProtoCanPulseCallbackОтправляет периодический pulse со счётчиком.Из callback нужного базового таймера. PROTOCAN_SEND_SETTINGS_RESPONSE / ERRORФормирует успешный либо ошибочный ответ привязки ROM.Из пользовательского обработчика SETTINGS.
-

Точки расширения

Переопределите нужную __weak-функцию в собственном C-файле: семейства ProtoCanMsgToBroadcast…, …Discrete…, …Analog…, ProtoCanMsgToSettings, ProtoCanMsgToGeneralAddressSpace и …Modbus…. Не редактируйте демонстрационную реализацию в ядре — так обновлять библиотеку проще.

+

Точки расширения

Переопределите нужную __weak-функцию в собственном C-файле: семейства ProtoCanMsgToBroadcast…, …Discrete…, …Analog…, ProtoCanMsgToSettings, ProtoCanMsgToGeneralAddressSpace и ProtoCanMsgToModbus. Не редактируйте демонстрационную реализацию в ядре — так обновлять библиотеку проще.

@@ -168,7 +168,7 @@ Priority Route DeviceType DeviceID MsgType MsgBody 1 бит 1 бит 3 бита 4 бита 4 бита 16 бит
Многобайтовые значения payload передаются little-endian. Разметка ID через C bit-fields требует проверки при смене компилятора или ABI.

Реестр MsgType

- +
КодТипНазначениеСтатус
0x0BROADCASTОбщие команды всем устройствамstable
0x1DISCRETEСостояния, команды, флагиstable
0x2ANALOGДатчики U / I / T и универсальные данныеstable
0x3GASОбщее 16-битное адресное пространствоstable
0x4…0x7MODBUSCoil, Discrete, Holding, Inputstable
0x8ERRORКод ошибки и дополнительная информацияstable
0x9…0xDBOOTУправление, блоки A/B, статус, discoverydraft
0xESETTINGSПривязка 1-Wire ROM к локации Z/Ystable
0xFPULSEПрисутствие устройстваstable
0x0BROADCASTОбщие команды всем устройствамstable
0x1DISCRETEСостояния, команды, флагиstable
0x2ANALOGДатчики U / I / T и универсальные данныеstable
0x3GASОбщее 16-битное адресное пространствоstable
0x4GAS SLOTWord0 — маска битов 1…3, Word1…Word3 — три значенияstable
0x5MODBUSФункция 1–4: Coil, Discrete, Holding, Input; количество 1–4stable
0x6…0x7РезервСвободныreserved
0x8ERRORКод ошибки и дополнительная информацияstable
0x9…0xDBOOTУправление, блоки A/B, статус, discoverydraft
0xESETTINGSПривязка 1-Wire ROM к локации Z/Ystable
0xFPULSEПрисутствие устройстваstable
@@ -300,8 +300,8 @@ if (PROTOCAN_SEND(id, tx) != PROTOCAN_OK) {

Документация ProtoCAN

Статус комплекта: Draft
-Версия комплекта: 1.0
-Дата редакции: 2026-08-29
+Версия комплекта: 2.1
+Дата редакции: 2026-10-23
Транспорт: Classic CAN 2.0B, Extended ID, DLC 0…8

Этот каталог разделяет нормативное описание протокола, загрузчик и реестр общего адресного пространства. Большой исходный документ @@ -364,10 +364,12 @@ if (PROTOCAN_SEND(id, tx) != PROTOCAN_OK) {

Все документы и тестовые векторы включаются в единый файл doc/setcan/index.html. Скрипт не изменяет исходные Markdown/XLSX и пригоден для запуска в CI.

+

GAS: регистры 0x3 и слоты 0x4

+

Адресация GAS: 0x3 — отдельные 16-битные регистры 0…65535, запись 1…4 слов. 0x4 — слот с Word0-маской и тремя значениями; PERIPH сохраняет 200 слов в 67 слотах 0xMM00…0xMM42. Формат определяется MsgType, без настройки профиля.

ProtoCAN — базовый протокол

Статус: Stable с зарезервированным загрузочным расширением
-Версия: 1.0
+Версия: 2.2: единый Modbus 0x5, функции и количество 1…4
Порядок байтов payload: little-endian, если явно не указано иное

Назначение

ProtoCAN — прикладной протокол поверх classic CAN 2.0B. Используются только @@ -502,35 +504,28 @@ Priority Route DeviceType DeviceID MsgType MsgBody GAS оба 0/2/4/6/8 -stable +регистры 0…65535 0x4 -MODBUS_COIL +GAS_SLOT оба -0…8 -stable +0/8 +Word0 — маска, Word1…Word3 — значения 0x5 -MODBUS_DISCRETE +MODBUS оба -0…8 -stable +0/1/2/4/6/8 +функции 1…4, количество 1…4 -0x6 -MODBUS_HOLDING -оба -0…8 -stable - - -0x7 -MODBUS_INPUT -оба -0…8 -stable +0x6…0x7 +резерв +— +— +свободны 0x8 @@ -609,14 +604,18 @@ Priority Route DeviceType DeviceID MsgType MsgBody подтип [15:12], значение/адрес [11:0] -Modbus -начальный адрес [15:4], количество [3:0] +Modbus 0x5 +адрес [15:4], функция − 1 [3:2], количество − 1 [1:0] -GAS +GAS 0x3 адрес первого 16-битного регистра [15:0] +GAS SLOT 0x4 +адрес слота [15:0]; маска — в Word0 payload, значения — Word1…Word3 + + error дополнительная информация [15:8], код [7:0] @@ -634,7 +633,64 @@ Priority Route DeviceType DeviceID MsgType MsgBody +

Контракт обоих GAS: OAP.md. Тип 0x3 адресует отдельные слова; тип 0x4 имеет маску битов 1…3 в Word0 и три значения. Для PERIPH 0x4 используются 67 слотов 0xMM00…0xMM42, последний содержит два значения. Старый Coil 0x4 заменён; формат определяется MsgType.

+

Единый Modbus 0x5

+

Все четыре банка используют один MsgType=0x5. Коды 0x6 и 0x7 свободны. +Начальный адрес занимает [15:4] и лежит в диапазоне 0x000…0xFFF. +Биты [3:2] содержат Function − 1, биты [1:0] — RegCount − 1. +Физические значения функции и количества: 1…4. Всё окно должно помещаться +в 4096 адресов: StrAdr + RegCount ≤ 4096.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ФункцияБанкЭлементDLC данных
1Coilдискретный выход1 байт для 1…4 битов
2Discreteдискретный вход1 байт для 1…4 битов
3Holding16-битный регистр2 × RegCount, 2/4/6/8 байт
4Input16-битный регистр2 × RegCount, 2/4/6/8 байт
+

Это селектор банка в ProtoCAN по нумерации функций Modbus, без RTU-заголовка +и CRC. Сохраняется правило ProtoCAN: Route=0, DLC=0 читает окно; +непустой payload записывает Coil/Holding, Discrete/Input доступны только +для чтения. Ответ имеет Route=1, сохраняет MsgBody и содержит значения +либо эхо успешной записи. RTR запрещён. Биты упакованы начиная с младшего, +старшие неиспользуемые биты нулевые. Регистры передаются little-endian.

+

Пример: адрес 0x123, функция 3, четыре регистра дают +MsgBody = (0x123 << 4) | ((3 − 1) << 2) | (4 − 1) = 0x123B.

+

Изменение wire-формата несовместимо с прежними отдельными типами +0x5/0x6/0x7: узлы и клиенты обновляются согласованно. Тип GAS SLOT 0x4 +сохраняет своё назначение.

Общие правила обмена

+

Профиль синхронизации часов и сообщения платы о завершении инициализации: +GLOBAL_TIME.md. Он сохраняет штатный BROADCAST RTCSETUP +и определяет общий пакет готовности поверх DISCRETE/FLAGS.

  • Многобайтовые значения в DATA передаются little-endian.
  • Узел игнорирует адресованные кадры с чужим DeviceType/DeviceID.
  • @@ -998,99 +1054,501 @@ anti-rollback. Bootloader не обновляется командами B
  • Новое приложение после самопроверки выполняет CONFIRM.
-

Общее адресное пространство

-

Статус: Stable, данные ведутся в XLSX
-Порядок значений: 16-битные регистры, little-endian в CAN payload

-

Редактируемый источник реестра: -Протокол CAN и ОАП.xlsx.

-

Просматриваемая большая таблица находится в -Протокол CAN и ОАП.html и -Протокол CAN и ОАП.md.

-

Назначение

-

ОАП связывает 16-битный адрес регистра с его типом, назначением, доступом и -масштабом. В ProtoCAN используется MsgType=0x3, а MsgBody содержит адрес -первого регистра.

-

Обязательные поля реестра

+

Общее адресное пространство: GAS и GAS SLOT

+

Дата редакции: 2026-10-23. Номер типа однозначно определяет единицу адресации:

- - + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + +
ПолеТребованиеMsgTypeИмяMsgBodyPayload
AddressHex0x0000…0xFFFF, уникальное значение0x3GASадрес первого 16-битного регистра1…4 последовательных регистра, DLC 2/4/6/8
AddressDecдесятичный эквивалент AddressHex
Groupфункциональная группа
Nameоднозначное имя параметра
Typeu16, i16, u32, i32, float32, bitmap или массив
Registersчисло занятых 16-битных регистров
AccessR, W или RW
Unitфизическая единица либо —
Scaleмножитель/делитель представления
Defaultзначение после сброса, если применимо
Descriptionсемантика, диапазон и особые значения0x4GAS SLOTадрес слотаWord0 — маска; Word1…Word3 — три значения; DLC 8
-

Правила ведения

+

В обоих случаях запрос чтения — extended data frame с DLC=0, Route=0. +Ответ имеет Route=1, тот же узел и адрес. Прикладного ACK записи нет; +успех применения уставки проверяется прикладным ответом или последующим чтением. +RTR, error frame, стандартный 11-битный ID и нечётные длины не исполняются.

+

GAS 0x3: отдельные регистры

+

MsgBody=RegisterAddress[15:0]. Адреса 0…65535 (0x0000…0xFFFF) +обозначают 65 536 отдельных 16-битных регистров, логически 128 КиБ на узел. +Это адреса протокола, а не указатели RAM MCU; provider подключает только существующие регионы.

+

Payload содержит значения с адресов addr, addr+1, addr+2, addr+3 +в порядке little-endian. Количество равно DLC/2, допускаются DLC 2, 4, 6, 8. +Для изменения одной уставки по адресу 0x0001 на 0x1234 передаются +MsgBody=0x0001, DLC=2, Data=34 12; соседние слова не изменяются. +Чтение возвращает до четырёх существующих последовательных регистров, +останавливаясь на первом недоступном адресе или границе 0xFFFF. +Запись, пересекающая 0xFFFF, отвергается до изменения данных.

+

Регионы карты, права и значения проверяет pcan_gas; callback остаётся +ответственностью приложения. Блочная запись может остановиться на первом отказе provider: +атомарность нескольких регистров не обещается. Связанные u32/float32 и команды +требуют согласованной прикладной операции. Основной контракт: c/set-protocol/docs/legacy/GAS.md. +GAS 167/v1, GAS Logger, GAS_WATCH2, NAND и Altera Logic сохраняют регистровые адреса. +Номер mode задаёт адрес узла; его нельзя автоматически прибавлять к адресу регистра.

+

GAS SLOT 0x4: маска в Word0

+

MsgBody=SlotAddress[15:0]. Восемь октетов имеют фиксированное расположение:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ОктетыWire-словоНазначение
0…1Word016-битная маска, little-endian
2…3Word1первое значение
4…5Word2второе значение
6…7Word3третье значение
+

Биты маски 1, 2, 3 соответствуют Word1, Word2, Word3. Бит 0 и биты 4…15 +зарезервированы и должны быть нулевыми. Маска непустая; все допустимые маски: +0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, 0x000E. +При записи отмеченные значения применяются, неотмеченные позиции игнорируются +и сохраняют текущие значения устройства. Нули не являются специальными маркерами. +При чтении маска ответа отмечает достоверные/доступные значения.

+

Например, изменить только Word2 на 0x1234: Data=04 00 00 00 34 12 00 00. +Word1 и Word3 сохраняются. Полная запись трёх значений использует маску 0x000E. +Передаются всегда восемь октетов, кроме пустого запроса чтения. Сжатия или сегментации нет. +Provider проверяет все выбранные права и значения до первого изменения, затем применяет +выбранные слова под общей блокировкой. Невыбранные readonly-поля не записываются. +Ядро не выполняет опасное чтение-изменение-запись слота на стороне клиента.

+

Полное пространство 0x4 содержит 65 536 слотов × 3 значения = 196 608 слов = 384 КиБ. +Word0 — метаданные кадра, не четвёртый хранимый регистр. Координата значения — +(SlotAddress, WordIndex), где WordIndex=1…3. Любой узел поддерживается общими +pcan_gas_slot_id() и pcan_gas_slot_handle_address(); адрес слота не ограничен страницами PERIPH. +Тип 0x4 MODBUS_COIL заменён этим сервисом. Единый Modbus использует 0x5, функцию и количество 1…4 в Body; 0x6/0x7 свободны. +Старое оборудование с Coil 0x4 требует согласованного обновления; автоопределения формата нет.

+

PERIPH: проекция 200 слов на слоты 0x4

+

mode=0…31; DeviceType=1+mode/16, DeviceID=mode mod 16. +SlotAddress=(mode<<8)|LocalSlot. Маски не занимают места в карте значений. +На mode сохранены 200 слов, поэтому используются 67 слотов LocalSlot=0x00…0x42: +66 полных слотов и два значения последнего. В последнем разрешена только маска +из битов 1/2 (0x0002, 0x0004, 0x0006); Word3 не существует. +LocalSlot=0x43…0xFF — резерв. Узел и старший октет слота должны совпадать.

+

Смещение технологического слова: n=3*LocalSlot+(WordIndex-1). +Обратное преобразование: LocalSlot=n/3, WordIndex=1+n mod 3. +Соседние native-сервисы могут оказаться в одном слоте, поэтому provider проверяет +доступ и наличие каждой отмеченной позиции отдельно.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
modeНазначениеDeviceType / DeviceIDСлоты 0x4Запрос первого слота
0Резерв0x01 / 0x000x0000…0x00420x11040000
1Трансформатор 10x01 / 0x010x0100…0x01420x11140100
2Трансформатор 20x01 / 0x020x0200…0x02420x11240200
3Силовой узел 10x01 / 0x030x0300…0x03420x11340300
4Силовой узел 20x01 / 0x040x0400…0x04420x11440400
5УМП10x01 / 0x050x0500…0x05420x11540500
6УМП20x01 / 0x060x0600…0x06420x11640600
7ENG10x01 / 0x070x0700…0x07420x11740700
8Задатчик / пульт0x01 / 0x080x0800…0x08420x11840800
9Шкаф0x01 / 0x090x0900…0x09420x11940900
10Общий адрес: служебная роль0x01 / 0x0A0x0A00…0x0A420x11A40A00
11Терминал: служебная роль0x01 / 0x0B0x0B00…0x0B420x11B40B00
12Резерв назначения0x01 / 0x0C0x0C00…0x0C420x11C40C00
13Резерв назначения0x01 / 0x0D0x0D00…0x0D420x11D40D00
14Резерв назначения0x01 / 0x0E0x0E00…0x0E420x11E40E00
15Резерв назначения0x01 / 0x0F0x0F00…0x0F420x11F40F00
16Резерв назначения0x02 / 0x000x1000…0x10420x12041000
17Резерв назначения0x02 / 0x010x1100…0x11420x12141100
18Резерв назначения0x02 / 0x020x1200…0x12420x12241200
19Резерв назначения0x02 / 0x030x1300…0x13420x12341300
20Резерв назначения0x02 / 0x040x1400…0x14420x12441400
21Резерв назначения0x02 / 0x050x1500…0x15420x12541500
22Резерв назначения0x02 / 0x060x1600…0x16420x12641600
23Резерв назначения0x02 / 0x070x1700…0x17420x12741700
24Резерв назначения0x02 / 0x080x1800…0x18420x12841800
25Резерв назначения0x02 / 0x090x1900…0x19420x12941900
26Резерв назначения0x02 / 0x0A0x1A00…0x1A420x12A41A00
27Резерв назначения0x02 / 0x0B0x1B00…0x1B420x12B41B00
28Резерв назначения0x02 / 0x0C0x1C00…0x1C420x12C41C00
29Резерв назначения0x02 / 0x0D0x1D00…0x1D420x12D41D00
30Резерв назначения0x02 / 0x0E0x1E00…0x1E420x12E41E00
31Резерв назначения0x02 / 0x0F0x1F00…0x1F420x12F41F00
+

Назначения mode из periph_28335

+

Источники: 28335_periph/Source/Internal/Include/package.h, peripher.c:get_Mode(), cntrl_adr.c. Код платы Desk не участвует в вычислении адреса.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
modeНазначениеИсходный символ
0РезервПеремычками текущей платы не задаётся
1 / 2Трансформаторные узлы 1 / 2adr_TRN1 / adr_TRN2
3 / 4Силовые узлы 1 / 2adr_POW1 / adr_POW2
5 / 6УМП1 / УМП2adr_LOA1 / adr_LOA2, Desk=dsk_LOAD=6
7ENG1adr_ENG1
8Задатчик / пультadr_PULT; имя «Задатчик» принято в реестре PERIPH
9Шкафadr_SHKF
10Общий адрес, служебная рольCNTRL_ADDR_UNIVERSAL, ADDR_FOR_ALL; не отдельная плата
11Терминал, служебная рольADDR_TERMINAL; не доказательство отдельной платы
12…31Резерв назначенияПеремычки текущей платы дают только 1…16
+

Соответствия native-сервисам PERIPH

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Смещение nNative-адресНазначениеДоступ
0…1270x0000…0x007Fтехнологические данные, уставки, командыпо provider
128…1430x1000…0x100Fстатус регистратора УМПR
144…1550x1200…0x120Bпаспорт прошивкиR
156…1630x1300…0x1307защита УМПW только 0x1302/0x1303
164…1670x1000…0x1003команды регистраторапо операции
168…199нетрезервотказ
+

pcan_gas_slot_native() принимает WordIndex=1…3; WordIndex=0 является маской +и не переводится в регистр. Наличие сервиса, права и блокировку проверяет приложение. +GAS 0x3 сохраняет собственные адреса подключённых регионов; эта проекция относится только к 0x4. +Архив УМП, окна 120/124 слова и физическая EEPROM сохраняют native-контракты.

+

Реализация и реестр

    -
  • Адрес не переиспользуется с другим смыслом после выпуска стабильной версии.
  • -
  • Многорегистровое значение занимает непрерывный диапазон.
  • -
  • Порядок 16-битных слов для 32-битного значения фиксируется в строке типа.
  • -
  • Резервные диапазоны явно отмечаются и не используются без изменения версии.
  • -
  • Удалённый параметр помечается deprecated, а не исчезает молча.
  • -
  • Изменение адреса, типа или масштаба отражается в CHANGELOG.md.
  • +
  • GAS 0x3: pcan_gas.h/.c, существующие ABI и клиенты.
  • +
  • GAS SLOT 0x4: pcan_gas_slot.h/.c; тонкие Python GasSlots и Android/JNI GasSlots.
  • +
  • Формат определяется MsgType, параметр gas_profile не используется.
  • +
  • C28x хранит wire-октеты в uint_least8_t; DLC измеряется октетами линии.
  • +
  • Перенос в другую единицу адресации или fallback после отказа запрещены.
-

Экспорт

-

Для программной генерации каталог следует экспортировать из XLSX в CSV с -UTF-8 и фиксированными английскими именами колонок. CSV должен проверяться на:

-
    -
  • уникальность адресов;
  • -
  • пересечение многорегистровых значений;
  • -
  • допустимые типы и права доступа;
  • -
  • равенство шестнадцатеричного и десятичного адреса;
  • -
  • попадание адреса в диапазон 0x0000…0xFFFF.
  • -
-

До появления автоматического экспортёра нормативным источником адресов -остаётся XLSX, а HTML/Markdown считаются представлением.

+

XLSX «Интерфейс протокола» содержит оба типа; «Общее адресное пространство» — +проекцию 0x4 и native-адреса её значений; «ОАП legacy» сохраняет исходный словный реестр 0x3. +Уникальный ключ реестра включает узел, MsgType, адрес и для 0x4 WordIndex. +Права, тип, единица, масштаб и порядок слов u32/float32 задаются явно. +Эталоны: examples/gas-slot-vectors.json; регистровые проверки — test_gas_register.c.

История изменений ProtoCAN

Формат основан на Keep a Changelog. Версия относится к спецификации, а не к версии прошивки отдельного прибора.

[Unreleased]

+

Changed — 2026-10-23

+
    +
  • Modbus Discrete/Holding/Input объединены в MsgType 0x5; Coil/Discrete/Holding/Input выбираются функцией 1…4, количество ограничено 1…4.

    +
  • +
  • Body Modbus: адрес [15:4], функция минус один [3:2], количество минус один [1:0]; номера 0x6/0x7 освобождены.

    +
  • +
  • GAS 0x3 возвращён к адресации отдельных 16-битных регистров 0…65535, DLC 0/2/4/6/8.

    +
  • +
  • Слотный GAS перенесён на 0x4 вместо MODBUS_COIL; Word0 содержит маску битов 1…3, Word1…Word3 — значения.

    +
  • +
  • PERIPH сохраняет 200 значений на mode в 67 слотах; последний содержит два значения.

    +
  • +
  • Формат выбирается номером MsgType; Python/JNI, STM32, Modbus routing, тесты, XLSX и HTML согласованы.

    +
  • +

Added

  • Структурированный комплект документации doc/setcan/protocan.
  • diff --git a/doc/setcan/protocan/CHANGELOG.md b/doc/setcan/protocan/CHANGELOG.md index 73c921e..8d22bce 100644 --- a/doc/setcan/protocan/CHANGELOG.md +++ b/doc/setcan/protocan/CHANGELOG.md @@ -5,6 +5,16 @@ ## [Unreleased] +### Changed — 2026-10-23 + +- Modbus Discrete/Holding/Input объединены в MsgType 0x5; Coil/Discrete/Holding/Input выбираются функцией 1…4, количество ограничено 1…4. +- Body Modbus: адрес [15:4], функция минус один [3:2], количество минус один [1:0]; номера 0x6/0x7 освобождены. + +- GAS 0x3 возвращён к адресации отдельных 16-битных регистров 0…65535, DLC 0/2/4/6/8. +- Слотный GAS перенесён на 0x4 вместо MODBUS_COIL; Word0 содержит маску битов 1…3, Word1…Word3 — значения. +- PERIPH сохраняет 200 значений на mode в 67 слотах; последний содержит два значения. +- Формат выбирается номером MsgType; Python/JNI, STM32, Modbus routing, тесты, XLSX и HTML согласованы. + ### Added - Структурированный комплект документации `doc/setcan/protocan`. diff --git a/doc/setcan/protocan/GLOBAL_TIME.md b/doc/setcan/protocan/GLOBAL_TIME.md new file mode 100644 index 0000000..ae25d39 --- /dev/null +++ b/doc/setcan/protocan/GLOBAL_TIME.md @@ -0,0 +1,97 @@ +# ProtoCAN: глобальное время и завершение инициализации платы + +Профиль библиотеки [`c/global-time`](../../../c/global-time/README.md). +Время использует штатную команду BROADCAST RTCSETUP. +Общий флаг готовности — новое соглашение этого профиля поверх DISCRETE/FLAGS; +его нельзя считать уже реализованным всеми историческими приборами ProtoCAN. + +## Плата → верхний уровень: готовность + +После успешной инициализации оборудования и параметров плата отправляет: + +| Поле | Значение | +|---|---| +| IDE / RTR | 1 / 0 | +| Priority | 1, standard | +| Route | 1, от устройства | +| DeviceType / DeviceID | собственный адрес платы | +| MsgType | 0x1, DISCRETE | +| MsgBody | 0x3000: подтип FLAGS=3, страница 0 | +| DLC | 1 | +| DATA[0] | 0x01: бит 0 означает «инициализация завершена» | + +Биты DATA[0] 1..7 зарезервированы нулями. Пакет не меняет локальные +технологические флаги «Статус инициализации» в ОАП конкретных приборов. +В этом профиле Body `0x3000`, DLC1, DATA01 закреплены за общим событием готовности; +приборы с другим историческим назначением этой комбинации требуют адаптера. + +Для PERIPH5 / УМП1, Type1/ID5: + +```text +CAN ID 0x19513000, DLC 1, DATA 01 +``` + +Плата посылает готовность хотя бы один раз, даже если успела получить broadcast +ещё до завершения собственной инициализации. Пока синхронизация не получена, +событие повторяется не чаще одного раза в 1000 мс. Повтор не означает новый reset; +мастер может объединять несколько близких запросов в один broadcast. + +## Верхний уровень → все платы: дата и время + +При получении готовности мастер читает свою текущую дату, формирует штатный +RTCSETUP и отправляет один кадр всем узлам. Может также периодически передавать +RTCSETUP для коррекции дрейфа; библиотека принимает каждый корректный пакет. + +| Поле | Значение | +|---|---| +| IDE / RTR | 1 / 0 | +| Priority | 0 или 1 | +| Route | 0, от ПМ | +| DeviceType / DeviceID | 0 / 0, верхний уровень | +| MsgType | 0, BROADCAST | +| MsgBody | 0x0030: команда RTCSETUP=3, параметр=0 | +| DLC | ровно 7 | +| DATA | hour, minute, second, year−2000, month, day, weekday | + +Все поля двоичные, без BCD. Диапазоны: часы 0..23, минуты/секунды 0..59, +год 0..99, месяц 1..12, число согласно календарю, день недели 0..6. +Профиль использует 0=воскресенье, 1=понедельник; библиотека сохраняет переданную +фазу недели и затем продвигает её вместе с календарём. Дата имеет приоритет +для абсолютной метки; несоответствие фазы недели календарю не меняет дату. + +Пример: 2026-10-19 12:34:56, понедельник: + +```text +CAN ID 0x00000030, DLC 7, DATA 0C 22 38 1A 0A 13 01 +``` + +Каждая плата независимо проверяет кадр и календарь, рассчитывает смещение +от своей временной базы и атомарно корректирует её. Повреждённый или чужой +кадр не меняет время и качество предыдущей синхронизации. При отсутствии +новых пакетов часы продолжают локальный отсчёт. Тайм-ауты основаны на независимом +uptime; перевод календаря назад не удлиняет и не сокращает их. + +## Миллисекунды и потребители + +Нулевой миллисекундной долей опорной даты считается момент RX ISR. +Тики, прошедшие до обработки в main, прибавляются к присланному времени. +Исходный кадр содержит только целые секунды: локальное разрешение 1 мс +не означает погрешность синхронизации между платами 1 мс. +Мастер выбирает общую шкалу, например UTC, и момент отправки около секундной +границы. Часовой пояс, leap seconds и компенсация арбитража CAN не передаются. + +Логгер снимает `gt_stamp` с секундами от 2000 года, миллисекундной долей, +признаком синхронизации, номером коррекции и независимым uptime. +64-битная календарная метка не помещается в старое 32-битное поле времени +логгеров; изменение формата архива выполняет конкретное приложение. + +## Верхний уровень: точки подключения + +`gt_parse_ready()` извлекает Type/ID из сообщения платы. +`gt_make_rtc()` проверяет дату и формирует кадр с DLC7; ненулевые миллисекунды +на входе отклоняются, чтобы не терять точность молча. Источник календаря, +CAN-транспорт и обработчик входящего события предоставляет приложение мастера. + +Для TMS320F28335 готовый порт занимает eCAN-A mailbox7/8 и по выбору +CPU Timer2/INT14 либо hook существующего ISR 1 мс. Подробные порядок вызовов, +требования к общему CAN ISR и проверки — в README библиотеки. diff --git a/doc/setcan/protocan/OAP.md b/doc/setcan/protocan/OAP.md index 28918bf..94fed0a 100644 --- a/doc/setcan/protocan/OAP.md +++ b/doc/setcan/protocan/OAP.md @@ -1,56 +1,162 @@ -# Общее адресное пространство +# Общее адресное пространство: GAS и GAS SLOT -Статус: **Stable, данные ведутся в XLSX**
    -Порядок значений: **16-битные регистры, little-endian в CAN payload** +Дата редакции: **2026-10-23**. Номер типа однозначно определяет единицу адресации: -Редактируемый источник реестра: -[`Протокол CAN и ОАП.xlsx`](../Протокол%20CAN%20и%20ОАП.xlsx). +| MsgType | Имя | MsgBody | Payload | +|---|---|---|---| +| `0x3` | GAS | адрес первого 16-битного регистра | 1…4 последовательных регистра, DLC 2/4/6/8 | +| `0x4` | GAS SLOT | адрес слота | Word0 — маска; Word1…Word3 — три значения; DLC 8 | -Просматриваемая большая таблица находится в -[`Протокол CAN и ОАП.html`](../Протокол%20CAN%20и%20ОАП.html) и -[`Протокол CAN и ОАП.md`](../Протокол%20CAN%20и%20ОАП.md). +В обоих случаях запрос чтения — extended data frame с `DLC=0`, `Route=0`. +Ответ имеет `Route=1`, тот же узел и адрес. Прикладного ACK записи нет; +успех применения уставки проверяется прикладным ответом или последующим чтением. +RTR, error frame, стандартный 11-битный ID и нечётные длины не исполняются. -## Назначение +## GAS 0x3: отдельные регистры -ОАП связывает 16-битный адрес регистра с его типом, назначением, доступом и -масштабом. В ProtoCAN используется `MsgType=0x3`, а `MsgBody` содержит адрес -первого регистра. +`MsgBody=RegisterAddress[15:0]`. Адреса `0…65535` (`0x0000…0xFFFF`) +обозначают **65 536 отдельных 16-битных регистров**, логически 128 КиБ на узел. +Это адреса протокола, а не указатели RAM MCU; provider подключает только существующие регионы. -## Обязательные поля реестра +Payload содержит значения с адресов `addr`, `addr+1`, `addr+2`, `addr+3` +в порядке little-endian. Количество равно `DLC/2`, допускаются DLC 2, 4, 6, 8. +Для изменения одной уставки по адресу `0x0001` на `0x1234` передаются +`MsgBody=0x0001`, `DLC=2`, Data=`34 12`; соседние слова не изменяются. +Чтение возвращает до четырёх существующих последовательных регистров, +останавливаясь на первом недоступном адресе или границе `0xFFFF`. +Запись, пересекающая `0xFFFF`, отвергается до изменения данных. -| Поле | Требование | -|---|---| -| AddressHex | `0x0000…0xFFFF`, уникальное значение | -| AddressDec | десятичный эквивалент AddressHex | -| Group | функциональная группа | -| Name | однозначное имя параметра | -| Type | `u16`, `i16`, `u32`, `i32`, `float32`, bitmap или массив | -| Registers | число занятых 16-битных регистров | -| Access | `R`, `W` или `RW` | -| Unit | физическая единица либо `—` | -| Scale | множитель/делитель представления | -| Default | значение после сброса, если применимо | -| Description | семантика, диапазон и особые значения | +Регионы карты, права и значения проверяет `pcan_gas`; callback остаётся +ответственностью приложения. Блочная запись может остановиться на первом отказе provider: +атомарность нескольких регистров не обещается. Связанные `u32/float32` и команды +требуют согласованной прикладной операции. Основной контракт: `c/set-protocol/docs/legacy/GAS.md`. +GAS 167/v1, GAS Logger, GAS_WATCH2, NAND и Altera Logic сохраняют регистровые адреса. +Номер mode задаёт адрес узла; его нельзя автоматически прибавлять к адресу регистра. -## Правила ведения +## GAS SLOT 0x4: маска в Word0 -- Адрес не переиспользуется с другим смыслом после выпуска стабильной версии. -- Многорегистровое значение занимает непрерывный диапазон. -- Порядок 16-битных слов для 32-битного значения фиксируется в строке типа. -- Резервные диапазоны явно отмечаются и не используются без изменения версии. -- Удалённый параметр помечается deprecated, а не исчезает молча. -- Изменение адреса, типа или масштаба отражается в `CHANGELOG.md`. +`MsgBody=SlotAddress[15:0]`. Восемь октетов имеют фиксированное расположение: -## Экспорт +| Октеты | Wire-слово | Назначение | +|---|---|---| +| 0…1 | Word0 | 16-битная маска, little-endian | +| 2…3 | Word1 | первое значение | +| 4…5 | Word2 | второе значение | +| 6…7 | Word3 | третье значение | -Для программной генерации каталог следует экспортировать из XLSX в CSV с -UTF-8 и фиксированными английскими именами колонок. CSV должен проверяться на: +Биты маски 1, 2, 3 соответствуют Word1, Word2, Word3. Бит 0 и биты 4…15 +зарезервированы и должны быть нулевыми. Маска непустая; все допустимые маски: +`0x0002`, `0x0004`, `0x0006`, `0x0008`, `0x000A`, `0x000C`, `0x000E`. +При записи отмеченные значения применяются, неотмеченные позиции игнорируются +и сохраняют текущие значения устройства. Нули не являются специальными маркерами. +При чтении маска ответа отмечает достоверные/доступные значения. -- уникальность адресов; -- пересечение многорегистровых значений; -- допустимые типы и права доступа; -- равенство шестнадцатеричного и десятичного адреса; -- попадание адреса в диапазон `0x0000…0xFFFF`. +Например, изменить только Word2 на `0x1234`: Data=`04 00 00 00 34 12 00 00`. +Word1 и Word3 сохраняются. Полная запись трёх значений использует маску `0x000E`. +Передаются всегда восемь октетов, кроме пустого запроса чтения. Сжатия или сегментации нет. +Provider проверяет все выбранные права и значения до первого изменения, затем применяет +выбранные слова под общей блокировкой. Невыбранные readonly-поля не записываются. +Ядро не выполняет опасное чтение-изменение-запись слота на стороне клиента. -До появления автоматического экспортёра нормативным источником адресов -остаётся XLSX, а HTML/Markdown считаются представлением. +Полное пространство 0x4 содержит **65 536 слотов × 3 значения = 196 608 слов = 384 КиБ**. +Word0 — метаданные кадра, не четвёртый хранимый регистр. Координата значения — +`(SlotAddress, WordIndex)`, где `WordIndex=1…3`. Любой узел поддерживается общими +`pcan_gas_slot_id()` и `pcan_gas_slot_handle_address()`; адрес слота не ограничен страницами PERIPH. +Тип `0x4 MODBUS_COIL` заменён этим сервисом. Единый Modbus использует `0x5`, функцию и количество 1…4 в Body; `0x6/0x7` свободны. +Старое оборудование с Coil 0x4 требует согласованного обновления; автоопределения формата нет. + +## PERIPH: проекция 200 слов на слоты 0x4 + +`mode=0…31`; `DeviceType=1+mode/16`, `DeviceID=mode mod 16`. +`SlotAddress=(mode<<8)|LocalSlot`. Маски не занимают места в карте значений. +На mode сохранены 200 слов, поэтому используются 67 слотов `LocalSlot=0x00…0x42`: +66 полных слотов и два значения последнего. В последнем разрешена только маска +из битов 1/2 (`0x0002`, `0x0004`, `0x0006`); Word3 не существует. +`LocalSlot=0x43…0xFF` — резерв. Узел и старший октет слота должны совпадать. + +Смещение технологического слова: `n=3*LocalSlot+(WordIndex-1)`. +Обратное преобразование: `LocalSlot=n/3`, `WordIndex=1+n mod 3`. +Соседние native-сервисы могут оказаться в одном слоте, поэтому provider проверяет +доступ и наличие каждой отмеченной позиции отдельно. + +| mode | Назначение | DeviceType / DeviceID | Слоты 0x4 | Запрос первого слота | +|---:|---|---|---|---| +| 0 | Резерв | `0x01 / 0x00` | `0x0000…0x0042` | `0x11040000` | +| 1 | Трансформатор 1 | `0x01 / 0x01` | `0x0100…0x0142` | `0x11140100` | +| 2 | Трансформатор 2 | `0x01 / 0x02` | `0x0200…0x0242` | `0x11240200` | +| 3 | Силовой узел 1 | `0x01 / 0x03` | `0x0300…0x0342` | `0x11340300` | +| 4 | Силовой узел 2 | `0x01 / 0x04` | `0x0400…0x0442` | `0x11440400` | +| 5 | УМП1 | `0x01 / 0x05` | `0x0500…0x0542` | `0x11540500` | +| 6 | УМП2 | `0x01 / 0x06` | `0x0600…0x0642` | `0x11640600` | +| 7 | ENG1 | `0x01 / 0x07` | `0x0700…0x0742` | `0x11740700` | +| 8 | Задатчик / пульт | `0x01 / 0x08` | `0x0800…0x0842` | `0x11840800` | +| 9 | Шкаф | `0x01 / 0x09` | `0x0900…0x0942` | `0x11940900` | +| 10 | Общий адрес: служебная роль | `0x01 / 0x0A` | `0x0A00…0x0A42` | `0x11A40A00` | +| 11 | Терминал: служебная роль | `0x01 / 0x0B` | `0x0B00…0x0B42` | `0x11B40B00` | +| 12 | Резерв назначения | `0x01 / 0x0C` | `0x0C00…0x0C42` | `0x11C40C00` | +| 13 | Резерв назначения | `0x01 / 0x0D` | `0x0D00…0x0D42` | `0x11D40D00` | +| 14 | Резерв назначения | `0x01 / 0x0E` | `0x0E00…0x0E42` | `0x11E40E00` | +| 15 | Резерв назначения | `0x01 / 0x0F` | `0x0F00…0x0F42` | `0x11F40F00` | +| 16 | Резерв назначения | `0x02 / 0x00` | `0x1000…0x1042` | `0x12041000` | +| 17 | Резерв назначения | `0x02 / 0x01` | `0x1100…0x1142` | `0x12141100` | +| 18 | Резерв назначения | `0x02 / 0x02` | `0x1200…0x1242` | `0x12241200` | +| 19 | Резерв назначения | `0x02 / 0x03` | `0x1300…0x1342` | `0x12341300` | +| 20 | Резерв назначения | `0x02 / 0x04` | `0x1400…0x1442` | `0x12441400` | +| 21 | Резерв назначения | `0x02 / 0x05` | `0x1500…0x1542` | `0x12541500` | +| 22 | Резерв назначения | `0x02 / 0x06` | `0x1600…0x1642` | `0x12641600` | +| 23 | Резерв назначения | `0x02 / 0x07` | `0x1700…0x1742` | `0x12741700` | +| 24 | Резерв назначения | `0x02 / 0x08` | `0x1800…0x1842` | `0x12841800` | +| 25 | Резерв назначения | `0x02 / 0x09` | `0x1900…0x1942` | `0x12941900` | +| 26 | Резерв назначения | `0x02 / 0x0A` | `0x1A00…0x1A42` | `0x12A41A00` | +| 27 | Резерв назначения | `0x02 / 0x0B` | `0x1B00…0x1B42` | `0x12B41B00` | +| 28 | Резерв назначения | `0x02 / 0x0C` | `0x1C00…0x1C42` | `0x12C41C00` | +| 29 | Резерв назначения | `0x02 / 0x0D` | `0x1D00…0x1D42` | `0x12D41D00` | +| 30 | Резерв назначения | `0x02 / 0x0E` | `0x1E00…0x1E42` | `0x12E41E00` | +| 31 | Резерв назначения | `0x02 / 0x0F` | `0x1F00…0x1F42` | `0x12F41F00` | + +## Назначения mode из periph_28335 + +Источники: `28335_periph/Source/Internal/Include/package.h`, `peripher.c:get_Mode()`, `cntrl_adr.c`. Код платы `Desk` не участвует в вычислении адреса. + +| mode | Назначение | Исходный символ | +|---:|---|---| +| 0 | Резерв | Перемычками текущей платы не задаётся | +| 1 / 2 | Трансформаторные узлы 1 / 2 | `adr_TRN1 / adr_TRN2` | +| 3 / 4 | Силовые узлы 1 / 2 | `adr_POW1 / adr_POW2` | +| 5 / 6 | УМП1 / УМП2 | `adr_LOA1 / adr_LOA2`, `Desk=dsk_LOAD=6` | +| 7 | ENG1 | `adr_ENG1` | +| 8 | Задатчик / пульт | `adr_PULT`; имя «Задатчик» принято в реестре PERIPH | +| 9 | Шкаф | `adr_SHKF` | +| 10 | Общий адрес, служебная роль | `CNTRL_ADDR_UNIVERSAL`, `ADDR_FOR_ALL`; не отдельная плата | +| 11 | Терминал, служебная роль | `ADDR_TERMINAL`; не доказательство отдельной платы | +| 12…31 | Резерв назначения | Перемычки текущей платы дают только 1…16 | + +## Соответствия native-сервисам PERIPH + +| Смещение n | Native-адрес | Назначение | Доступ | +|---|---|---|---| +| 0…127 | `0x0000…0x007F` | технологические данные, уставки, команды | по provider | +| 128…143 | `0x1000…0x100F` | статус регистратора УМП | R | +| 144…155 | `0x1200…0x120B` | паспорт прошивки | R | +| 156…163 | `0x1300…0x1307` | защита УМП | W только `0x1302/0x1303` | +| 164…167 | `0x1000…0x1003` | команды регистратора | по операции | +| 168…199 | нет | резерв | отказ | + +`pcan_gas_slot_native()` принимает WordIndex=1…3; WordIndex=0 является маской +и не переводится в регистр. Наличие сервиса, права и блокировку проверяет приложение. +GAS 0x3 сохраняет собственные адреса подключённых регионов; эта проекция относится только к 0x4. +Архив УМП, окна 120/124 слова и физическая EEPROM сохраняют native-контракты. + +## Реализация и реестр + +- GAS 0x3: `pcan_gas.h/.c`, существующие ABI и клиенты. +- GAS SLOT 0x4: `pcan_gas_slot.h/.c`; тонкие Python `GasSlots` и Android/JNI `GasSlots`. +- Формат определяется MsgType, параметр `gas_profile` не используется. +- C28x хранит wire-октеты в `uint_least8_t`; DLC измеряется октетами линии. +- Перенос в другую единицу адресации или fallback после отказа запрещены. + +XLSX «Интерфейс протокола» содержит оба типа; «Общее адресное пространство» — +проекцию 0x4 и native-адреса её значений; «ОАП legacy» сохраняет исходный словный реестр 0x3. +Уникальный ключ реестра включает узел, MsgType, адрес и для 0x4 WordIndex. +Права, тип, единица, масштаб и порядок слов u32/float32 задаются явно. +Эталоны: `examples/gas-slot-vectors.json`; регистровые проверки — `test_gas_register.c`. diff --git a/doc/setcan/protocan/PROTOCOL.md b/doc/setcan/protocan/PROTOCOL.md index aea4627..b3c0273 100644 --- a/doc/setcan/protocan/PROTOCOL.md +++ b/doc/setcan/protocan/PROTOCOL.md @@ -1,7 +1,7 @@ # ProtoCAN — базовый протокол Статус: **Stable с зарезервированным загрузочным расширением**
    -Версия: **1.0**
    +Версия: **2.2: единый Modbus 0x5, функции и количество 1…4**
    Порядок байтов payload: **little-endian**, если явно не указано иное ## Назначение @@ -59,11 +59,10 @@ can_id = | `0x0` | `BROADCAST` | ПМ → все | зависит от команды | stable | | `0x1` | `DISCRETE` | оба | 0…8 | stable | | `0x2` | `ANALOG` | оба | 0…8 | stable | -| `0x3` | `GAS` | оба | 0/2/4/6/8 | stable | -| `0x4` | `MODBUS_COIL` | оба | 0…8 | stable | -| `0x5` | `MODBUS_DISCRETE` | оба | 0…8 | stable | -| `0x6` | `MODBUS_HOLDING` | оба | 0…8 | stable | -| `0x7` | `MODBUS_INPUT` | оба | 0…8 | stable | +| `0x3` | `GAS` | оба | 0/2/4/6/8 | регистры 0…65535 | +| `0x4` | `GAS_SLOT` | оба | 0/8 | Word0 — маска, Word1…Word3 — значения | +| `0x5` | `MODBUS` | оба | 0/1/2/4/6/8 | функции 1…4, количество 1…4 | +| `0x6…0x7` | резерв | — | — | свободны | | `0x8` | `ERROR` | прибор → ПМ | 0 | stable | | `0x9` | `BOOT_CONTROL` | ПМ → прибор | 0/8 | draft | | `0xA` | `BOOT_DATA_A` | ПМ → прибор | 8 | draft | @@ -81,15 +80,51 @@ can_id = |---|---| | broadcast | команда `[15:4]`, параметр `[3:0]` | | discrete/analog | подтип `[15:12]`, значение/адрес `[11:0]` | -| Modbus | начальный адрес `[15:4]`, количество `[3:0]` | -| GAS | адрес первого 16-битного регистра `[15:0]` | +| Modbus 0x5 | адрес `[15:4]`, функция − 1 `[3:2]`, количество − 1 `[1:0]` | +| GAS 0x3 | адрес первого 16-битного регистра `[15:0]` | +| GAS SLOT 0x4 | адрес слота `[15:0]`; маска — в Word0 payload, значения — Word1…Word3 | | error | дополнительная информация `[15:8]`, код `[7:0]` | | settings | номер сборки `[15:8]`, позиция `[7:0]` | | boot control/status | `SessionID[15:8]`, команда `[7:0]` | | boot data | `BlockIndex[15:0]` | +Контракт обоих GAS: [OAP.md](OAP.md). Тип 0x3 адресует отдельные слова; тип 0x4 имеет маску битов 1…3 в Word0 и три значения. Для PERIPH 0x4 используются 67 слотов `0xMM00…0xMM42`, последний содержит два значения. Старый Coil 0x4 заменён; формат определяется MsgType. + +## Единый Modbus `0x5` + +Все четыре банка используют один `MsgType=0x5`. Коды `0x6` и `0x7` свободны. +Начальный адрес занимает `[15:4]` и лежит в диапазоне `0x000…0xFFF`. +Биты `[3:2]` содержат `Function − 1`, биты `[1:0]` — `RegCount − 1`. +Физические значения функции и количества: **1…4**. Всё окно должно помещаться +в 4096 адресов: `StrAdr + RegCount ≤ 4096`. + +| Функция | Банк | Элемент | DLC данных | +|---:|---|---|---| +| 1 | Coil | дискретный выход | 1 байт для 1…4 битов | +| 2 | Discrete | дискретный вход | 1 байт для 1…4 битов | +| 3 | Holding | 16-битный регистр | `2 × RegCount`, 2/4/6/8 байт | +| 4 | Input | 16-битный регистр | `2 × RegCount`, 2/4/6/8 байт | + +Это селектор банка в ProtoCAN по нумерации функций Modbus, без RTU-заголовка +и CRC. Сохраняется правило ProtoCAN: `Route=0, DLC=0` читает окно; +непустой payload записывает Coil/Holding, Discrete/Input доступны только +для чтения. Ответ имеет `Route=1`, сохраняет `MsgBody` и содержит значения +либо эхо успешной записи. RTR запрещён. Биты упакованы начиная с младшего, +старшие неиспользуемые биты нулевые. Регистры передаются little-endian. + +Пример: адрес `0x123`, функция 3, четыре регистра дают +`MsgBody = (0x123 << 4) | ((3 − 1) << 2) | (4 − 1) = 0x123B`. + +Изменение wire-формата несовместимо с прежними отдельными типами +`0x5/0x6/0x7`: узлы и клиенты обновляются согласованно. Тип GAS SLOT `0x4` +сохраняет своё назначение. + ## Общие правила обмена +Профиль синхронизации часов и сообщения платы о завершении инициализации: +[GLOBAL_TIME.md](GLOBAL_TIME.md). Он сохраняет штатный BROADCAST RTCSETUP +и определяет общий пакет готовности поверх DISCRETE/FLAGS. + - Многобайтовые значения в `DATA` передаются little-endian. - Узел игнорирует адресованные кадры с чужим `DeviceType/DeviceID`. - Прибор принимает команды ПМ с `Route=0`; ПМ принимает ответы с `Route=1`. diff --git a/doc/setcan/protocan/README.md b/doc/setcan/protocan/README.md index 841978e..b696bdb 100644 --- a/doc/setcan/protocan/README.md +++ b/doc/setcan/protocan/README.md @@ -1,8 +1,8 @@ # Документация ProtoCAN Статус комплекта: **Draft**
    -Версия комплекта: **1.0**
    -Дата редакции: **2026-08-29**
    +Версия комплекта: **2.1**
    +Дата редакции: **2026-10-23**
    Транспорт: **Classic CAN 2.0B, Extended ID, DLC 0…8** Этот каталог разделяет нормативное описание протокола, загрузчик и реестр @@ -41,3 +41,7 @@ Все документы и тестовые векторы включаются в единый файл `doc/setcan/index.html`. Скрипт не изменяет исходные Markdown/XLSX и пригоден для запуска в CI. + +## GAS: регистры 0x3 и слоты 0x4 + +[Адресация GAS](OAP.md): `0x3` — отдельные 16-битные регистры `0…65535`, запись 1…4 слов. `0x4` — слот с Word0-маской и тремя значениями; PERIPH сохраняет 200 слов в 67 слотах `0xMM00…0xMM42`. Формат определяется MsgType, без настройки профиля. diff --git a/doc/setcan/protocan/examples/gas-slot-vectors.json b/doc/setcan/protocan/examples/gas-slot-vectors.json new file mode 100644 index 0000000..3d11862 --- /dev/null +++ b/doc/setcan/protocan/examples/gas-slot-vectors.json @@ -0,0 +1,55 @@ +{ + "profile": "GAS SLOT 0x4 / Word0 mask", + "words": [ + 14, + 4660, + 43981, + 65535 + ], + "payload_hex": "0E003412CDABFFFF", + "vectors": [ + { + "mode": 5, + "local_slot": 0, + "request_id": "0x11540500", + "response_id": "0x19540500" + }, + { + "mode": 6, + "local_slot": 0, + "request_id": "0x11640600", + "response_id": "0x19640600" + }, + { + "mode": 7, + "local_slot": 0, + "request_id": "0x11740700", + "response_id": "0x19740700" + }, + { + "mode": 8, + "local_slot": 0, + "request_id": "0x11840800", + "response_id": "0x19840800" + }, + { + "mode": 16, + "local_slot": 0, + "request_id": "0x12041000", + "response_id": "0x1A041000" + }, + { + "mode": 31, + "local_slot": 66, + "request_id": "0x12F41F42", + "response_id": "0x1AF41F42", + "words": [ + 6, + 4660, + 43981, + 0 + ], + "payload_hex": "06003412CDAB0000" + } + ] +} diff --git a/doc/setcan/Протокол CAN и ОАП.html b/doc/setcan/Протокол CAN и ОАП.html index e4c7fbc..44bde86 100644 --- a/doc/setcan/Протокол CAN и ОАП.html +++ b/doc/setcan/Протокол CAN и ОАП.html @@ -1,32 +1,259 @@ - - - - - -Протокол CAN и ОАП - - -

    Протокол CAN и ОАП

    +ProtoCAN — GAS 0x3 и GAS SLOT 0x4

    Протокол CAN и ОАП

    Таблицы перенесены из Протокол CAN и ОАП.xlsx. Цвета, объединённые ячейки и структура листов сохранены средствами HTML внутри Markdown.

    +

    Адреса PERIPH обновлены по листу «Интерфейс протокола», A44:F79: +Type 0x01 содержит PERIPH 0–15, Type 0x02 — PERIPH 16–31; +Device ID равен младшим четырём битам номера PERIPH. +УМП1 — 0x01/0x05, УМП2 — 0x01/0x06, задатчик — 0x01/0x08. +Назначения остальных mode уточнены по periph_28335: 1/2 — трансформаторы, 3/4 — силовые узлы, 7 — ENG1, 9 — шкаф; 10/11 — служебные роли. Общий Boot-адрес 0x03/0x07 отменён. +Полный реестр назначений применяется и к загрузчику, и к GUI.

    -

    +

    +

    +

    GAS: регистры 0x3 и масочные слоты 0x4

    +

    Нормативная спецификация: OAP.md. GAS 0x3: адрес первого регистра 0…65535, DLC 0/2/4/6/8. GAS SLOT 0x4: Word0 — маска битов 1…3, Word1…Word3 — три значения, DLC 0/8. PERIPH сохраняет 200 значений в 67 слотах; последний содержит два. Словный реестр ниже сохраняет адреса GAS 0x3.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    modeНазначениеType / IDСлоты 0x4CAN запрос
    0Резерв0x01 / 0x000x0000…0x00420x11040000
    1Трансформатор 10x01 / 0x010x0100…0x01420x11140100
    2Трансформатор 20x01 / 0x020x0200…0x02420x11240200
    3Силовой узел 10x01 / 0x030x0300…0x03420x11340300
    4Силовой узел 20x01 / 0x040x0400…0x04420x11440400
    5УМП10x01 / 0x050x0500…0x05420x11540500
    6УМП20x01 / 0x060x0600…0x06420x11640600
    7ENG10x01 / 0x070x0700…0x07420x11740700
    8Задатчик / пульт0x01 / 0x080x0800…0x08420x11840800
    9Шкаф0x01 / 0x090x0900…0x09420x11940900
    10Общий адрес: служебная роль0x01 / 0x0A0x0A00…0x0A420x11A40A00
    11Терминал: служебная роль0x01 / 0x0B0x0B00…0x0B420x11B40B00
    12Резерв назначения0x01 / 0x0C0x0C00…0x0C420x11C40C00
    13Резерв назначения0x01 / 0x0D0x0D00…0x0D420x11D40D00
    14Резерв назначения0x01 / 0x0E0x0E00…0x0E420x11E40E00
    15Резерв назначения0x01 / 0x0F0x0F00…0x0F420x11F40F00
    16Резерв назначения0x02 / 0x000x1000…0x10420x12041000
    17Резерв назначения0x02 / 0x010x1100…0x11420x12141100
    18Резерв назначения0x02 / 0x020x1200…0x12420x12241200
    19Резерв назначения0x02 / 0x030x1300…0x13420x12341300
    20Резерв назначения0x02 / 0x040x1400…0x14420x12441400
    21Резерв назначения0x02 / 0x050x1500…0x15420x12541500
    22Резерв назначения0x02 / 0x060x1600…0x16420x12641600
    23Резерв назначения0x02 / 0x070x1700…0x17420x12741700
    24Резерв назначения0x02 / 0x080x1800…0x18420x12841800
    25Резерв назначения0x02 / 0x090x1900…0x19420x12941900
    26Резерв назначения0x02 / 0x0A0x1A00…0x1A420x12A41A00
    27Резерв назначения0x02 / 0x0B0x1B00…0x1B420x12B41B00
    28Резерв назначения0x02 / 0x0C0x1C00…0x1C420x12C41C00
    29Резерв назначения0x02 / 0x0D0x1D00…0x1D420x12D41D00
    30Резерв назначения0x02 / 0x0E0x1E00…0x1E420x12E41E00
    31Резерв назначения0x02 / 0x0F0x1F00…0x1F420x12F41F00

    Прошивка приборов по CAN

    -

    Ниже зафиксирован формат планируемого загрузочного сервиса. Значения -MsgType=0x9..0xD зарезервированы в протоколе, но обработчики загрузчика в -текущих protocan.c/.h ещё не реализованы.

    +

    Загрузчик MsgType=0x9…0xD реализован в c/protocan-boot. Актуальные команды, A/B и single-slot: BOOTLOADER.md. Ниже сохранена историческая таблица; при расхождении применяется актуальная спецификация.

    Загрузчик работает поверх classic CAN 2.0B с Extended ID. Управляющий модуль использует Route=0, прибор отвечает с Route=1. Команды стирания и записи всегда должны быть адресованы конкретной паре DeviceType/DeviceID; @@ -704,8 +931,8 @@ DATA[4..7] RunningCRC32, uint32 little-endian 0x1. Стандартный 0х1. Устройство -0x1 -0x0 - 0xF устройств +0x01 PERIPH +0x0–0xF; PERIPH 0–15
    0x5: УМП1; 0x6: УМП2; 0x8: Задатчик 0x1. Запрос на вкл/выкл Выбор "страницы" из 64 устройств (Битовые флаги в Data)   @@ -716,8 +943,8 @@ DATA[4..7] RunningCRC32, uint32 little-endian     -0x2 -0x0 - 0xF устройств +0x02 PERIPH +0x0–0xF; PERIPH 16–31 0x2. Рестарт устройств Выбор "страницы" из 64 устройств (Битовые флаги в Data)   @@ -955,14 +1182,14 @@ DATA[4..7] RunningCRC32, uint32 little-endian     0x3. Общее адресное пространство -Адрес регистра (Стартовый адрес, если DLC COUNT > 2) (0, 0x0000 - 65535, 0xFFFF) +GAS: адрес первого 16-битного регистра 0x0000…0xFFFF; до четырёх последовательных значений.   0/2/4/6/8   -Четвёртый регистр -Третий регистр -Второй регистр -Первый регистр +Регистр addr+3 +Регистр addr+2 +Регистр addr+1 +Регистр addr+0   @@ -971,13 +1198,28 @@ DATA[4..7] RunningCRC32, uint32 little-endian       -0x4. Modbus Coil +0x4. GAS SLOT +Адрес слота 0x0000…0xFFFF +  +0/8 +  +Word3 | Word2 | Word1 | Word0: маска битов 1…3 + + +  +  +  +  +  +  +0x5. Modbus Стартовый адрес регистра (0x0 - 0xFFF) -Кол-во регистров (0-15) +Функция (1–4) +Кол-во регистров (1–4)   -  +0/1/2/4/6/8   -NULL +FC1/2: биты; FC3/4: слова LE   @@ -986,13 +1228,12 @@ DATA[4..7] RunningCRC32, uint32 little-endian       -0x5. Modbus Discrete -Стартовый адрес регистра (0x0 - 0xFFF) -Кол-во регистров (0-15) +0x6. Резерв +        -NULL +    @@ -1001,28 +1242,12 @@ DATA[4..7] RunningCRC32, uint32 little-endian       -0x6. Modbus Holding -Стартовый адрес регистра (0x0 - 0xFFF) -Кол-во регистров (0-15( +0x7. Резерв +        -NULL - - -  -  -  -  -  -  -0x7. Modbus Input -Стартовый адрес регистра (0x0 - 0xFFF) -Кол-во регистров (0-15) -  -  -  -NULL +    @@ -1421,8 +1646,8 @@ DATA[4..7] RunningCRC32, uint32 little-endian

-

-

Лист «Общее адресное пространство»

+

+

Исторический лист «ОАП legacy»: адреса регистров

Таблица прокручивается по горизонтали; длинный лист ограничен по высоте окна.

@@ -13399,6 +13624,4 @@ DATA[4..7] RunningCRC32, uint32 little-endian
- - - + \ No newline at end of file diff --git a/doc/setcan/Протокол CAN и ОАП.md b/doc/setcan/Протокол CAN и ОАП.md index 171ec3b..7048cfe 100644 --- a/doc/setcan/Протокол CAN и ОАП.md +++ b/doc/setcan/Протокол CAN и ОАП.md @@ -2,16 +2,61 @@ Таблицы перенесены из `Протокол CAN и ОАП.xlsx`. Цвета, объединённые ячейки и структура листов сохранены средствами HTML внутри Markdown. +Адреса PERIPH обновлены по листу «Интерфейс протокола», A44:F79: +Type `0x01` содержит PERIPH 0–15, Type `0x02` — PERIPH 16–31; +Device ID равен младшим четырём битам номера PERIPH. +УМП1 — `0x01/0x05`, УМП2 — `0x01/0x06`, задатчик — `0x01/0x08`. +Назначения остальных mode уточнены по periph_28335: 1/2 — трансформаторы, 3/4 — силовые узлы, 7 — ENG1, 9 — шкаф; 10/11 — служебные роли. Общий Boot-адрес `0x03/0x07` отменён. +Полный [реестр назначений](DEVICE_REGISTRY.md) применяется и к загрузчику, и к GUI. + - [Интерфейс протокола](#sheet-protocol) - [Общее адресное пространство](#sheet-oap) - [Прошивка приборов по CAN](#can-firmware) + +## GAS: регистры 0x3 и масочные слоты 0x4 + +Нормативная спецификация: [OAP.md](protocan/OAP.md). GAS 0x3: адрес первого регистра 0…65535, DLC 0/2/4/6/8. GAS SLOT 0x4: Word0 — маска битов 1…3, Word1…Word3 — три значения, DLC 0/8. PERIPH сохраняет 200 значений в 67 слотах; последний содержит два. Словный реестр ниже сохраняет адреса GAS 0x3. + +| mode | Назначение | Type / ID | Слоты 0x4 | CAN запрос | +|---:|---|---|---|---| +| 0 | Резерв | `0x01 / 0x00` | `0x0000…0x0042` | `0x11040000` | +| 1 | Трансформатор 1 | `0x01 / 0x01` | `0x0100…0x0142` | `0x11140100` | +| 2 | Трансформатор 2 | `0x01 / 0x02` | `0x0200…0x0242` | `0x11240200` | +| 3 | Силовой узел 1 | `0x01 / 0x03` | `0x0300…0x0342` | `0x11340300` | +| 4 | Силовой узел 2 | `0x01 / 0x04` | `0x0400…0x0442` | `0x11440400` | +| 5 | УМП1 | `0x01 / 0x05` | `0x0500…0x0542` | `0x11540500` | +| 6 | УМП2 | `0x01 / 0x06` | `0x0600…0x0642` | `0x11640600` | +| 7 | ENG1 | `0x01 / 0x07` | `0x0700…0x0742` | `0x11740700` | +| 8 | Задатчик / пульт | `0x01 / 0x08` | `0x0800…0x0842` | `0x11840800` | +| 9 | Шкаф | `0x01 / 0x09` | `0x0900…0x0942` | `0x11940900` | +| 10 | Общий адрес: служебная роль | `0x01 / 0x0A` | `0x0A00…0x0A42` | `0x11A40A00` | +| 11 | Терминал: служебная роль | `0x01 / 0x0B` | `0x0B00…0x0B42` | `0x11B40B00` | +| 12 | Резерв назначения | `0x01 / 0x0C` | `0x0C00…0x0C42` | `0x11C40C00` | +| 13 | Резерв назначения | `0x01 / 0x0D` | `0x0D00…0x0D42` | `0x11D40D00` | +| 14 | Резерв назначения | `0x01 / 0x0E` | `0x0E00…0x0E42` | `0x11E40E00` | +| 15 | Резерв назначения | `0x01 / 0x0F` | `0x0F00…0x0F42` | `0x11F40F00` | +| 16 | Резерв назначения | `0x02 / 0x00` | `0x1000…0x1042` | `0x12041000` | +| 17 | Резерв назначения | `0x02 / 0x01` | `0x1100…0x1142` | `0x12141100` | +| 18 | Резерв назначения | `0x02 / 0x02` | `0x1200…0x1242` | `0x12241200` | +| 19 | Резерв назначения | `0x02 / 0x03` | `0x1300…0x1342` | `0x12341300` | +| 20 | Резерв назначения | `0x02 / 0x04` | `0x1400…0x1442` | `0x12441400` | +| 21 | Резерв назначения | `0x02 / 0x05` | `0x1500…0x1542` | `0x12541500` | +| 22 | Резерв назначения | `0x02 / 0x06` | `0x1600…0x1642` | `0x12641600` | +| 23 | Резерв назначения | `0x02 / 0x07` | `0x1700…0x1742` | `0x12741700` | +| 24 | Резерв назначения | `0x02 / 0x08` | `0x1800…0x1842` | `0x12841800` | +| 25 | Резерв назначения | `0x02 / 0x09` | `0x1900…0x1942` | `0x12941900` | +| 26 | Резерв назначения | `0x02 / 0x0A` | `0x1A00…0x1A42` | `0x12A41A00` | +| 27 | Резерв назначения | `0x02 / 0x0B` | `0x1B00…0x1B42` | `0x12B41B00` | +| 28 | Резерв назначения | `0x02 / 0x0C` | `0x1C00…0x1C42` | `0x12C41C00` | +| 29 | Резерв назначения | `0x02 / 0x0D` | `0x1D00…0x1D42` | `0x12D41D00` | +| 30 | Резерв назначения | `0x02 / 0x0E` | `0x1E00…0x1E42` | `0x12E41E00` | +| 31 | Резерв назначения | `0x02 / 0x0F` | `0x1F00…0x1F42` | `0x12F41F00` | + ## Прошивка приборов по CAN -Ниже зафиксирован формат планируемого загрузочного сервиса. Значения -`MsgType=0x9..0xD` зарезервированы в протоколе, но обработчики загрузчика в -текущих `protocan.c/.h` ещё не реализованы. +Загрузчик `MsgType=0x9…0xD` реализован в `c/protocan-boot`. Актуальные команды, A/B и single-slot: [BOOTLOADER.md](protocan/BOOTLOADER.md). Ниже сохранена историческая таблица; при расхождении применяется актуальная спецификация. Загрузчик работает поверх classic CAN 2.0B с Extended ID. Управляющий модуль использует `Route=0`, прибор отвечает с `Route=1`. Команды стирания и записи @@ -576,8 +621,8 @@ CRC32 обнаруживает случайное повреждение, но 0x1. Стандартный 0х1. Устройство -0x1 -0x0 - 0xF устройств +0x01 PERIPH +0x0–0xF; PERIPH 0–15
0x5: УМП1; 0x6: УМП2; 0x8: Задатчик 0x1. Запрос на вкл/выкл Выбор "страницы" из 64 устройств (Битовые флаги в Data)   @@ -588,8 +633,8 @@ CRC32 обнаруживает случайное повреждение, но     -0x2 -0x0 - 0xF устройств +0x02 PERIPH +0x0–0xF; PERIPH 16–31 0x2. Рестарт устройств Выбор "страницы" из 64 устройств (Битовые флаги в Data)   @@ -597,11 +642,11 @@ CRC32 обнаруживает случайное повреждение, но   64 битовых адресса - +     0x3 -0x0 - 0xF устройств
0x7: F28335-M95M02
ProductType: 0x2833 +0x0 - 0xF устройств 0x3. Установка времени     @@ -827,14 +872,14 @@ CRC32 обнаруживает случайное повреждение, но     0x3. Общее адресное пространство -Адрес регистра (Стартовый адрес, если DLC COUNT > 2) (0, 0x0000 - 65535, 0xFFFF) +GAS: адрес первого 16-битного регистра 0x0000…0xFFFF; до четырёх последовательных значений.   0/2/4/6/8   -Четвёртый регистр -Третий регистр -Второй регистр -Первый регистр +Регистр addr+3 +Регистр addr+2 +Регистр addr+1 +Регистр addr+0   @@ -843,13 +888,28 @@ CRC32 обнаруживает случайное повреждение, но       -0x4. Modbus Coil +0x4. GAS SLOT +Адрес слота 0x0000…0xFFFF +  +0/8 +  +Word3 | Word2 | Word1 | Word0: маска битов 1…3 + + +  +  +  +  +  +  +0x5. Modbus Стартовый адрес регистра (0x0 - 0xFFF) -Кол-во регистров (0-15) +Функция (1–4) +Кол-во регистров (1–4)   -  +0/1/2/4/6/8   -NULL +FC1/2: биты; FC3/4: слова LE   @@ -858,13 +918,12 @@ CRC32 обнаруживает случайное повреждение, но       -0x5. Modbus Discrete -Стартовый адрес регистра (0x0 - 0xFFF) -Кол-во регистров (0-15) +0x6. Резерв +        -NULL +    @@ -873,28 +932,12 @@ CRC32 обнаруживает случайное повреждение, но       -0x6. Modbus Holding -Стартовый адрес регистра (0x0 - 0xFFF) -Кол-во регистров (0-15( +0x7. Резерв +        -NULL - - -  -  -  -  -  -  -0x7. Modbus Input -Стартовый адрес регистра (0x0 - 0xFFF) -Кол-во регистров (0-15) -  -  -  -NULL +    @@ -1294,8 +1337,8 @@ CRC32 обнаруживает случайное повреждение, но - -## Лист «Общее адресное пространство» + +## Исторический лист «ОАП legacy»: адреса регистров

Таблица прокручивается по горизонтали; длинный лист ограничен по высоте окна.

diff --git a/doc/setcan/Протокол CAN и ОАП.xlsx b/doc/setcan/Протокол CAN и ОАП.xlsx index 0ce7a42..12b53ef 100644 Binary files a/doc/setcan/Протокол CAN и ОАП.xlsx and b/doc/setcan/Протокол CAN и ОАП.xlsx differ diff --git a/firmware-version-porting.md b/firmware-version-porting.md index ece253c..9844ffb 100644 --- a/firmware-version-porting.md +++ b/firmware-version-porting.md @@ -4,6 +4,7 @@ - [Пошаговое подключение модуля версии](c/firmware-info/PORTING.md). - [BAT-файлы precompile и postcompile для CCS и Keil](tools/firmware-build/README.md). +- [Шаблон контроля версий ПЛИС: Xilinx ISE, Vivado и Altera/Intel Quartus](tools/firmware-build/fpga/README.md). - [Настройка подготовки и публикации образов](tools/firmware-publish/PORTING.md). В режиме CCS `--identity` precompile создаёт заголовок версии и Git-метаданные, а postcompile преобразует OUT в SCI8 HEX/BIN и создаёт manifest и SHA-256. В прежнем режиме postcompile запускает SETGUI preflight готового образа. Для каждого проекта задаются явные пути; алгоритмы остаются в templates. diff --git a/python/README.md b/python/README.md index 4e2b50d..30ba13f 100644 --- a/python/README.md +++ b/python/README.md @@ -24,6 +24,13 @@ Saleae SDK подключается при обращении к устройс в приложении. Общая панель обработки графиков размещена в `qt_ports.plot_processing`: [контракт, подключение нового графика и примеры](../c/set-protocol/docs/PLOT_PROCESSING.md). +Конструкторы CAN-адаптера, CAN DevBoard и RS485 DevBoard используют общий +компонент `set_devices.qt_ports.can_frame_builder.CanFrameFields`. Он задаёт +одинаковые поля и исходный режим «Обычный CAN — ID / DLC / Data», сохраняет +альтернативный режим SETCAN и сообщает об изменениях сигналом `changed`. +`frame_values()` возвращает проверенные ID, IDE, Data и необязательный Body; +упаковка конкретного транспорта и отправка остаются у приложения. + Пути к нативным библиотекам задаёт потребитель перед импортом: `SETPROTOCOL_LIBRARY`, при необходимости `ALTERA_LOGIC_LIBRARY`, `CANDLE_LIBRARY`. Порты не ищут DLL в каталогах SETGUI. C99-ядро собирается из `c/set-protocol`, diff --git a/python/examples/console_examples.py b/python/examples/console_examples.py new file mode 100644 index 0000000..1453266 --- /dev/null +++ b/python/examples/console_examples.py @@ -0,0 +1,46 @@ +"""Три автономных примера общей консоли templates без подключения к аппаратуре.""" # Примеры показывают служебный текст, CAN и двоичный RS485 на одном компоненте. +import argparse # Ключ --kind выбирает один пример для отдельного запуска. +import time # Время в модели кадра соответствует обычному источнику пакетов приложения. +from set_devices.can485_board import BoardFrame # Штатная модель строит RS485-пакет с настоящим CRC. +from set_devices.can_monitor import decode_protocol # CAN расшифровывается действующим декодером templates. +from set_devices.can_transport import build_frame # Транспортный кадр не собирается вручную в UI. +from set_devices.qt_ports.console import ConsoleView # Все примеры используют ту же консоль, что SETGUI. +try: # Выбираем доступную версию Qt без зависимости от приложения SETGUI. + from PySide6.QtWidgets import QApplication, QTabWidget # Вкладки позволяют сравнить три независимых журнала. +except ImportError: # Сохраняем совместимость примера с портом Qt 5. + from PySide2.QtWidgets import QApplication, QTabWidget # Интерфейс запуска одинаков для обеих версий Qt. + + +def create_examples(): # Фабрика доступна также тесту и генератору снимков интерфейса. + service = ConsoleView(limit=4000) # Первый журнал показывает служебные ответы и команды платы. + service.append_message(">>> V", direction="TX", color="#8fd18f") # Метка отправки демонстрирует независимый фильтр TX. + service.append_message("#OK driver started", direction="RX", color="#6fa8dc") # Ответ устройства показывает цвет и фильтр RX. + service.append_message("#ERR transmit failed (no ack / bus busy)", color="#ff7b7b") # Ошибка остаётся видна независимо от фильтров направления. + can = ConsoleView(limit=4000, payloads=True) # Второй пример добавляет переключение представления настоящих байтов CAN. + frame = build_frame(0x701, b"\x05", ide=False, rtr=False) # ID 0x701 и байт 05 задают heartbeat CANopen узла 1 в Operational. + decoded = decode_protocol(frame, "deif") # Подпись события берётся из штатного протокольного декодера. + can.append_message("RX CAN 0x701 · " + decoded.summary, direction="RX", payload=b"\x05") # Исходный payload позволяет сравнить режимы HEX и ASCII. + rs485 = ConsoleView(limit=4000, payloads=True) # Третий пример показывает транспортный пакет платы отдельно от прикладного CAN. + packet = BoardFrame(time.time(), False, 0x701, False, 1, b"\x05", "RS485").rs485_packet() # Пакет AA55 и CRC8 формируются кодеком templates. + rs485.append_message("RX RS485 · пакет CAN485", direction="RX", payload=packet) # Консоль отображает байты, не повторяя алгоритм разбора пакета. + for console in (can, rs485): # Двоичные примеры сразу демонстрируют одновременно байты и печатное представление. + console.display.setCurrentText("HEX + ASCII") # Пользователь может вернуться к исходной подписи или выбрать один формат. + return (("Служебная консоль", service), ("CAN", can), ("RS485", rs485)) # Каждый журнал владеет своей историей и настройками просмотра. + + +def main(): # Точка входа запускается обычным Python с установленным Qt-портом templates. + parser = argparse.ArgumentParser(description=__doc__) # Справка объясняет назначение примеров без отдельного приложения. + parser.add_argument("--kind", choices=("all", "service", "can", "rs485"), default="all") # Один пример каждого источника доступен отдельной командой. + args = parser.parse_args() # Пользователь выбирает источник до создания окна. + app = QApplication.instance() or QApplication([]) # Одно приложение Qt обслуживает все примеры. + window = QTabWidget() # Общий просмотр не связывает состояния независимых консолей. + for key, (title, console) in zip(("service", "can", "rs485"), create_examples()): # Стабильные ключи соответствуют значениям --kind. + if args.kind in ("all", key): window.addTab(console.panel, title) # Выбранные примеры добавляются с общей панелью инструментов. + window.setWindowTitle("Примеры консоли templates") # Заголовок явно отличает демонстрацию от подключения к плате. + window.resize(1100, 480) # Начальный размер в логических пикселях позволяет видеть все инструменты. + window.show() # Окно появляется только при прямом запуске примера. + return app.exec() # Цикл Qt обрабатывает поиск, паузу, экспорт и изменение масштаба. + + +if __name__ == "__main__": # Импорт фабрики в тестах не должен открывать окно или запускать цикл событий. + raise SystemExit(main()) # Код завершения Qt возвращается вызывающему процессу. diff --git a/python/logic_analyzer/decoders/set_can.py b/python/logic_analyzer/decoders/set_can.py index f0d0867..9e8e51e 100644 --- a/python/logic_analyzer/decoders/set_can.py +++ b/python/logic_analyzer/decoders/set_can.py @@ -6,8 +6,8 @@ from .set_uart import number, parse_frame TYPES = {0: 'BROADCAST', 1: 'DISCRETE', 2: 'ANALOG', 3: 'GAS', - 4: 'MODBUS_COIL', 5: 'MODBUS_DISCRETE', 6: 'MODBUS_HOLDING', - 7: 'MODBUS_INPUT', 8: 'ERROR', 9: 'BOOT_CONTROL', 10: 'BOOT_DATA_A', + 4: 'GAS_SLOT', 5: 'MODBUS', # Единый Modbus занимает 0x5, прежние коды 0x6 и 0x7 освобождены. + 8: 'ERROR', 9: 'BOOT_CONTROL', 10: 'BOOT_DATA_A', # Остальные сервисы сохраняют числовые коды. 11: 'BOOT_DATA_B', 12: 'BOOT_STATUS', 13: 'BOOT_DISCOVERY', 15: 'PULSE'} BOOT = dict(enumerate(('IDENTIFY ENTER_BOOT BEGIN_IMAGE BEGIN_COMPAT ERASE VERIFY ' 'COMMIT CONFIRM REBOOT ABORT QUERY_PROGRESS').split(), 1)) @@ -42,8 +42,21 @@ def legacy(ident, data, profile='protocan'): raise ValueError('Invalid GAS register payload/range') result['registers'] = [(body + i//2, number(data[i:i+2])) for i in range(0, len(data), 2)] text += ' ' + ('READ' if not data else ' '.join('R%04X=%04X' % pair for pair in result['registers'])) - elif 4 <= msg <= 7: - text += ' address=%03X count=%d' % (body >> 4, body & 15) + elif msg == 4: # Слотный GAS определяется номером типа, без эвристики по первым байтам данных. + from protocan.gas_slots import GasSlots # Проверку Word0-маски, длины и порядка октетов выполняет единственный C-кодек. + values = GasSlots().decode_address(ident, data) # Не ограничиваем анализатор адресами семейства PERIPH. + result['slot'] = body # Адрес слота отделён от списка обычных регистров GAS 0x3. + result['mask'] = values[0] if values else None # Пустой запрос чтения не содержит фиктивной маски. + result['slot_words'] = [(index, values[index]) for index in range(1, 4) if values and values[0] & (1 << index)] # Публикуем только выбранные или достоверные значения, без служебного Word0. + text += ' slot=%04X' % body + (' READ' if not values else ' mask=%04X' % values[0]) # В логе ясно различаются адрес и маска частичной записи. + elif msg == 5: # Modbus использует один тип сообщения и поле функции внутри Body. + from protocan.protocan import decode # Один подробный декодер проверяет длину, диапазон адресов и битовые маски. + decoded = decode(ident, bytes(data)) # Передаём исходный payload без повторной реализации протокольных проверок. + if decoded.warnings: # Некорректные значения должны быть видны вызывающему анализатору. + raise ValueError('; '.join(decoded.warnings)) # Сохраняем подробные сообщения общей реализации. + result['address'], result['count'], result['function'] = body >> 4, (body & 3) + 1, ((body >> 2) & 3) + 1 # Внешний результат содержит физические значения полей 1…4. + result['registers'] = decoded.registers # Для Coil/Discrete публикуются отдельные биты, для Holding/Input — 16-битные слова. + text += ' FC%d address=%03X count=%d' % (result['function'], result['address'], result['count']) # Журнал явно различает четыре банка единого Modbus. elif msg == 8: text += ' info=%02X code=%02X' % (body >> 8, body & 255) elif msg in (9, 12): diff --git a/python/protocan/README.md b/python/protocan/README.md index bd9f1b4..b62e697 100644 --- a/python/protocan/README.md +++ b/python/protocan/README.md @@ -55,3 +55,7 @@ assert decode_entry(raw) == entry `SETGUI` (вкладки «Шина CAN» и «Адресное пространство»), `CAN_to_RS485`. Там пакет лежит внутри `gui_desktop/core`, здесь — источник истины. + +## GAS: регистры 0x3 и слоты 0x4 + +[Адресация GAS](../../doc/setcan/protocan/OAP.md): `0x3` — отдельные 16-битные регистры `0…65535`, запись 1…4 слов. `0x4` — слот с Word0-маской и тремя значениями; PERIPH сохраняет 200 слов в 67 слотах `0xMM00…0xMM42`. Формат определяется MsgType, без настройки профиля. diff --git a/python/protocan/can_boot.py b/python/protocan/can_boot.py index 8b80446..ca2960b 100644 --- a/python/protocan/can_boot.py +++ b/python/protocan/can_boot.py @@ -37,6 +37,8 @@ class CanBootTransfer: def __init__(self, image, target: CanBootTarget): if not 0 < len(image.data) <= 512 * 1024: raise ValueError("ProtoCAN Boot: размер образа 1…512 КиБ") + if target.product_type == 0x2833 and len(image.data) > 0x1FE00: + raise ValueError("F28335 M95M02 A/B: образ не должен превышать 130560 байт") if not 0 <= image.version <= 0xFFFFFFFF: raise ValueError("Версия образа вне диапазона u32") self.image, self.target = image, target @@ -46,6 +48,10 @@ class CanBootTransfer: self.finished = False self._window_end = 0 + @property + def response_timeout_ms(self): + return 15000 if self.stage in ("enter", "verify", "commit") else 1500 + @property def percent(self): return min(100, self.next_block * 8 * 100 // len(self.image.data)) @@ -74,7 +80,7 @@ class CanBootTransfer: # но метаданные образа сохраняют исходную длину без этого дополнения. def _window(self): total = (len(self.image.data) + 7) // 8 - self._window_end = min(total, self.next_block + 16) + self._window_end = min(total, (self.next_block // 16 + 1) * 16) # Ядро подтверждает абсолютные границы по 16 блоков; после потери повторяется только хвост текущего окна, чтобы его ACK не застал в очереди кадры следующего окна. return [self._frame(10 + self.slot, i, self.image.data[i * 8:(i + 1) * 8].ljust(8, b"\xff")) for i in range(self.next_block, self._window_end)] @@ -113,8 +119,11 @@ class CanBootTransfer: limit = total if self.stage == "erase" else self._window_end if expected > limit: raise RuntimeError("ProtoCAN Boot: подтверждён непереданный блок") - if self.stage == "data" and status == 0 and expected < self.next_block: - return [], "" + # Один и тот же ACK или SEQUENCE_ERROR может прийти от нескольких оставшихся кадров старого окна. + # Повторная отправка на каждый такой ответ переполняет очередь MCU; при отсутствии продвижения + # последнее окно повторяет транспорт по тайм-ауту, а подтверждённые ранее блоки не отправляются заново. + if self.stage == "data" and expected <= self.next_block: # Сравнивает next_block для обоих статусов: OK и SEQUENCE_ERROR не должны повторно открывать одно окно. + return [], "" # Оставляет текущие кадры и срок ожидания транспорта без изменений до нового прогресса или тайм-аута. self.next_block = expected if expected == total: self.stage = "verify" @@ -128,4 +137,93 @@ class CanBootTransfer: self.stage = "reboot" return self._control(9), "Перезапуск прибора" self.stage, self.finished = "finished", True + if self.target.product_type == 0x2833: + return [], "Образ принят; после перезапуска приложение подтвердит пробный запуск" return [], "Прошивка ProtoCAN Boot завершена" + + +class CanBootServices: + """Read-only passport queries and explicit session service commands. + + Replies use message D, body=(page<<8)|command. IDENTIFY/discovery reply body=1. + All multibyte values are little endian; version is major:8/minor:8/patch:16. + """ + def __init__(self, target: CanBootTarget): + self.target = target + + def request(self, command: int, page: int = 0): + if command not in (1, 8, 11, 12, 13, 14, 15): + raise ValueError("Unsupported service command") + if not 0 <= page <= 255 or (page and command not in (14, 15)): + raise ValueError("Invalid service page") + t = self.target + payload = bytes([page]) if command in (14, 15) else b"" + return build_frame(ProtoCanId.build(1, 0, t.device_type, t.device, 9, + t.session_id << 8 | command), payload, to_can=True) + + @staticmethod + def discover(): + return build_frame(ProtoCanId.build(1, 0, 7, 15, 13, 0), b"", to_can=True) + + def decode(self, frame, *, discovery=False): + p = ProtoCanId.parse(frame.can_id) + if (frame.to_can or not frame.ide or frame.rtr or frame.is_error or p.pm != 1 + or p.msg_type not in (12, 13) or len(frame.data) != 8): + return None + if discovery: + if p.msg_type != 13 or p.body != 1: + return None + elif (p.device_type, p.device) != (self.target.device_type, self.target.device): + return None + if p.msg_type == 12: + if p.body >> 8 != self.target.session_id: + return None + status, slot, next_block, crc32 = struct.unpack("> 8 + d = frame.data + result = {"kind": "passport", "device_type": p.device_type, "device": p.device, "command": command, "page": page} + if command == 1 and page == 0: + product, hardware, protocol, version = struct.unpack("> 24, (version >> 16) & 255, version & 65535)) + elif command == 12 and page == 0: + result.update(protocol_version=d[0], state=d[1], active_slot=d[2], target_slot=d[3], + session_id=d[4], slot_count=d[5], last_status=d[6]) + elif command == 13 and page == 0: + flags, capacity = struct.unpack("> 16, APP_DATA & 65535, APP_DATA >> 16, end & 65535, end >> 16, crc & 65535, crc >> 16, (~entry) & 65535, ((~entry) >> 16) & 65535, 0x5AA5, 0xA55A) # Первые четыре физических октета образуют ASCII FAB1; далее следуют версия, размер, адреса, CRC, инверсия entry и маркеры завершения. + return struct.pack('<16H', *values) # Передаёт ровно 32 октета без платформенного выравнивания структуры. + + +def validate_words(entry, loaded): # Одинаково проверяет содержимое JTAG COFF и транспортной таблицы RS Flash. + if any(APP_START + index not in loaded for index in range(HEADER_WORDS)): # Все слова заголовка должны присутствовать явно, а не получаться заполнением 0xFFFF. + raise ValueError('Нет полного заголовка Flash-приложения FAB1; требуется новая сборка под постоянный загрузчик') # Старый образ с codestart по 0x33FFF6 не допускается. + actual = struct.pack('<16H', *(loaded[APP_START + index] for index in range(HEADER_WORDS))) # Получает описание именно из передаваемых данных. + if actual != descriptor(entry, loaded): # Проверяет CRC, границы, обе половины entry и маркеры одной независимой реконструкцией. + raise ValueError('Заголовок или CRC32 Flash-приложения FAB1 не соответствует данным') # Повреждение нельзя скрыть корректным именем файла или внешним паспортом. + + +def parse_sci8(data): # Разбирает только приложение ниже сектора A, не разрешая аппаратный переход ROM. + if len(data) < 24 or len(data) % 2 or data[:2] != b'\xaa\x08': # SCI8 имеет ключ 0x08AA, 22-октетный заголовок и чётный терминатор. + raise ValueError('Неверный заголовок или размер Flash SCI8') # Обычный бинарный дамп и COFF не являются таблицей адресных блоков TI. + def address(offset): # Адрес TI состоит из старшего 16-битного слова, затем младшего; каждое слово little endian. + high, low = struct.unpack_from(' len(data): # Адрес и все слова должны помещаться в текущем файле. + raise ValueError('Обрезанный блок Flash SCI8') # Не читает случайные байты за границей изображения. + start = address(offset) # Получает абсолютный адрес назначения очередного блока. + offset += 4 # Пропускает две половины абсолютного адреса. + if not APP_START <= start < start + count <= APP_STOP: # Сектор A и весь аппаратный boot исключены независимо от имени секции. + raise ValueError(f'Запрещённый Flash-диапазон 0x{start:06X}, {count} слов: загрузчик защищён') # Показывает точное пересечение до начала обновления. + values = struct.unpack_from('<' + 'H' * count, data, offset) # Читает только полностью проверенный блок. + if any(start + index in loaded for index in range(count)): # Дублирование адреса могло бы скрыть подмену заголовка поздним блоком. + raise ValueError('Перекрывающиеся блоки Flash SCI8') # Запрещает неоднозначный порядок программирования. + loaded.update((start + index, value) for index, value in enumerate(values)) # Сохраняет каждое слово по его физическому LOAD-адресу. + blocks.append((start, data[offset:offset + count * 2])) # Сохраняет исходные октеты без изменения порядка секций. + offset += count * 2 # Переходит к размеру следующего блока. + raise ValueError('Нет терминатора Flash SCI8') # Обрезанный файл не считается полным приложением. + + +def coff_sections(document): # Извлекает адреса и точные октеты из результата TI ofd2000 -x. + coff = document.find('.//ti_coff') # Рабочая прошивка F28335 использует COFF ABI. + if coff is None or coff.findtext('file_header/target_id') != '0x9d' or coff.findtext('file_header/exec') != 'true': # Проверяет процессор и признак связанного исполняемого файла. + raise ValueError('Требуется исполняемый COFF C2000') # Объектные модули и файлы другой архитектуры не программируются. + entry = int(coff.findtext('optional_file_header/entry_point', '0'), 0) # Entry задаёт запуск приложения через общий Flash boot. + sections, loaded = {}, {} # Отдельно хранит XML полей секций и адресное пространство программируемых слов. + for section in coff.findall('section'): # Рассматривает все секции, включая LOAD для функций, исполняемых из RAM. + sections[section.findtext('name')] = section # Служебный заголовок находится по стабильному имени .flash_app. + raw, start = section.findtext('raw_data'), int(section.findtext('virtual_addr', '0'), 0) # OFD называет virtual адресом LOAD, physical — RUN. + if raw is None or section.findtext('copy') == 'true': # Только явно незагружаемые COPY/отладочные секции и секции без данных исключаются из программирования. + continue # Их наличие не расширяет область разрешённого программирования. + payload = base64.b64decode(raw) # Получает точные октеты вместо доверия к соседней MAP. + if len(payload) != int(section.findtext('raw_data_size', '0'), 0) or len(payload) % 2 or not APP_START <= start < start + len(payload) // 2 <= APP_STOP: # Любая загружаемая секция обязана целиком находиться ниже A; RAM, OTP, CSM и несогласованный размер запрещены. + raise ValueError('COFF содержит запрещённую Flash-секцию: ' + str(section.findtext('name'))) # Старый самостоятельный codestart будет отклонён. + for index, value in enumerate(struct.unpack('<' + 'H' * (len(payload) // 2), payload)): # Восстанавливает 16-битное представление каждого слова C28x. + if start + index in loaded: # Две секции не должны программировать одно физическое слово. + raise ValueError('Перекрывающиеся LOAD-секции COFF') # Сохраняет единственность заголовка и однозначную контрольную сумму. + loaded[start + index] = value # Собирает ожидаемый Flash-образ для проверки CRC и конверсии SCI8. + return entry, loaded, sections # Метаданные нужны как подписанию, так и независимой проверке готового OUT. + + +def seal_coff(image, inspector): # Заполняет только заранее выделенный linker заголовок после успешной линковки. + image = Path(image) # Принимает путь текущей сборки без зависимости от рабочего каталога. + document = ET.fromstring(subprocess.check_output([str(inspector), '-x', str(image)])) # Доверяет размещению секций, подтверждённому официальным TI-инспектором. + entry, loaded, sections = coff_sections(document) # Отсекает любой LOAD в сектор A до изменения двоичного файла. + section = sections.get('.flash_app') # Секция размером 16 слов резервируется linker и не меняет адресов остальной программы. + if section is None or int(section.findtext('virtual_addr', '0'), 0) != APP_START or int(section.findtext('raw_data_size', '0'), 0) != HEADER_WORDS * 2: # Нельзя добавлять заголовок поверх машинного кода. + raise ValueError('Linker должен выделить .flash_app из 16 слов по адресу 0x300000') # Ошибка требует пересборки вместо небезопасного смещения программы. + offset = int(section.findtext('file_offsets/raw_data_ptr', '0'), 0) # OFD указывает точное файловое смещение содержимого секции COFF. + raw, signed = bytearray(image.read_bytes()), descriptor(entry, loaded) # Считает CRC уже окончательно связанных Flash LOAD-секций. + if offset <= 0 or offset + len(signed) > len(raw): # Проверяет размер файла до адресной записи заголовка. + raise ValueError('Неверное смещение заголовка COFF') # Повреждённые метаданные не могут изменить постороннюю часть OUT. + raw[offset:offset + len(signed)] = signed # Меняет только зарезервированные 32 октета, не трогая символы, адреса и отладочную информацию. + image.write_bytes(raw) # Сохраняет подписанный результат до конверсии в SCI8 и создания внешнего SHA-256. + loaded.update((APP_START + index, value) for index, value in enumerate(struct.unpack('<16H', signed))) # Приводит адресную модель к записанному заголовку. + validate_words(entry, loaded) # Независимо проверяет только что сформированный результат. diff --git a/python/protocan/gas_slots.py b/python/protocan/gas_slots.py new file mode 100644 index 0000000..e2e19db --- /dev/null +++ b/python/protocan/gas_slots.py @@ -0,0 +1,79 @@ +import ctypes # Передаём построение ID, проверку маски и порядок октетов единственному C-кодеку. +from .native import get_native_core # Используем штатный поиск библиотеки без резервного Python-кодека. + +class GasSlots: # Тип 0x4 содержит Word0 с маской и три значения в фиксированных позициях. + def __init__(self, library=None): # Тест или приложение может передать ту же собранную библиотеку явно. + self.lib = library or get_native_core().lib # Отсутствующее общее ядро проявляется штатной ошибкой загрузки. + self.lib.pcan_gas_slot_request_id.argtypes = [ctypes.c_uint] * 3 # Обёртка PERIPH принимает mode, локальный слот и Route. + self.lib.pcan_gas_slot_request_id.restype = ctypes.c_uint32 # Extended ID возвращается без знакового преобразования. + self.lib.pcan_gas_slot_id.argtypes = [ctypes.c_uint] * 4 # Общий построитель принимает DeviceType, DeviceID, полный адрес и Route. + self.lib.pcan_gas_slot_id.restype = ctypes.c_uint32 # Любой корректный ID типа 0x4 отличен от нулевого маркера ошибки. + self.lib.pcan_gas_slot_encode.argtypes = [ctypes.POINTER(ctypes.c_uint16), ctypes.c_uint, ctypes.POINTER(ctypes.c_uint8)] # Четыре wire-слова включают маску, а не четвёртый регистр. + self.lib.pcan_gas_slot_encode.restype = ctypes.c_int # Кодек возвращает длину 0/8 либо отрицательный отказ. + self.lib.pcan_gas_slot_decode.argtypes = [ctypes.c_uint32, ctypes.c_uint, ctypes.POINTER(ctypes.c_uint8), ctypes.c_uint, ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint16)] # PERIPH-декодер дополнительно проверяет принадлежность странице и последний слот. + self.lib.pcan_gas_slot_decode.restype = ctypes.c_int # Результат 0/4 включает маску при наличии данных. + self.lib.pcan_gas_slot_decode_words.argtypes = [ctypes.c_uint32, ctypes.c_uint, ctypes.POINTER(ctypes.c_uint8), ctypes.c_uint, ctypes.POINTER(ctypes.c_uint16)] # Общий декодер поддерживает остальные классы узлов и все 16 бит адреса. + self.lib.pcan_gas_slot_decode_words.restype = ctypes.c_int # Отрицательное значение означает отказ без публикации частичного результата. + + @staticmethod # Проверка представимости Python-чисел не дублирует wire-логику. + def _unsigned(value, maximum): # Проверяем границы до возможного сужения ctypes. + if type(value) is not int or not 0 <= value <= maximum: # bool, дробь и отрицательное число не являются полями протокола. + raise ValueError('Недопустимое целое значение протокола') # Не отправляем усечённое значение к другому адресу. + + def _payload(self, words, route): # Общая упаковка используется адресным и PERIPH-построителями. + values = None if words is None else tuple(words) # Фиксируем входной iterable до преобразования к C-массиву. + if values is not None: # Запись или ответ содержат ровно маску и три значения. + if len(values) != 4: # Позиции не сдвигаются при частичной записи. + raise ValueError('Нужны Word0-маска и три значения Word1…Word3') # Не дополняем отсутствующие позиции нулями неявно. + for value in values: # Все wire-слова имеют одинаковую ширину 16 бит. + self._unsigned(value, 0xFFFF) # Корректные ноль и 65535 остаются допустимыми значениями. + if values is None and route != 0: # Пустой ответ прибора не имеет определённого смысла. + raise ValueError('Ответ должен содержать маску и значения') # Отказ возникает до отправки в транспорт. + source = None if values is None else (ctypes.c_uint16 * 4)(*values) # Маску и значения проверяет C до кодирования. + data = (ctypes.c_uint8 * 8)() # Буфер ограничен одним classic CAN кадром. + length = self.lib.pcan_gas_slot_encode(source, 0 if values is None else 4, data) # Единственный кодек проверяет разрешённые биты маски и порядок октетов. + if length < 0: # Неверная маска не заменяется другой командой. + raise ValueError('Неверная маска GAS SLOT: допустимы непустые биты 1…3') # Бит 0 относится к служебному слову и запрещён. + return bytes(data[:length]) # Возвращаем только готовые wire-октеты. + + def frame(self, mode, slot, words=None, route=0): # Удобная обёртка для 200 регистров каждого mode PERIPH. + for value in (mode, slot, route): # Исключаем переполнение host ABI до вызова C. + self._unsigned(value, 0xFFFFFFFF) # Семантические пределы mode и local проверяет общий построитель. + can_id = self.lib.pcan_gas_slot_request_id(mode, slot, route) # C формирует MsgType=0x4 и HEX-страницу mode. + if can_id == 0: # Не создаём адрес для резерва страницы или неверного направления. + raise ValueError('Неверный mode, слот или направление') # Исходная ошибка не превращается в обращение к соседнему прибору. + payload = self._payload(words, route) # Данные одинаковы для обоих адресных API. + self.decode(can_id, payload) # Дополнительно проверяем маску двух действующих значений последнего слота PERIPH. + return can_id, payload # Транспорт получает готовые CAN ID и данные. + + def frame_address(self, device_type, device_id, address, words=None, route=0): # Полный слотный API для любого узла, включая STM Invertor. + for value in (device_type, device_id, address, route): # Python-числа не должны оборачиваться в C unsigned. + self._unsigned(value, 0xFFFFFFFF) # Конкретную ширину полей идентификатора проверяет C. + can_id = self.lib.pcan_gas_slot_id(device_type, device_id, address, route) # Общий построитель сохраняет все адреса 0…65535. + if can_id == 0: # Нулевой результат означает ошибку адреса узла или слота. + raise ValueError('Неверный адрес узла, слота или направление') # Не скрываем ошибку входа маскированием. + return can_id, self._payload(words, route) # Не привязываем общий формат к странице PERIPH. + + def _input(self, can_id, data, flags): # Проверяем размеры и представимость до создания ctypes-буферов. + self._unsigned(can_id, 0xFFFFFFFF) # C затем проверит фактические 29 бит CAN ID. + self._unsigned(flags, 0xFFFFFFFF) # Флаги IDE/RTR/ERR проверяются общим wire-кодеком. + payload = bytes(data) # Сохраняем точную длину без усечения. + if len(payload) > 8: # CAN FD не включается неявно. + raise ValueError('Classic CAN допускает до восьми октетов') # Лишние октеты остаются видимой ошибкой. + return (ctypes.c_uint8 * len(payload)).from_buffer_copy(payload), len(payload) # Нулевой запрос не требует фиктивных данных. + + def decode(self, can_id, data, flags=1): # Возвращаем mode, локальный слот и wire-слова PERIPH с маской. + raw, length = self._input(can_id, data, flags) # Получаем проверенный ограниченный буфер. + mode, slot, words = ctypes.c_uint(), ctypes.c_uint(), (ctypes.c_uint16 * 4)() # Отдельные выходы сохраняют ширину host ABI. + count = self.lib.pcan_gas_slot_decode(can_id, flags, raw, length, ctypes.byref(mode), ctypes.byref(slot), words) # C проверяет полный формат и геометрию PERIPH. + if count < 0: # Чужая страница или несуществующая позиция не становятся регистрами другого профиля. + raise ValueError('Неверный кадр GAS SLOT PERIPH') # Никакого автоматического перехода к типу 0x3. + return mode.value, slot.value, tuple(words[:count]) # Пустой кортеж означает запрос чтения. + + def decode_address(self, can_id, data, flags=1): # Декодируем маску и три значения любого адресуемого узла. + raw, length = self._input(can_id, data, flags) # Проверяем точную длину до native-вызова. + words = (ctypes.c_uint16 * 4)() # Четыре wire-слова включают служебную маску. + count = self.lib.pcan_gas_slot_decode_words(can_id, flags, raw, length, words) # Общий C-кодек проверяет тип 0x4 и все транспортные условия. + if count < 0: # Ошибка не выдаётся за допустимый пустой слот. + raise ValueError('Неверный кадр GAS SLOT') # Сообщение пригодно для CAN-журнала. + return tuple(words[:count]) # Адрес и класс узла уже доступны вызывающему коду в CAN ID. diff --git a/python/protocan/gas_watch.py b/python/protocan/gas_watch.py new file mode 100644 index 0000000..f6ba056 --- /dev/null +++ b/python/protocan/gas_watch.py @@ -0,0 +1,115 @@ +# Тонкий порт GAS_WATCH2: форматы запросов, подтверждений и выборок проверяет общее C-ядро. +# Python хранит неизменяемые модели и состояние подтверждённой подписки без второго кодека. + +from __future__ import annotations # Откладываем вычисление аннотаций для совместимости с Python 3.8. + +import ctypes # Передаём типизированные буферы единственной реализации протокола в общей библиотеке. +from dataclasses import dataclass # Неизменяемые модели фиксируют порядок адресов и значений одной конфигурации. + +MAX_SIGNALS = 64 # Общий контракт GAS_WATCH2 ограничивает подписку 64 регистрами по 16 бит. +MAX_PAYLOAD_BYTES = 512 # Верхняя граница payload GUI protocol v1 позволяет C выбрать фактическую длину запроса. + + +def _unsigned(value: int, maximum: int, name: str) -> None: # Проверяем представимость Python-числа перед сужением через ctypes. + if type(value) is not int or not 0 <= value <= maximum: # Исключаем bool, дроби и переполнение целевого беззнакового типа. + raise ValueError(f"{name}: требуется целое число от 0 до {maximum}") # Не допускаем незаметного усечения C-аргумента. + + +@dataclass(frozen=True) # Изменение списка после отправки не должно менять смысл ожидаемого подтверждения. +class GasWatchConfig: # Описываем подписку отдельно от её визуального оформления и истории графика. + config_id: int # Ненулевой 32-битный идентификатор связывает выборки с конкретным порядком адресов. + period_ms: int # Беззнаковый 16-битный период задаётся в миллисекундах; ноль используется для отключения. + addresses: tuple[int, ...] # Порядок 16-битных GAS-адресов совпадает с порядком значений в выборке. + + def __post_init__(self) -> None: # Нормализуем коллекцию и защищаем границу Python/C от сужения чисел. + _unsigned(self.config_id, 0xFFFFFFFF, "config_id") # Диапазон соответствует uint32_t в публичном C ABI. + if self.config_id == 0: # Нулевой идентификатор зарезервирован для состояния без установленной подписки. + raise ValueError("config_id должен быть ненулевым") # Не создаём модель, которая не может обозначать конфигурацию. + _unsigned(self.period_ms, 0xFFFF, "period_ms") # Диапазон соответствует uint16_t; логическое сочетание с адресами проверяет C. + addresses = tuple(self.addresses) # Отделяем модель от изменяемого списка, переданного вызывающим приложением. + if len(addresses) > MAX_SIGNALS: # Не передаём C массив сверх согласованного предела подписки. + raise ValueError("GAS_WATCH2 поддерживает не более 64 адресов") # Объясняем ограничение до выделения буфера ctypes. + for address in addresses: # Проверяем каждый элемент до записи в массив uint16_t. + _unsigned(address, 0xFFFF, "address") # GAS использует нулевые 16-битные индексы регистров, без расширенных адресов. + object.__setattr__(self, "addresses", addresses) # Устанавливаем неизменяемую копию внутри frozen dataclass только при создании. + + +@dataclass(frozen=True) # Полученная выборка остаётся стабильной при передаче между рабочим потоком и GUI. +class GasWatchSample: # Возвращаем проверенную модель, а не поля бинарного сообщения. + config_id: int # Идентификатор принадлежит уже подтверждённой конфигурации, проверенной C-декодером. + sequence: int # 32-битный номер выборки позволяет приложению обнаруживать пропуски доставки. + timestamp_ms: int # 32-битная метка устройства передаётся в миллисекундах без подмены временем GUI. + values: tuple[int | None, ...] # None обозначает ошибку источника и отличается от корректного нулевого значения. + + def __post_init__(self) -> None: # Не допускаем сохранения изменяемого списка в публичной frozen-модели. + _unsigned(self.config_id, 0xFFFFFFFF, "config_id") # Сохраняем представимость идентификатора в C uint32_t. + _unsigned(self.sequence, 0xFFFFFFFF, "sequence") # Переполнение счётчика обрабатывается устройством по модулю 2^32. + _unsigned(self.timestamp_ms, 0xFFFFFFFF, "timestamp_ms") # Ограничиваем метку диапазоном миллисекундного uint32_t. + values = tuple(self.values) # Копируем контейнер, чтобы внешний список не изменял уже принятую выборку. + if len(values) > MAX_SIGNALS: # Размер результата должен помещаться в общий предел числа каналов. + raise ValueError("GAS_WATCH2 поддерживает не более 64 значений") # Отвергаем публичную модель с недопустимой геометрией. + for value in values: # Проверяем только модель данных, не выполняя повторного разбора wire-пакета. + if value is not None: # Недоступный источник представляется None и не требует числового преобразования. + _unsigned(value, 0xFFFF, "value") # Достоверное значение регистра сохраняется как беззнаковое 16-битное слово. + object.__setattr__(self, "values", values) # Закрепляем независимый кортеж в неизменяемом экземпляре. + + +class NativeGasWatch: # Управляем ожидаемой и активной подписками поверх единственного C-кодека GAS_WATCH2. + def __init__(self, library: ctypes.CDLL) -> None: # Принимаем уже загруженную общую библиотеку без поиска или fallback. + self.lib = library # Сохраняем владельца C-функций на весь срок жизни адаптера. + try: # Проверяем наличие всей новой возможности до настройки сигнатур ABI. + self._request = library.set_gas_watch_request # C формирует запрос и проверяет допустимость полной конфигурации. + self._ack = library.set_gas_watch_ack # C сравнивает подтверждение со всем запрошенным списком адресов. + self._decode = library.set_gas_watch_decode # C проверяет версию, идентификатор, геометрию и маску достоверности. + except AttributeError as error: # Старая DLL может оставаться пригодной для других возможностей протокола. + raise RuntimeError("Пересоберите SETProtocol с set_gas_watch.c для поддержки GAS_WATCH2") from error # Явно сообщаем о необходимой сборке вместо Python-кодека. + self._request.argtypes = [ctypes.c_uint32, ctypes.c_uint16, ctypes.POINTER(ctypes.c_uint16), ctypes.c_size_t, ctypes.POINTER(ctypes.c_uint8), ctypes.c_size_t] # Передаём id, период, адреса и явные размеры входа/выхода по C ABI. + self._request.restype = ctypes.c_size_t # Ноль означает отказ C-валидатора, положительное значение — длину payload. + self._ack.argtypes = [ctypes.POINTER(ctypes.c_uint8), ctypes.c_size_t, ctypes.c_uint32, ctypes.c_uint16, ctypes.POINTER(ctypes.c_uint16), ctypes.c_size_t] # Сопоставляем байты ACK с полным содержимым ожидаемой конфигурации. + self._ack.restype = ctypes.c_int # Ненулевой результат подтверждает точное принятие подписки устройством. + self._decode.argtypes = [ctypes.POINTER(ctypes.c_uint8), ctypes.c_size_t, ctypes.c_uint32, ctypes.c_size_t, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint16), ctypes.POINTER(ctypes.c_uint8), ctypes.c_size_t] # C получает ожидаемую конфигурацию и отдельные буферы значений и достоверности. + self._decode.restype = ctypes.c_int # Отрицательный результат означает устаревшее либо повреждённое сообщение. + self.reset() # Новый экземпляр не принимает DATA до подтверждения своей первой подписки. + + def reset(self) -> None: # Сбрасываем состояние соединения при переподключении без отправки wire-команд. + self._pending: GasWatchConfig | None = None # Позднее подтверждение предыдущего соединения больше не ожидается. + self._active: GasWatchConfig | None = None # Ранее подтверждённые DATA нельзя привязать к новому соединению автоматически. + + def request(self, config: GasWatchConfig) -> bytes: # Подготавливаем запрос, оставляя старую активную подписку до нового ACK. + if not isinstance(config, GasWatchConfig): # Тонкий порт требует заранее нормализованную модель вместо произвольного объекта. + raise TypeError("Ожидается GasWatchConfig") # Не допускаем обхода проверок представимости аргументов ctypes. + for known in (self._active, self._pending): # Сравниваем идентификатор с ещё значимыми конфигурациями текущего соединения. + if known is not None and known.config_id == config.config_id and known != config: # Один id не может обозначать другой порядок адресов или период. + raise ValueError("Новая конфигурация требует нового config_id") # Иначе C не сможет отличить старые DATA с тем же id и количеством. + addresses = (ctypes.c_uint16 * len(config.addresses))(*config.addresses) # Передаём C непрерывный массив слов без собственного кодирования endian. + output = (ctypes.c_uint8 * MAX_PAYLOAD_BYTES)() # Резервируем транспортный предел; реальную длину определяет C-builder. + size = self._request(config.config_id, config.period_ms, addresses, len(addresses), output, len(output)) # Единственный C-валидатор проверяет дубликаты и сочетание периода с количеством. + if not size: # При ошибке запроса сохраняем предыдущие ожидаемую и активную подписки. + raise ValueError("Недопустимая конфигурация GAS_WATCH2") # Не публикуем частично сформированный payload. + self._pending = config # После успешной сборки ожидаем ACK именно последнего отправляемого запроса. + return bytes(output[:size]) # Копируем готовые байты C без разбора или пересборки полей в Python. + + def validate_ack(self, payload: bytes, config: GasWatchConfig) -> None: # Активируем подписку только после полного подтверждения её содержимого. + if self._pending is None or config != self._pending: # Поздний ACK предыдущего запроса не должен отменять более новую ожидаемую конфигурацию. + raise ValueError("Подтверждение не соответствует ожидаемой конфигурации GAS_WATCH2") # Сохраняем активную подписку при гонке ответов. + data = (ctypes.c_uint8 * len(payload)).from_buffer_copy(payload) # Предоставляем C входные байты без знания их внутреннего расположения. + addresses = (ctypes.c_uint16 * len(config.addresses))(*config.addresses) # Сохраняем исходный порядок для строгой проверки эха в C. + if not self._ack(data, len(data), config.config_id, config.period_ms, addresses, len(addresses)): # Требуем совпадения всей конфигурации, а не одного количества каналов. + raise ValueError("Устройство не подтвердило полную конфигурацию GAS_WATCH2") # Повреждённый или частичный ACK не изменяет состояния подписок. + self._active = config # Только подтверждённая конфигурация определяет допустимые DATA и порядок возвращаемых значений. + self._pending = None # Повторный либо поздний ACK больше не считается ответом на ожидаемую команду. + + def sample(self, payload: bytes) -> GasWatchSample: # Преобразуем проверенную C выборку в неизменяемую модель языка GUI. + config = self._active # Один вызов использует один согласованный снимок ссылки на подтверждённую конфигурацию. + if config is None: # До первого ACK и после reset принадлежность значений неизвестна. + raise RuntimeError("Сначала подтвердите конфигурацию GAS_WATCH2") # Не принимаем неподтверждённые или оставшиеся от прошлого соединения DATA. + data = (ctypes.c_uint8 * len(payload)).from_buffer_copy(payload) # Буфер ctypes передаёт готовый пакет C-декодеру без Python-парсинга. + sequence = ctypes.c_uint32() # C запишет номер выборки только после полной проверки пакета. + timestamp = ctypes.c_uint32() # C вернёт исходную миллисекундную метку устройства. + values = (ctypes.c_uint16 * MAX_SIGNALS)() # Буфер рассчитан на максимальные 64 регистра, согласованные с C-контрактом. + valid = (ctypes.c_uint8 * MAX_SIGNALS)() # C разворачивает wire-маску в отдельный признак достоверности каждого значения. + count = self._decode(data, len(data), config.config_id, len(config.addresses), ctypes.byref(sequence), ctypes.byref(timestamp), values, valid, MAX_SIGNALS) # Проверку id, длины и маски полностью выполняет общее ядро. + if count < 0: # Устаревшие и повреждённые DATA не меняют конфигурацию и не попадают на график. + raise ValueError("Устаревшие или повреждённые данные GAS_WATCH2") # Не возвращаем нулевые значения из неуспешного C-вызова. + words = tuple(values[index] if valid[index] else None for index in range(count)) # Преобразуем результат C в модель, сохраняя различие отсутствующего значения и нуля. + return GasWatchSample(config.config_id, sequence.value, timestamp.value, words) # Закрепляем идентификатор именно той конфигурации, которую подтвердил C-декодер. diff --git a/python/protocan/protocan.py b/python/protocan/protocan.py index 5a31d62..3a76e3e 100644 --- a/python/protocan/protocan.py +++ b/python/protocan/protocan.py @@ -46,10 +46,8 @@ class MsgType(IntEnum): DISCRETE = 0b0001 ANALOG = 0b0010 GENERAL_ADDRESS_SPACE = 0b0011 - MODBUS_COIL = 0b0100 - MODBUS_DISCRETE = 0b0101 - MODBUS_HOLDING = 0b0110 - MODBUS_INPUT = 0b0111 + GAS_SLOT = 0b0100 # Тип 0x4 однозначно выбирает слотный GAS с маской вместо прежнего Modbus Coil. + MODBUS = 0b0101 # Единый тип 0x5 выбирает банк функцией 1…4 в Body; номера 0x6 и 0x7 освобождены. ERROR = 0b1000 BOOT_CONTROL = 0b1001 BOOT_DATA_A = 0b1010 @@ -60,6 +58,13 @@ class MsgType(IntEnum): PULSE = 0b1111 +class ModbusFunction(IntEnum): # Функция единого типа Modbus выбирает один из четырёх банков. + COIL = 1 # Дискретные выходы соответствуют функции 1. + DISCRETE = 2 # Дискретные входы соответствуют функции 2. + HOLDING = 3 # Изменяемые 16-битные регистры соответствуют функции 3. + INPUT = 4 # Входные 16-битные регистры соответствуют функции 4. + + class SettingsResult(IntEnum): OK = 0x00 INVALID_DLC = 0x01 @@ -115,10 +120,8 @@ MSGTYPE_RU = { MsgType.DISCRETE: "Discrete", MsgType.ANALOG: "Analog", MsgType.GENERAL_ADDRESS_SPACE: "General Address Space", - MsgType.MODBUS_COIL: "Modbus Coil", - MsgType.MODBUS_DISCRETE: "Modbus Discrete", - MsgType.MODBUS_HOLDING: "Modbus Holding", - MsgType.MODBUS_INPUT: "Modbus Input", + MsgType.GAS_SLOT: "GAS Slot", # Отдельное имя показывает, что адрес в Body относится к слоту, а не к Modbus-регистру. + MsgType.MODBUS: "Modbus", # Один тип охватывает Coil, Discrete, Holding и Input через поле функции. MsgType.ERROR: "Error", MsgType.BOOT_CONTROL: "Boot Control", MsgType.BOOT_DATA_A: "Boot Data A", @@ -134,14 +137,26 @@ MSGTYPE_RU = { #: но не присваивает приборам имён. DEVICE_TYPE_NAMES = { 0x0: "Верхний уровень", + 0x1: "PERIPH 0–15", # Excel «Интерфейс протокола», C6/F6: первый тип содержит младшие 16 номеров периферии. + 0x2: "PERIPH 16–31", # Excel C7/F7: второй тип продолжает нумерацию, сохраняя четырёхбитный Device ID. 0x6: "Логические анализаторы", } DEVICE_ADDRESS_NAMES = { + (0x1, 0x5): "УМП1", # Excel B50/C50/F50 закрепляет отдельный адрес первого модуля нагрузки. + (0x1, 0x6): "УМП2", # Excel B51/C51/F51 отделяет второй модуль от первого и от задатчика. + (0x1, 0x8): "Задатчик", # Excel B53/C53/F53 задаёт адрес задатчика без сдвига старого CAN Mode на единицу. (0x6, 0xE): "Altera Logic", (0x7, 0xD): "configurator", + (0x7, 0xE): "STM Invertor", # Отдельный ПЧ STM32G474VET6: адрес 7/E проверен по портам Templates; 7/D и 7/F заняты. } + +def periph_address(periph_id: int) -> tuple[int, int]: # Возвращает адрес ProtoCAN для номера из 32 строк обновлённой таблицы PERIPH. + if not 0 <= periph_id < 32: # Число 32 задаёт полный диапазон двух типов по 16 экземпляров; за его пределами адрес не назначается. + raise ValueError("ID PERIPH должен быть в диапазоне 0…31") # Запрещает незаметное оборачивание ошибочного номера на другую плату. + return 1 + periph_id // 16, periph_id % 16 # Старшая группа выбирает Type 1/2, младшие четыре бита — Device ID 0…15. + SETTINGS_RESULT_RU = { SettingsResult.OK: "успех", SettingsResult.INVALID_DLC: "неверный DLC", @@ -336,9 +351,8 @@ def split_analog(body: int): return body & 0xFFF, (body >> 12) & 0xF -def split_modbus(body: int): - """MODBUS: RegCount[3:0], StrAdr[15:4].""" - return (body >> 4) & 0xFFF, body & 0xF +def split_modbus(body: int): # Возвращает адрес, количество и функцию в тех же единицах, что принимает упаковщик. + return (body >> 4) & 0xFFF, (body & 3) + 1, ((body >> 2) & 3) + 1 # Адрес занимает 12 бит, два остальных поля кодируются значением минус один. def split_error(body: int): @@ -358,8 +372,10 @@ def merge_analog(an_type: int, sensor_id: int) -> int: return ((an_type & 0xF) << 12) | (sensor_id & 0xFFF) -def merge_modbus(str_adr: int, reg_count: int) -> int: - return ((str_adr & 0xFFF) << 4) | (reg_count & 0xF) +def merge_modbus(str_adr: int, reg_count: int, function: int) -> int: # Функция 1…4 явно задаёт банк единого сообщения Modbus. + if not 0 <= str_adr <= 0xFFF or not 1 <= reg_count <= 4 or not 1 <= function <= 4 or str_adr + reg_count > 0x1000: # Проверяем окно целиком, чтобы не усекать адреса и значения двухбитных полей. + raise ValueError("Modbus: адрес 0…4095, количество и функция 1…4; окно не должно выходить за 4095") # Ошибочный ввод не превращается в допустимый кадр другого банка. + return (str_adr << 4) | ((function - 1) << 2) | (reg_count - 1) # Функция занимает биты 3:2, количество — 1:0; оба wire-кода лежат в диапазоне 0…3. def merge_error(info: int, code: int) -> int: @@ -408,9 +424,10 @@ def _ascii(data: bytes) -> str: return "".join(chr(b) if 32 <= b < 127 else "." for b in data) -def decode(raw_id: int, data: bytes, ide: bool = True, rtr: bool = False) -> Decoded: +def decode(raw_id: int, data: bytes, ide: bool = True, rtr: bool = False) -> Decoded: # Тип 0x3 всегда адресует регистры, тип 0x4 всегда адресует слоты; настройка профиля не требуется. """Разбирает кадр ProtoCAN в структуру Decoded.""" pid = ProtoCanId.parse(raw_id) + source_data = bytes(data) # Сохраняем фактическую длину кадра до отображения ограниченного classic CAN payload. data = bytes(data[:8]) res = Decoded(id=pid, dlc=len(data), data=data, ide=ide, rtr=rtr) @@ -431,15 +448,32 @@ def decode(raw_id: int, data: bytes, ide: bool = True, rtr: bool = False) -> Dec if rtr: res.warnings.append("Remote frame: полезная нагрузка отсутствует") + if pid.msg_type == MsgType.GAS_SLOT: # Слотный кодек вызывается только для своего типа 0x4, без угадывания по содержимому. + from .gas_slots import GasSlots # Тонкая модель вызывает единственный C-кодек формата и проверок. + try: # Ошибочный слот остаётся видимым в журнале, не превращаясь в регистровый кадр. + values = GasSlots().decode_address(raw_id, source_data, (1 if ide else 0) | (2 if rtr else 0)) # Общий C-кодек проверяет маску и точную длину слота любого узла, включая отдельный инвертор. + except ValueError as error: # Отказ протокола отображаем как ошибку кадра, а не подменяем legacy-декодированием. + res.summary = "GAS SLOT: неверный кадр" # Короткий текст подходит для строки CAN-лога. + res.warnings.append(str(error)) # Подробности доступны в панели выбранного сообщения. + return res # Отвергнутый слот не получает вымышленных адресов регистров. + res.fields.append(("GAS SLOT", "MsgType 0x4")) # Отдельный номер сообщения определяет формат без настройки профиля соединения. + if values: # Запрос чтения не содержит маски или значений. + res.fields.append(("Word0: маска", "0x%04X" % values[0])) # Нулевая позиция отображается как служебная маска, а не как регистр. + for index in range(1, 4): # Три значения имеют фиксированные позиции Word1…Word3 в восьмибайтовом кадре. + if values[0] & (1 << index): # Невыбранные значения не отображаются как записанные или достоверные измерения. + res.fields.append(("Слот 0x%04X, Word%d" % (pid.body, index), "0x%04X (%d)" % (values[index], values[index]))) # Полная координата сохраняет адрес слота и выбранную позицию. + res.summary = "GAS SLOT slot=0x%04X%s" % (pid.body, " mask=0x%04X" % values[0] if values else " (запрос)") # CAN-журнал явно показывает маску частичного изменения. + return res # Не передаём четыре слова старому обработчику адреса первого регистра. + if pid.msg_type == MsgType.MODBUS and len(source_data) > 8: # Проверяем реальную длину до усечения отображаемого classic CAN payload. + res.summary = "MODBUS: неверная длина кадра" # Нельзя выдавать девять и более октетов за допустимые восемь. + res.warnings.append("Modbus: classic CAN допускает не более 8 байт") # Сохраняем причину отказа для журнала и анализатора захвата. + return res # Не публикуем регистры из частично обрезанного кадра. handler = { MsgType.BROADCAST: _decode_broadcast, MsgType.DISCRETE: _decode_discrete, MsgType.ANALOG: _decode_analog, MsgType.GENERAL_ADDRESS_SPACE: _decode_gas, - MsgType.MODBUS_COIL: _decode_modbus_bit, - MsgType.MODBUS_DISCRETE: _decode_modbus_bit, - MsgType.MODBUS_HOLDING: _decode_modbus_reg, - MsgType.MODBUS_INPUT: _decode_modbus_reg, + MsgType.MODBUS: _decode_modbus, # Банк выбирается функцией из Body внутри общего обработчика. MsgType.ERROR: _decode_error, MsgType.BOOT_CONTROL: _decode_boot, MsgType.BOOT_DATA_A: _decode_boot, @@ -611,6 +645,12 @@ def _decode_gas(res: Decoded) -> None: res.fields.append((" Адрес первого регистра", "0x%04X (%d)" % (start, start))) if res.dlc % 2: res.warnings.append("DLC = %d нечётный: регистры GAS передаются парами байт" % res.dlc) + res.summary = "GAS: неверная длина данных" # Усечённое слово не должно становиться достоверным значением или уставкой в GUI. + return # Не публикуем частичный список регистров повреждённого кадра. + if start + res.dlc // 2 > 0x10000: # Адрес FFFF допустим для одного слова, следующий адрес уже выходит за 16-битное пространство. + res.warnings.append("Диапазон GAS выходит за адрес 0xFFFF") # Не создаём вымышленные адреса 0x10000 и выше. + res.summary = "GAS: неверный диапазон регистров" # Ошибка остаётся видимой в CAN-журнале. + return # Не передаём некорректные значения потребителям трендов или карты данных. vals = regs_le(res.data) if len(vals) > 4: res.warnings.append("В одном кадре GAS не более 4 регистров, получено %d" % len(vals)) @@ -629,47 +669,36 @@ def _decode_gas(res: Decoded) -> None: res.summary = "GAS: запрос по адресу 0x%04X" % start -def _decode_modbus_bit(res: Decoded) -> None: - str_adr, reg_count = split_modbus(res.id.body) - kind = "COIL" if res.id.msg_type == MsgType.MODBUS_COIL else "DISCRETE" - res.fields.append((" Modbus.StrAdr", "0x%03X (%d)" % (str_adr, str_adr))) - res.fields.append((" Modbus.RegCount", "%d" % reg_count)) - expected = reg_count % 8 + 1 - if res.dlc and res.dlc != expected: - res.warnings.append( - "Для %s ожидается DLC = RegCount %% 8 + 1 = %d, получено %d" - % (kind, expected, res.dlc)) - if len(res.data) >= 2: - val = res.data[0] | (res.data[1] << 8) - bits = ["%d" % ((val >> i) & 1) for i in range(16)] - res.registers = [(str_adr, val)] - res.fields.append((" Значение", "0x%04X" % val)) - res.fields.append((" Биты 0..15", " ".join(bits))) - res.summary = "MODBUS %s @0x%03X x%d = 0x%04X" % (kind, str_adr, reg_count, val) - else: - res.summary = "MODBUS %s @0x%03X x%d (запрос)" % (kind, str_adr, reg_count) - - -def _decode_modbus_reg(res: Decoded) -> None: - str_adr, reg_count = split_modbus(res.id.body) - kind = "HOLDING" if res.id.msg_type == MsgType.MODBUS_HOLDING else "INPUT" - res.fields.append((" Modbus.StrAdr", "0x%03X (%d)" % (str_adr, str_adr))) - res.fields.append((" Modbus.RegCount", "%d" % reg_count)) - if res.dlc and res.dlc != reg_count * 2: - res.warnings.append( - "Для %s ожидается DLC = 2 * RegCount = %d, получено %d" - % (kind, reg_count * 2, res.dlc)) - if reg_count > 4: - res.warnings.append("В одном кадре не более 4 регистров, в ID указано %d" % reg_count) - vals = regs_le(res.data) - res.registers = [(str_adr + i, v) for i, v in enumerate(vals)] - for adr, v in res.registers: - res.fields.append((" Reg 0x%04X" % adr, "0x%04X (%d)" % (v, v))) - if vals: - res.summary = "MODBUS %s @0x%03X: %s" % ( - kind, str_adr, " ".join("%04X" % v for v in vals)) - else: - res.summary = "MODBUS %s @0x%03X x%d (запрос)" % (kind, str_adr, reg_count) +def _decode_modbus(res: Decoded) -> None: # Единый тип 0x5 разбирается по номеру функции, а не по прежним трём MsgType. + if not res.ide or res.rtr: # Modbus поверх ProtoCAN принимает только расширенные data frames. + return # Общий декодер уже добавил предупреждение о неверном формате; данные такого кадра не публикуются. + str_adr, reg_count, function = split_modbus(res.id.body) # Извлекаем физические значения функции и количества 1…4. + kind = ("COIL", "DISCRETE", "HOLDING", "INPUT")[function - 1] # Порядок банков соответствует функциям Modbus 1, 2, 3 и 4. + res.fields.extend([(" Modbus.Function", "%d (%s)" % (function, kind)), (" Modbus.StrAdr", "0x%03X (%d)" % (str_adr, str_adr)), (" Modbus.RegCount", str(reg_count))]) # Журнал показывает функцию отдельно от единого типа сообщения. + res.summary = "MODBUS FC%d %s @0x%03X x%d" % (function, kind, str_adr, reg_count) # Общая подпись сохраняется также для ошибочного payload. + if str_adr + reg_count > 0x1000: # Проверяем конец окна относительно 12-битного адресного пространства. + res.warnings.append("Modbus: окно выходит за адрес 0xFFF") # Не отображаем выход за границу как корректные регистры. + return # Неверное окно не интерпретируется дальше. + expected = 1 if function <= 2 else reg_count * 2 # До четырёх битов помещаются в октет; каждому 16-битному регистру нужны два октета. + if not res.dlc: # Пустой payload обозначает запрос чтения от ПМ. + if res.id.route == Route.FROM_DEVICE: # Ответ устройства обязан содержать запрошенные значения. + res.warnings.append("Modbus: пустой ответ устройства") # Пустой ответ не маскируется под запрос. + res.summary += " (запрос)" # Запрос отображается без вымышленных нулевых значений. + return # Чтение не содержит регистров для декодирования. + if res.dlc != expected: # Длина должна точно соответствовать функции и количеству в Body. + res.warnings.append("Modbus FC%d: ожидается DLC=%d, получено %d" % (function, expected, res.dlc)) # Сообщаем ожидаемую длину без частичного разбора. + return # Некорректный payload не выдаётся за действительные данные. + if function <= 2: # Coil и Discrete передают значения младшими битами одного октета. + if res.data[0] >> reg_count: # Биты вне запрошенного количества должны оставаться нулевыми. + res.warnings.append("Modbus: установлены биты вне запрошенного количества") # Выявляем неверную битовую маску. + return # Не публикуем неверные значения. + values = [(res.data[0] >> index) & 1 for index in range(reg_count)] # Каждый следующий адрес соответствует следующему младшему биту. + else: # Holding и Input сохраняют порядок little-endian внутри каждого регистра. + values = regs_le(res.data) # Общий помощник извлекает проверенное число 16-битных значений. + res.registers = [(str_adr + index, value) for index, value in enumerate(values)] # Возвращаем отдельную координату для каждого бита или регистра. + for address, value in res.registers: # Детальная панель показывает все значения выбранного банка. + res.fields.append((" Reg 0x%04X" % address, "0x%04X (%d)" % (value, value))) # Одновременно доступны HEX и десятичное представление. + res.summary += ": " + " ".join("%04X" % value for value in values) # Краткая строка журнала включает полученные значения. def _decode_error(res: Decoded) -> None: diff --git a/python/protocan/protocol.py b/python/protocan/protocol.py index 2b7ae73..c582de2 100644 --- a/python/protocan/protocol.py +++ b/python/protocan/protocol.py @@ -51,6 +51,8 @@ class MessageType(IntEnum): GAS_CATALOG = 0x11 GAS_WATCH_SET = 0x12 GAS_WATCH_DATA = 0x13 + GAS_WATCH2_SET = 0x14 # Новый тип подписки передаёт идентификатор и полный упорядоченный список GAS-регистров, сохраняя старый 0x12. + GAS_WATCH2_DATA = 0x15 # Новый тип выборки связывает значения с конфигурацией и признаками достоверности, сохраняя старый 0x13. SENSOR_SCAN = 0x20 SENSOR_LIST = 0x21 SENSOR_READ = 0x22 diff --git a/python/protocan/stm_invertor.py b/python/protocan/stm_invertor.py new file mode 100644 index 0000000..f1f9005 --- /dev/null +++ b/python/protocan/stm_invertor.py @@ -0,0 +1,28 @@ +import ctypes # Привязка передаёт готовые слова общему C-кодеку без повторения wire-формата на Python. +from .native import _load_library # Стандартный поиск сохраняет существующий механизм доставки SETProtocol. +class StmInvertorCodec: # Один экземпляр владеет только сигнатурами функций общей библиотеки. + def __init__(self, library=None): # Явная DLL позволяет новой панели не заменять библиотеку работающего приложения. + self.lib = library if library is not None else _load_library() # Нет Python fallback при отсутствии нового C-кодека. + self.lib.set_invertor_gas_limit.argtypes = [ctypes.c_uint] # Тип сообщения передаётся без вычисления геометрии карты в Python. + self.lib.set_invertor_gas_limit.restype = ctypes.c_uint # Границы определяются профилем C из Templates. + self.lib.set_invertor_gas_build.argtypes = [ctypes.c_uint, ctypes.c_uint, ctypes.POINTER(ctypes.c_uint16), ctypes.c_uint, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint8)] # Типы совпадают с публичным C ABI общего адаптера. + self.lib.set_invertor_gas_build.restype = ctypes.c_int # C возвращает фактический DLC либо отрицательную ошибку. + self.lib.set_invertor_gas_decode.argtypes = [ctypes.c_uint32, ctypes.c_uint, ctypes.POINTER(ctypes.c_uint8), ctypes.c_uint, ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint16)] # Декодер проверяет ID, тип, направление, длину и маску. + self.lib.set_invertor_gas_decode.restype = ctypes.c_int # Число принятых wire-слов приходит только из C. + def limit(self, message_type): # Интерфейс не хранит отдельную копию константы 250 или 750. + return int(self.lib.set_invertor_gas_limit(message_type)) # Передаём актуальную границу виджету адреса. + def build(self, message_type, address, words=()): # Пустой набор слов означает чтение DLC0 в обоих протоколах. + if not 0 <= address <= 0xFFFF or len(words) > 4 or any(not 0 <= word <= 0xFFFF for word in words): # Проверяем представимость Python-чисел перед сужением до типов ABI. + raise ValueError('Адрес или значение вне диапазона ABI') # Не допускаем тихого усечения и циклического переноса ctypes. + source = (ctypes.c_uint16 * len(words))(*words) if words else None # Значения остаются словами, endian выбирает общий кодек. + identifier = ctypes.c_uint32(); data = (ctypes.c_uint8 * 8)() # Локальные буферы имеют размеры Classic CAN и не переживают вызов. + length = self.lib.set_invertor_gas_build(message_type, address, source, len(words), ctypes.byref(identifier), data) # Ни CAN ID, ни маска не строятся здесь вручную. + if length < 0: # C отклоняет неверную геометрию, длину блока и маску. + raise ValueError('GAS: неверный адрес, длина блока или маска Word0') # Пользователь видит причину отказа до передачи на шину. + return identifier.value, bytes(data[:length]) # Транспорт получает полностью готовые ID и октеты. + def decode(self, identifier, flags, payload): # Входной кадр проверяется до публикации значений интерфейсу. + if not 0 <= identifier <= 0x1FFFFFFF or len(payload) > 8: # Не допускаем сужения большого CAN ID и переполнения временного буфера. + return None # Кадры другого транспорта не считаются ответом инвертора. + data = (ctypes.c_uint8 * 8)(*payload); metadata = (ctypes.c_uint * 2)(); words = (ctypes.c_uint16 * 4)() # ABI работает с фиксированными массивами без указателей на объекты Python. + count = self.lib.set_invertor_gas_decode(identifier, flags, data, len(payload), metadata, words) # Wire-разбор остаётся единственной C-реализацией. + return (metadata[0], metadata[1], tuple(words[:count])) if count > 0 else None # Недопустимый кадр не изменяет отображённые значения. diff --git a/python/set_devices/bus_demo.py b/python/set_devices/bus_demo.py index ee81014..56a46e4 100644 --- a/python/set_devices/bus_demo.py +++ b/python/set_devices/bus_demo.py @@ -53,8 +53,8 @@ class BusDemoSource: data = tag + ("%04d" % sid).encode() elif kind == "modbus": adr, cnt = self._rng.randint(0, 0x200), self._rng.randint(1, 4) - cid = pc.ProtoCanId.build(0, 1, dev_type, dev_id, pc.MsgType.MODBUS_HOLDING, - pc.merge_modbus(adr, cnt)) + cid = pc.ProtoCanId.build(0, 1, dev_type, dev_id, pc.MsgType.MODBUS, # Демонстрация использует единый тип 0x5 вместо прежнего Holding 0x6. + pc.merge_modbus(adr, cnt, pc.ModbusFunction.HOLDING)) # Функция 3 обозначает банк Holding, количество по-прежнему находится в диапазоне 1…4. data = b"".join(self._rng.randint(0, 0xFFFF).to_bytes(2, "little") for _ in range(cnt)) elif kind == "gas": diff --git a/python/set_devices/deif_controls.py b/python/set_devices/deif_controls.py new file mode 100644 index 0000000..440435b --- /dev/null +++ b/python/set_devices/deif_controls.py @@ -0,0 +1,52 @@ +"""Готовые операции DEIF для GUI без знания wire-разметки и адресных масок.""" # Все числовые правила реализованы единственным C99-ядром templates. +import ctypes as C # Преобразование фиксированных ABI-структур не является вторым кодеком. +from dataclasses import dataclass # Именованные поля исключают индексы метаданных в GUI. +from .deif_native import get_deif_native, Frame # Общий декодер и builders используются независимо от приложения. +from .can_transport import build_frame # Транспорт получает уже готовые CAN-кадры. +@dataclass(frozen=True) # Неизменяемые описания безопасно используются диагностикой и редакторами. +class SelectorInfo: # Это скалярный результат C, а не wire-структура. + node: int; index: int; subindex: int; dam: bool; legacy_key: str # Последний элемент сохраняет только формат прежних ключей настроек Desktop. +@dataclass(frozen=True) # Описание входного кадра отделено от его транспортного контейнера. +class PacketInfo: # GUI не обращается к смещениям payload. + kind: int; node: int; index: int; subindex: int; raw: int; status: int; dam: bool # Все значения получены из C-декодера. + @property # Диагностический ключ независим от адресного байта SAM/DAM. + def object_key(self): # Для TX-эхо достаточно индекса и подиндекса готового объекта. + return self.index, self.subindex # Это идентичность объекта, а не повторная распаковка CAN-data. +def selector_info(selector): # Редактор получает имена полей вместо ручных масок. + raw = bytes.fromhex(selector) if isinstance(selector, str) else bytes(selector) # HEX — только формат хранения пользовательской настройки. + if len(raw) != 4: return None # Буфер неправильного размера не передаётся C. + metadata = (C.c_int32 * 4)() # Node, index, subindex и DAM определены публичным ABI. + if not get_deif_native().selector_info(raw, metadata): return None # Некорректная привязка не становится источником на рисунке. + return SelectorInfo(metadata[0], metadata[1], metadata[2], bool(metadata[3]), raw[1:].hex()) # Срез используется только для совместимости непрозрачного старого ключа настроек. +def readdress_selector(selector, node, dam=None): # Меняет адрес пользовательской привязки общим алгоритмом C. + if not selector: return "" # Явно отключённое поле остаётся отключённым. + raw = bytes.fromhex(selector) if isinstance(selector, str) else bytes(selector) # Порт преобразует текст настройки в буфер ABI. + output = (C.c_uint8 * 4)() # Готовый селектор создаёт C-код. + if len(raw) != 4 or not get_deif_native().readdress(raw, node, 2 if dam is None else int(bool(dam)), output): raise ValueError("Неверный селектор или Node-ID DEIF") # Индекс не пересобирается в Python. + return bytes(output).hex(" ").upper() # Формат вывода совместим с прежним редактором HEX. +def route_parameters(node, mode, identifier, operation=0): # Согласует параметры редактора с C-правилами адресации. + output = (C.c_uint32 * 3)() # COB-ID, Node и адресный байт возвращаются одним вызовом. + if not get_deif_native().route(node, mode == "dam", identifier, operation, output): return None # Неверный диапазон не вызывает произвольную перенастройку привязок. + return tuple(output) # GUI хранит и отображает готовые значения. +def data_node(identifier, fallback=1): # Получает узел из CAN ID без повторения маски в GUI. + result = route_parameters(fallback or 1, "sam", identifier, 2) # Legacy SAM сохраняет явно выбранный источник. + return result[1] if result else fallback # Вне диапазона данных остаётся пользовательское исходное значение. +def packet_info(frame): # Метаданные для подтверждения команд и TX-эхо. + code, metadata = get_deif_native().inspect_frame(frame.can_id, frame.data, frame.ide, frame.rtr) # Wire-разбор находится в C. + return PacketInfo(metadata[0], metadata[1], metadata[2], metadata[3], metadata[4], metadata[7], bool(metadata[8])) if code > 0 else None # Некорректный кадр не получает выдуманных полей. +def heartbeat_description(identifier, data, extended=False, rtr=False): # Приложение не содержит собственного классификатора CANopen error control. + code, _ = get_deif_native().inspect_frame(identifier, data, extended, rtr) # Проверку COB-ID, DLC и состояния выполняет C. + if code not in (2, -3): return None # Обычные MPDO не попадают в поле heartbeat. + from .deif_xdi import decode # Общий локализованный formatter используется обоими CAN-мониторами и прибором. + return decode(build_frame(identifier, bytes(data), ide=extended, rtr=rtr)).summary # Готовая подпись не подтверждает получение конкретного измерения. +def _frame(output): # Общий адаптер переводит структуру C в существующий транспортный контейнер. + return build_frame(output.can_id, bytes(output.data[:output.dlc]), ide=False) # Идентификатор, длина и данные уже вычислены ядром. +def service_frame(node, value, nmt=False): # Строит heartbeat либо локальную NMT-команду через C. + output = Frame() # Память результата принадлежит Python-порту. + if not get_deif_native().service(bool(nmt), node, value, C.byref(output)): raise ValueError("Неверный Node-ID или CANopen-сервис") # Ни COB-ID, ни служебные байты не собираются в GUI. + return _frame(output) # Физическую отправку выполняет выбранный приложением транспорт. +def angle_setpoint_frame(actual): # Формирует отдельный кадр задания с тем же значением фактического азимута. + source, output = Frame(), Frame() # Оба контейнера имеют стабильный layout ABI. + source.can_id, source.dlc, source.data[:] = actual.can_id, len(actual.data), bytes(actual.data) # Это копирование готового CAN-кадра, не декодирование его полей. + if not get_deif_native().angle_command(C.byref(source), C.byref(output)): raise ValueError("Кадр не содержит поддерживаемый азимут DEIF") # Проверку семейства и сборку 0x07 выполняет C. + return _frame(output) # Штатный передатчик получает второй независимый MPDO. diff --git a/python/set_devices/deif_display.py b/python/set_devices/deif_display.py new file mode 100644 index 0000000..ebf5206 --- /dev/null +++ b/python/set_devices/deif_display.py @@ -0,0 +1,129 @@ +"""Независимая от GUI Python-модель индикатора поверх общего C99-ядра DEIF.""" # Настройки и транспортные имена остаются в порту, wire-правила находятся в C. +import ctypes as C # Обмен с ABI использует фиксированные массивы и caller-owned память. +from dataclasses import dataclass # Привязка является простой моделью пользовательской настройки. +from time import monotonic # Порт передаёт часы ядру явно в миллисекундах. +from .deif_native import get_deif_native, Frame # Единственная реализация кодека и автомата загружается без Qt. + +FIELDS = ("power", "rpm", "angle", "power_percent", "rpm_percent", "angle_setpoint") # Порядок полей публичного ABI C; это имена модели, не wire-селекторы. +STATUS = {1: "ниже диапазона", 2: "выше диапазона", 3: "ошибка данных"} # Локализованные подписи готовых статусов C. + + +@dataclass # Привязки можно сохранять в существующих пользовательских профилях JSON. +class Binding: # Четыре HEX-байта и коэффициент поступают из настроек либо C-каталога. + selector: str = "" # Пустая строка означает явно отключённое поле. + scale: float = 1.0 # Коэффициент применяется только в общем C-ядре. + + +def _milliseconds(now): # Перевод единиц системных часов относится к платформенному порту. + return max(0, round((monotonic() if now is None else now) * 1000)) # ABI использует целые монотонные миллисекунды для одинаковых границ на всех платформах. + + +def validate_deif_transmit(frame): # Сохраняет прежний публичный Python API ограниченного маршрута MASTER. + if not get_deif_native().validate(frame.can_id, bytes(frame.data), len(frame.data), int(bool(frame.ide)) | (int(bool(frame.rtr)) << 1), 0): # Проверка адреса, объектов и размеров полностью выполняется в C. + raise ValueError("DEIF: разрешены только данные, яркость, Color и heartbeat; команды настройки через Node-ID запрещены") # Текст остаётся локализованной ответственностью приложения. + + +def brightness_frame(node_id, group, percent, can_id=None, mode="sam"): # Готовит один кадр без отправки или изменения прибора. + return get_deif_native().make_frame(6, node_id, percent, 0 if can_id is None else can_id, mode, group) # Поле ABI 6 обозначает яркость, исходный COB-ID и U8 определяет C. + + +def colour_palette_frame(node_id, group, palette, can_id=None, mode="sam"): # Готовит независимый от яркости кадр палитры. + return get_deif_native().make_frame(7, node_id, palette, 0 if can_id is None else can_id, mode, group) # Поле ABI 7 обозначает Color; исходный COB-ID и кодирование Day/Night/Dusk находятся в C. + + +class DeifDisplay: # Пассивная модель пригодна для Desktop, CLI и тестов без Qt. + services = False # Наблюдатель не объявляет себя узлом CAN и никогда не выдаёт heartbeat. + expiry_ms = 5000 # Прежний режим наблюдения скрывает показания после пяти секунд без обновления. + + def __init__(self, source="DevBoard", can_id=0x201, power_unit="RAW", device_node=None, bindings=None, xdi_net=True, self_start=True, dam_pdo=2, dimmer_group=1, source_node=1): # Дополнительные параметры передаются серверным портом, прежние профили остаются совместимыми. + self.source, self.can_id, self.power_unit, self.device_node = source, can_id, power_unit, device_node # Только имя транспорта и UI-единица остаются вне C. + self.xdi_net, self.self_start, self.dam_pdo, self.dimmer_group, self._source_node = xdi_net, self_start, dam_pdo, dimmer_group, source_node # Параметры профиля передаются C без копии правил протокола. + self._api, self._context, self._route, self._bindings_signature = get_deif_native(), None, None, None # Один контекст на прибор исключает смешивание показаний MASTER и SLAVE. + self.bindings = {} # Контейнер поддерживает прямое редактирование существующим диалогом привязок. + self._ensure_context() # Исходные селекторы и коэффициенты создаются единственным C-каталогом. + if bindings is None: # Новый профиль получает штатные привязки, включая азимут. + for index, key in enumerate(FIELDS[:5]): # Отдельное задание угла автоматически производно от привязки азимута в C. + selector, factor = (C.c_uint8 * 4)(), C.c_double() # Порт принимает готовые значения без разбора endian. + self._api.get_binding(self._context, index, selector, C.byref(factor)) # Настройки по умолчанию читаются из C-профиля. + self.bindings[key] = Binding(bytes(selector).hex(" ").upper(), factor.value) # HEX нужен только редактору настроек. + else: # Существующая библиотека сохраняет пользовательские объекты и масштабы. + self.bindings = {key: Binding(item.selector, item.scale) for key, item in bindings.items()} # Словари двух приборов не должны делить изменяемые Binding. + + def _ensure_context(self): # Изменение адреса требует нового C-контекста, а смена имени транспорта — нет. + route = (self.can_id, self.device_node, self.xdi_net, self.self_start, self.dam_pdo, self.dimmer_group, self.services, self._source_node) # Изменение источника также требует согласованной переинициализации. + if route == self._route: # Повторное чтение снимка не переинициализирует данные. + return # Сохраняет сроки и очередь работающего узла. + size = self._api.state_size() # Размер private C-структуры сообщает библиотека. + self._context = (C.c_uint64 * ((size + 7) // 8))() # uint64 обеспечивает необходимое выравнивание на Windows и ARM. + source = self._source_node # Источник профиля не вычисляется из имени GUI или физического Node-ID SLAVE. + if not self._api.init(self._context, size, self.device_node or 0, source, bool(self.xdi_net), bool(self.self_start), self.dam_pdo, self.dimmer_group, bool(self.services), self.can_id): # C проверяет reserved Node, RPDO и сетевые группы. + raise ValueError("DEIF: неверный профиль SLAVE, Node-ID или RPDO") # Частично инициализированный узел не используется. + self._route, self._bindings_signature = route, None # Привязки повторно синхронизируются после изменения профиля. + + def _sync_bindings(self): # Прямые изменения словаря UI передаются в C только при фактическом изменении настройки. + self._ensure_context() # Проверяет, не был ли изменён физический адрес либо CAN ID наблюдения. + signature = tuple((key, binding.selector, binding.scale) for key, binding in self.bindings.items()) # Это сравнение настроек, а не интерпретация wire-формата. + if signature == self._bindings_signature: # Частые тики и приём кадров не должны сбрасывать значения. + return # Состояние C остаётся прежним. + for index, key in enumerate(FIELDS): # Порядок соответствует публичным field IDs ядра. + if index == 5 and key not in self.bindings: # Производное задание азимута настраивает C при изменении поля angle. + continue # Не отключает автоматически созданную независимую привязку 0x07. + binding = self.bindings.get(key, Binding()) # Отсутствующее поле явно отключается. + selector = bytes.fromhex(binding.selector) if binding.selector else None # HEX является форматом хранения настроек, а не CAN-декодером. + if selector is not None and len(selector) != 4: # Порт проверяет размер буфера до передачи указателя C. + raise ValueError("Селектор DEIF должен содержать четыре байта") # Некорректная пользовательская настройка не создаёт чтение за пределами буфера. + if not self._api.bind(self._context, index, selector, binding.scale): # Интерпретация селектора и применение масштаба находятся в C. + raise ValueError("DEIF: неверная привязка или масштаб") # Нечисловой коэффициент не скрывается как отсутствие пакета. + self._bindings_signature = signature # Последующая обработка кадра использует уже настроенный контекст. + + def bind_default_angle(self): # Миграция старого профиля с пустым азимутом не требует знания адресов в GUI. + self._sync_bindings() # Источник и режим берутся из уже настроенных остальных полей. + selector, factor = (C.c_uint8 * 4)(), C.c_double() # C возвращает готовую библиотечную привязку. + if not self._api.default_angle(self._context, selector, C.byref(factor)): # Ни SAM/DAM, ни индекс не вычисляются в Python. + raise ValueError("Не удалось восстановить привязку азимута DEIF") # Ошибка миграции остаётся видимой. + self.bindings["angle"] = Binding(bytes(selector).hex(" ").upper(), factor.value) # Обновляется только отсутствующая настройка азимута. + self._sync_bindings() # Новая привязка применяется сразу в текущем сеансе. + + def reset(self): # Сохраняет API очистки показаний при смене пользовательского канала. + self._sync_bindings() # Настройки должны соответствовать очищаемому контексту. + self._api.reset_values(self._context) # Очистка выполняется общим ядром. + + def accept(self, source, identifier, data, extended=False, rtr=False, now=None): # Порт связывает транспортное имя с независимой моделью прибора. + if source != self.source or not 0 <= identifier <= 0x1FFFFFFF or len(data) > 8: # Имя канала относится к приложению, границы — к безопасному ABI. + return False # Кадры другого транспорта не обновляют C-контекст. + self._sync_bindings() # Диалог мог изменить привязки с момента предыдущего кадра. + accepted = bool(self._api.accept(self._context, identifier, bytes(data), len(data), int(bool(extended)) | (int(bool(rtr)) << 1), _milliseconds(now))) # Единственное место протокольной обработки находится в C. + return accepted and (self.services or not self._api.inspect_frame(identifier, data, extended, rtr)[1][7]) # Пассивный API сохраняет прежний признак отказа только для текущего ошибочного I16, не для других полей. + + def _snapshots(self, now=None): # Снимок переводит готовые C-поля в контейнеры Python без повторения алгоритма. + self._sync_bindings() # Требуется также после прямого редактирования масштаба в настройках. + result, moment = {}, _milliseconds(now) # Все поля одного снимка читаются в один момент времени. + for index, key in enumerate(FIELDS): # Порядок ABI не зависит от порядка ключей пользовательского словаря. + value, metadata = C.c_double(), (C.c_int64 * 4)() # C выдаёт масштабированное значение и флаги seen/valid/stale. + self._api.read(self._context, index, moment, self.expiry_ms, C.byref(value), metadata) # Свежесть и служебные статусы вычисляются ядром. + result[key] = (value.value, metadata[0] / 1000, metadata[2], metadata[3]) # Деление переводит только единицы системных часов порта. + return result # Снимок не раскрывает внутренний layout C. + + @property # Совместимый read-only снимок прежнего словаря показаний. + def values(self): # Значения остаются в C, Python не хранит вторую копию состояния. + return {key: item[0] for key, item in self._snapshots().items() if item[3] & 2} # Готовый valid-флаг исключает служебные I16. + + @property # Временные отметки нужны существующей отрисовке и диагностике. + def received(self): # Даже invalid является принятым обновлением объекта, а не отсутствием связи. + return {key: item[1] for key, item in self._snapshots().items() if item[3] & 1} # Решение о наличии сообщения уже принято C-ядром. + + def value(self, key, now=None): # Сохраняет интерфейс получения одного свежего показания. + item = self._snapshots(now).get(key) # Масштаб и свежесть получены из общего C-снимка. + return item[0] if item and item[3] & 2 and not item[3] & 4 else None # Python лишь отображает valid/stale флаги ABI. + + def angle_selection(self, now=None): # Одно правило азимута используется и пассивным монитором, и активным SLAVE. + self._sync_bindings() # Профиль мог быть загружен из старого пользовательского файла. + value = C.c_double() # Владение выходным скаляром остаётся у порта. + kind = self._api.angle(self._context, _milliseconds(now), self.expiry_ms, C.byref(value)) # C выбирает фактический угол либо принятое сетевое задание. + return (value.value if kind else None, kind == 2) # Второй элемент нужен только для подписи «задание» в GUI. + + @property # Список источников нужен только заголовку прибора, не алгоритму приёма. + def sam_sources(self): # UI получает готовые адреса без масок и смещений селектора. + from .deif_controls import selector_info # Разбор адреса селектора делегируется общему C-порту. + descriptors = [selector_info(binding.selector) for binding in self.bindings.values() if binding.selector] # Сохраняет индивидуальные привязки каждого поля. + return sorted({item.node for item in descriptors if item is not None and not item.dam}) # DAM-получатель не выдаётся за источник SAM. diff --git a/python/set_devices/deif_emulator.py b/python/set_devices/deif_emulator.py new file mode 100644 index 0000000..5b29355 --- /dev/null +++ b/python/set_devices/deif_emulator.py @@ -0,0 +1,36 @@ +"""Регистровый контракт аппаратного эмулятора DEIF из set_emu_deif.h.""" # Один контракт используется всеми MCU и настольными клиентами. +from dataclasses import dataclass # Неизменяемый снимок отделяет подтверждённое состояние платы от редактируемой формы. + +DEIF_BASE = 0x1600 # Начало окна управления DEIF в set_emu_server.c, адрес измеряется в 16-битных словах. +DEIF_WORDS = 52 # SET_DEIF_WORDS версии 1 включает профиль, RAW, привязки OD и диагностику. +DEIF_FIELDS = ("Угол, RAW", "Обороты, RAW", "Обороты %, RAW", "Мощность, RAW", "Мощность %, RAW", "Задание угла, RAW") # Порядок соответствует raw[6] переносимой C-модели; физические единицы зависят от словаря прибора. +DEIF_INDICES = (0x3001, 0x3081, 0x3091, 0x3421, 0x3431, 0x3001) # Начальные OD экземпляра 1 взяты из set_deif_init; последний объект имеет подиндекс 7. + + +@dataclass(frozen=True) # Клиент публикует только целиком проверенный снимок без последующих изменений. +class DeifSnapshot: # Тип не зависит от Qt, HAL, конкретного MCU и способа доставки регистров. + words: tuple # Содержит 52 беззнаковых слова, прочитанных одной командой FC03. + mode: int # Режим из конфигурации STM: 4 Master, 5 Slave либо иной остановленный режим. + + @property # Роль берётся из ответа платы, а не из ранее выбранного пункта GUI. + def role(self): # Возвращает 1 Master либо 2 Slave согласно set_emu_deif.h. + return self.words[3] # Слово 3 не совпадает с номерами режимов 4 и 5 блока STM. + + @property # Проверка запущенного состояния нужна для запрета изменения сетевого профиля. + def running(self): # Возвращает логическое состояние модели без запуска либо остановки. + return bool(self.words[2]) # Слово 2 равно 1 только после подтверждённой команды пуска. + + @property # Знаковое представление сохраняет отрицательные RAW и служебные коды DEIF. + def raw(self): # Возвращает шесть значений I16 в порядке DEIF_FIELDS. + return tuple(value if value < 0x8000 else value - 0x10000 for value in self.words[16:22]) # Старший бит задаёт знак 16-битного дополнения до двух. + + +def decode_snapshot(words, mode): # Проверяет совместимость прошивки до разрешения любых записей DEIF. + values = tuple(words) # Не сохраняет ссылку на изменяемый транспортный буфер. + if len(values) != DEIF_WORDS or values[:2] != (0x4446, 1): # Сигнатура DF и версия 1 заданы set_deif_read, не совпадают с конфигурацией STM. + raise ValueError("Нужна прошивка с сервисом DEIF Master/Slave версии 1") # Старая прошивка не получает команд в неизвестное окно. + if values[2] not in (0, 1) or values[3] not in (1, 2): # Повреждённые running и role не должны превращаться в разрешение записи. + raise ValueError("STM вернула неверное состояние DEIF") # Отказ сохраняет форму неподтверждённой. + if mode in (4, 5) and values[3] != mode - 3: # Конфигурация и окно состояния должны описывать одну роль текущего экземпляра. + raise ValueError("Роль DEIF не совпадает с режимом STM; повторите чтение") # Между чтениями другая сессия могла изменить режим платы. + return DeifSnapshot(values, mode) # Единственная точка создания проверенного снимка для UI и тестов. diff --git a/python/set_devices/deif_native.py b/python/set_devices/deif_native.py new file mode 100644 index 0000000..cd5a311 --- /dev/null +++ b/python/set_devices/deif_native.py @@ -0,0 +1,75 @@ +"""Тонкий ctypes-порт единственного C99-ядра DEIF из templates/c/set-protocol.""" # В Python нет второго кодека или автомата NMT. +import ctypes as C # Фиксированные типы повторяют только публичный ABI. +import os # Путь дополнительной библиотеки передаёт приложение, не общая библиотека. +from pathlib import Path # Дополнительный нативный компонент может лежать рядом с основной библиотекой любого приложения. +from protocan.native import _load_library # Стандартный механизм загрузки используется при отсутствии явного пути DEIF. + + +class Frame(C.Structure): # Структура содержит готовые STD-кадры, а не wire-структуру транспорта. + _fields_ = [("can_id", C.c_uint32), ("dlc", C.c_uint32), ("data", C.c_uint8 * 8)] # Layout размером 16 байт совпадает с deif_xdi.h. + + +class NativeDeif: # Экземпляр владеет только сигнатурами C, состояние выделяется отдельными моделями. + def __init__(self): # Отсутствие общего ядра является ошибкой сборки, алгоритмического fallback нет. + self.lib = C.CDLL(os.environ["SETPROTOCOL_DEIF_LIBRARY"]) if os.environ.get("SETPROTOCOL_DEIF_LIBRARY") else _load_library() # Выбор пути относится к загрузке, не к протоколу. + if not hasattr(self.lib, "setp_deif_version"): # Во время обновления основная DLL может оставаться занятой работающим приложением. + primary = Path(self.lib._name) # Путь сообщает стандартный загрузчик, структура gui_desktop здесь неизвестна. + self.lib = C.CDLL(str(primary.with_name(primary.stem + "_deif" + primary.suffix))) # Это дополнительная сборка того же C-ядра, а не алгоритмический Python fallback. + signatures = { # Сигнатуры скалярного ABI не зависят от внутренних C-структур. + "version": ([], C.c_int), "state_size": ([], C.c_size_t), # Проверка версии и caller-owned памяти. + "catalog": ([C.c_uint, C.POINTER(C.c_int32)], C.c_int), # Каталог числовых индексов и разрешений. + "selector": ([C.c_uint, C.c_uint, C.c_uint, C.c_uint, C.c_void_p], C.c_int), # C формирует готовый селектор. + "inspect": ([C.c_uint32, C.c_void_p, C.c_size_t, C.c_uint, C.POINTER(C.c_int32)], C.c_int), # Единственный разбор входящего wire-кадра. + "make": ([C.c_uint, C.c_uint, C.c_uint, C.c_int32, C.c_uint32, C.c_uint, C.POINTER(Frame)], C.c_int), # Единственная сборка MPDO. + "master": ([C.c_uint, C.POINTER(C.c_int32), C.c_uint32, C.c_uint, C.c_uint, C.POINTER(Frame)], C.c_int), # Единственный порядок пяти объектов цикла. + "service": ([C.c_uint, C.c_uint, C.c_uint, C.POINTER(Frame)], C.c_int), "angle_command": ([C.POINTER(Frame), C.POINTER(Frame)], C.c_int), # Служебные кадры и задание азимута собираются общим C-кодом. + "selector_info": ([C.c_void_p, C.POINTER(C.c_int32)], C.c_int), "route": ([C.c_uint, C.c_uint, C.c_uint32, C.c_uint, C.POINTER(C.c_uint32)], C.c_int), # Редакторы не разбирают адресный байт или COB-ID самостоятельно. + "readdress": ([C.c_void_p, C.c_uint, C.c_uint, C.c_void_p], C.c_int), # Перенос селектора сохраняет ручной объект без масок и endian в UI. + "validate": ([C.c_uint32, C.c_void_p, C.c_size_t, C.c_uint, C.c_uint], C.c_int), # Изолированные выходы MASTER и SLAVE. + "init": ([C.c_void_p, C.c_size_t] + [C.c_uint] * 7 + [C.c_uint32], C.c_int), # Семь параметров профиля и отдельный CAN ID наблюдателя. + "bind": ([C.c_void_p, C.c_uint, C.c_void_p, C.c_double], C.c_int), # Селектор и библиотечный масштаб передаются без интерпретации. + "get_binding": ([C.c_void_p, C.c_uint, C.c_void_p, C.POINTER(C.c_double)], C.c_int), # Исходные значения профиля приходят из единственного C-каталога. + "default_angle": ([C.c_void_p, C.c_void_p, C.POINTER(C.c_double)], C.c_int), # Общая миграция отсутствующей привязки. + "start": ([C.c_void_p, C.c_uint64, C.c_uint], C.c_int), "stop": ([C.c_void_p], None), "reset_values": ([C.c_void_p], None), # Жизненный цикл без системных часов C. + "accept": ([C.c_void_p, C.c_uint32, C.c_void_p, C.c_size_t, C.c_uint, C.c_uint64], C.c_int), # C проверяет NMT, адресацию, объекты и длину. + "poll": ([C.c_void_p, C.c_uint64, C.POINTER(Frame), C.c_size_t], C.c_size_t), # Порт владеет выходным буфером событий. + "read": ([C.c_void_p, C.c_uint, C.c_uint64, C.c_uint, C.POINTER(C.c_double), C.POINTER(C.c_int64)], C.c_int), # Готовое значение и временные метаданные индикатора. + "lost": ([C.c_void_p, C.c_uint64], C.c_uint), # Маска устаревших входов вычисляется в C. + "angle": ([C.c_void_p, C.c_uint64, C.c_uint, C.POINTER(C.c_double)], C.c_int), "meta": ([C.c_void_p, C.POINTER(C.c_int64)], C.c_int), # Единый выбор азимута и снимок состояния. + } # Эти объявления описывают ABI, а не копию алгоритма. + for name, (arguments, result) in signatures.items(): # Все отсутствующие символы выявляются при загрузке расширения. + function = getattr(self.lib, "setp_deif_" + name) # Названия совпадают с публичным заголовком templates. + function.argtypes, function.restype = arguments, result # ctypes не должен угадывать размеры указателей и целых. + setattr(self, name, function) # Короткие имена оставляют порты моделей читаемыми. + if self.version() != 1: # Несовместимый ABI не используется с предположением о layout. + raise RuntimeError("Нужна общая библиотека DEIF ABI 1") # Сообщение указывает на необходимость пересборки нативного ядра. + + def selector_bytes(self, field, node, instance=1, dam=False): # Возвращает готовый C-селектор для настроек UI. + output = (C.c_uint8 * 4)() # Размер мультиплексора задан публичным контрактом. + if not self.selector(field, node, instance, bool(dam), output): # Проверка диапазонов находится в C. + raise ValueError("DEIF: неверный Node-ID, объект или экземпляр") # Недопустимая привязка не сохраняется в настройках. + return bytes(output) # Порт преобразует только тип контейнера. + + def inspect_frame(self, identifier, data, extended=False, rtr=False): # Передаёт целый CAN-кадр общему декодеру. + if not 0 <= identifier <= 0x1FFFFFFF or len(data) > 8: # Проверяет представимость на границе ABI до сужения Python-чисел. + return -1, [0] * 12 # Переполнение нельзя превратить в другой допустимый кадр. + output = (C.c_int32 * 12)() # Индексы метаданных определены в контракте C-декодера. + code = self.inspect(identifier, bytes(data), len(data), int(bool(extended)) | (int(bool(rtr)) << 1), output) # Флаги относятся к типу CAN-кадра, не к содержимому протокола. + return code, list(output) # Локализованный текст формируется поверх готовых полей C. + + def make_frame(self, field, node, value, identifier, mode="sam", instance=1): # Возвращает кадр существующего транспортного API. + from .can_transport import build_frame # Пакет транспорта не импортируется до фактической сборки кадра. + if mode not in ("sam", "dam") or type(instance) is not int or not 0 <= instance <= 4294967295 or type(value) is not int or not -2147483648 <= value <= 2147483647 or type(node) is not int or not 0 <= node <= 127 or type(identifier) is not int or not 0 <= identifier <= 0x1FFFFFFF: # Порт проверяет только типы и представимость ABI. + raise ValueError("DEIF: неверный Node-ID, режим, CAN ID или значение") # Значения не усекаются до вызова C. + output = Frame() # Память выходного CAN-кадра принадлежит Python. + if not self.make(field, node, instance, value, identifier, mode == "dam", C.byref(output)): # Wire-байты и границы протокола определяются исключительно C. + raise ValueError("DEIF: Node-ID, RPDO, экземпляр или значение вне диапазона") # Причина отклонения остаётся видимой в интерфейсе. + return build_frame(output.can_id, bytes(output.data[:output.dlc]), ide=False) # Транспорт AA55/адаптер получает уже готовые данные STD. + + +_native = None # Общая библиотека загружается один раз на процесс. +def get_deif_native(): # Ленивое получение не требует Qt и пригодно для CLI. + global _native # Экземпляр хранит сигнатуры, состояния приборов остаются раздельными. + if _native is None: # Первая реальная операция DEIF проверяет наличие нового нативного ядра. + _native = NativeDeif() # Отсутствие DLL или ABI не скрывается Python-реализацией протокола. + return _native # Все модели используют один и тот же проверенный C-код. diff --git a/python/set_devices/deif_slave.py b/python/set_devices/deif_slave.py new file mode 100644 index 0000000..dacd573 --- /dev/null +++ b/python/set_devices/deif_slave.py @@ -0,0 +1,56 @@ +"""Серверный Python-порт DEIF: протокольное состояние целиком принадлежит общему C99.""" # Пакет не импортирует gui_desktop и пригоден без Qt. +import ctypes as C # Структуры ABI содержат только готовые кадры и скаляры. +from time import monotonic # Порт поставляет монотонные часы, чтобы C оставался независим от ОС. +from .deif_display import DeifDisplay, FIELDS, STATUS, _milliseconds # Пассивный и активный режимы используют одинаковые снимки индикаторов. +from .deif_native import Frame, get_deif_native # Нет Python-копии адресации, NMT, сроков или SDO. + + +def validate_slave_transmit(frame, node): # Серверный маршрут имеет отдельный контракт по собственному Node-ID. + if type(node) is not int or not 1 <= node <= 127 or not get_deif_native().validate(frame.can_id, bytes(frame.data), len(frame.data), int(bool(frame.ide)) | (int(bool(frame.rtr)) << 1), node): # C разрешает только собственные heartbeat, EMCY и ответы SDO. + raise ValueError("Разрешены только heartbeat, EMCY и ответы SDO своего SLAVE") # Недопустимый кадр не попадёт в физический транспорт. + + +class DeifSlave(DeifDisplay): # Отличие от монитора состоит в включённых сервисах C и сохранении последнего числа при Data lost. + services, expiry_ms = True, 0 # Частоту heartbeat и срок Data lost определяет C, нулевой expiry сохраняет последнее показание. + + def __init__(self, node=11, source_node=1, xdi_net=True, self_start=True, dam_pdo=2, bindings=None, dimmer_group=1): # Сохраняет существующий Python API модели SLAVE. + if any(type(value) is not int for value in (node, source_node, dam_pdo, dimmer_group)): # Порт проверяет типы до преобразования unsigned ABI. + raise ValueError("Параметры профиля DEIF должны быть целыми") # Логические и дробные адреса не превращаются в другой узел. + super().__init__(source="Локальная симуляция", device_node=node, bindings=bindings, source_node=source_node, xdi_net=xdi_net, self_start=self_start, dam_pdo=dam_pdo, dimmer_group=dimmer_group) # Все ограничения и исходные привязки создаются C-ядром. + + def start(self, now=None, reset_values=True): # Явное включение не использует физический транспорт напрямую. + self._sync_bindings() # Последние параметры UI должны соответствовать создаваемому сеансу. + self._api.start(self._context, _milliseconds(monotonic() if now is None else now), bool(reset_values)) # Boot-up и self-start формируются общим автоматом C. + + def stop(self): # Выключение прекращает в том числе невыданные служебные события. + self._api.stop(self._context) # Никакого отдельного Python-таймера heartbeat здесь нет. + + def accept(self, source, identifier, data, extended=False, rtr=False, now=None): # Транспортное имя фильтруется базовым портом, байты принимает C. + return super().accept(source, identifier, data, extended, rtr, monotonic() if now is None else now) # Явные часы позволяют одинаково проверять границы Python и JNI. + + def tick(self, now=None): # Порт регулярно выгружает готовые события и передаёт их выбранному транспорту. + from .can_transport import build_frame # Формат транспорта не смешивается с форматом DEIF. + self._sync_bindings() # Прямое изменение профиля не должно оставлять старые привязки. + output = (Frame * 16)() # Вместимость соответствует ограниченному пакету событий публичного ABI. + count = self._api.poll(self._context, _milliseconds(monotonic() if now is None else now), output, len(output)) # Все сроки и NMT-переходы обслуживаются C. + return [build_frame(frame.can_id, bytes(frame.data[:frame.dlc]), ide=False) for frame in output[:count]] # Python меняет только тип контейнера готовых кадров. + + def lost_fields(self, now=None): # Локализованный список строится поверх готовой маски C. + self._sync_bindings() # Непривязанное поле не должно участвовать в предупреждении. + mask = self._api.lost(self._context, _milliseconds(monotonic() if now is None else now)) # Независимые сроки по 3000 мс определяются общим ядром. + return [key for index, key in enumerate(FIELDS) if mask & (1 << index)] # Соответствие field ID и имени не повторяет алгоритм свежести. + + def _meta(self): # Набор скаляров не раскрывает внутреннюю структуру C. + output = (C.c_int64 * 10)() # Число элементов закреплено в deif_xdi.h. + self._api.meta(self._context, output) # Состояние хранится только в одном месте. + return list(output) # Python-порт не пересчитывает NMT или периоды. + + active = property(lambda self: bool(self._meta()[0])) # Флаг нужен жизненному циклу страницы. + state = property(lambda self: self._meta()[1]) # Готовый CANopen NMT-код используется в локализованной подписи. + started = property(lambda self: self._meta()[2] / 1000) # Секунды сохраняют совместимость прежнего Python API. + last_heartbeat = property(lambda self: self._meta()[3] / 1000) # Преобразуется только единица системного времени. + heartbeat_ms = property(lambda self: self._meta()[4]) # Значение стандартного объекта 0x1017 выдаёт C. + accepted = property(lambda self: self._meta()[5]) # Счётчик принятия не имитируется количеством тиков GUI. + brightness = property(lambda self: self._meta()[7]) # Текущий процент подсветки из C-профиля. + palette = property(lambda self: self._meta()[8]) # Day/Night/Dusk хранится как код общего ядра. + invalid = property(lambda self: {key: STATUS[item[2]] for key, item in self._snapshots().items() if item[2]}) # Только текст статуса локализуется в Python. diff --git a/python/set_devices/deif_xdi.py b/python/set_devices/deif_xdi.py index 97733cd..74bbe56 100644 --- a/python/set_devices/deif_xdi.py +++ b/python/set_devices/deif_xdi.py @@ -1,159 +1,97 @@ -"""DEIF XDi-192 observations from CAN analysis dated 2026-10-03. +"""Локализованное представление DEIF поверх единственного C99-кодека templates.""" # Wire-формат, адресация и диапазоны не реализуются повторно в Python. +import ctypes as C # Преобразуются только структуры публичного ABI. +from protocan import protocan as pc # Существующие CAN-мониторы получают прежний тип Decoded. +from .deif_native import get_deif_native, Frame # C-каталог и готовые метаданные используются без Qt. -Based on DEIF 4189350066D, sections 3.2, 11 and appendix 9. -Angle and AC2 percent use the verified working-library resolution of 0.1. -Absolute AC2 power remains RAW until its physical unit is confirmed. -""" -from protocan import protocan as pc - -SELECTORS = { - bytes.fromhex("01 01 30 07"): "Азимут / руль — задание", - bytes.fromhex("01 81 30 02"): "RPM / обороты", - bytes.fromhex("01 91 30 02"): "Обороты винта, %", - bytes.fromhex("01 21 34 02"): "Электрическая мощность AC2", - bytes.fromhex("01 31 34 02"): "Электрическая мощность AC2, %", -} -MASTER_SELECTORS = tuple(SELECTORS) -SELECTORS[bytes.fromhex("01 01 30 02")] = "Азимут / руль — фактическое значение" - -OBJECTS = { - 0x3000: ("Азимут / руль", "°"), - 0x3080: ("Обороты винта", "rpm"), - 0x3090: ("Обороты винта, %", "%"), - 0x3420: ("Электрическая мощность AC2", None), - 0x3430: ("Электрическая мощность AC2, %", "%"), -} +_API = get_deif_native() # Отсутствие общего DEIF-ядра является явной ошибкой нативной сборки. +_FIELD_NAMES = (("Электрическая мощность AC2", None), ("Обороты винта", "rpm"), ("Азимут / руль", "°"), ("Электрическая мощность AC2, %", "%"), ("Обороты винта, %", "%"), ("Азимут / руль", "°")) # Это только локализованные подписи, числовые объекты определяет C-каталог. +_MASTER_FIELDS = (5, 1, 4, 0, 3) # Соответствие прежнего порядка редакторов ID полей ABI; сборку цикла выполняет C. +MASTER_SELECTORS = tuple(_API.selector_bytes(field, 1) for field in _MASTER_FIELDS) # Селекторы возвращает единый C-каталог. +SELECTORS = dict(zip(MASTER_SELECTORS, ("Азимут / руль — задание", "RPM / обороты", "Обороты винта, %", "Электрическая мощность AC2", "Электрическая мощность AC2, %"))) # Тексты не влияют на проверку или отправку кадра. +SELECTORS[_API.selector_bytes(2, 1)] = "Азимут / руль — фактическое значение" # Фактический угол имеет отдельный объект каталога. +OBJECTS = {} # Сохраняет публичное представление названий семейств для прежних потребителей. +for _field in range(5): # Пять семейств поддерживаемого профиля индикации. + _metadata = (C.c_int32 * 3)() # C возвращает base, subindex и разрешение. + _API.catalog(_field, _metadata) # Базовый индекс не дублируется числовой таблицей Python. + OBJECTS[_metadata[0]] = _FIELD_NAMES[_field] # Имена остаются локализованными данными представления. -def decode(frame): - result = pc.Decoded(pc.ProtoCanId(frame.can_id, 0, 0, 0, 0, 0, 0), - len(frame.data), bytes(frame.data), ide=frame.ide, - rtr=frame.rtr, protocol="DEIF XDi-192") - result.fields = [("Протокол", "DEIF XDi-net / CANopen SAM-MPDO"), - ("CAN ID", "0x%03X" % frame.can_id)] - def reject(message): - result.summary = message - result.warnings.append(message) - return result - if frame.ide or frame.rtr: - return reject("DEIF: ожидается STD data frame; EXT/RTR не интерпретируется") - if 0x701 <= frame.can_id <= 0x77F: - node = frame.can_id - 0x700 - result.device_label = "Node %d" % node - result.message_label = "Heartbeat / Boot-up" - result.fields.append(("Node-ID", str(node))) - if len(frame.data) != 1: - return reject("DEIF: Heartbeat Node %d — ожидается DLC=1" % node) - state = {0: "Boot-up", 5: "Operational"}.get(frame.data[0]) - if state is None: - state = "состояние 0x%02X (не описано в журнале)" % frame.data[0] - result.fields.append(("Состояние", state)) - result.summary = "Node %d: %s" % (node, state) - return result - if not 0x201 <= frame.can_id <= 0x57F: - result.summary = "DEIF: CAN ID не описан в журнале" - return result - node = frame.can_id - 0x200 - result.message_label = "XDi-net broadcast / SAM-MPDO" - result.fields.append(("COB-ID", "0x%03X" % frame.can_id)) - if len(frame.data) != 8: - return reject("DEIF RPDO1: ожидается DLC=8") - selector = frame.data[:4] - result.fields.append(("Селектор Byte0..3", selector.hex(" ").upper())) - source = frame.data[0] & 0x7F - index = int.from_bytes(frame.data[1:3], "little") - subindex = frame.data[3] - result.fields.extend([("Источник Node-ID", str(source)), - ("Индекс объекта", "0x%04X" % index), - ("Подиндекс", "0x%02X" % subindex)]) - dam = bool(frame.data[0] & 0x80) - if dam: - result.fields = [(key, value) for key, value in result.fields if key != "Источник Node-ID"] - result.fields.append(("Получатель Node-ID", str(source))) - result.message_label = "CANopen DAM-MPDO" - if not source or frame.can_id - source not in (0x200, 0x300, 0x400, 0x500): - return reject("DEIF: получатель не соответствует RPDO COB-ID") - elif not source or not 0x201 <= frame.can_id <= 0x27F or (node != 127 and source != node): - return reject("DEIF: источник не соответствует COB-ID") - result.device_label = ("Получатель Node %d" if dam else "Источник Node %d") % source - result.fields[0] = ("Протокол", "CANopen DAM-MPDO" if dam else "DEIF XDi-net / CANopen SAM-MPDO") - family, instance = index & 0xFFF0, index & 0xF - if family not in OBJECTS or not instance or subindex not in (2, 7): - return reject("DEIF: неизвестный объект/подиндекс 0x%04X:%02X" % (index, subindex)) - name, unit = OBJECTS[family] - kind = "фактическое значение" if subindex == 2 else "задание" - name = "%s №%d — %s" % (name, instance, kind) - raw = int.from_bytes(frame.data[4:6], "little", signed=True) - result.fields.extend([("Параметр", name), - ("RAW INT16 LE", str(raw)), - ("Byte6..7", frame.data[6:].hex(" ").upper())]) - result.summary = "Node %d · 0x%04X:%02X · %s: RAW=%d" % (source, index, subindex, name, raw) - if raw in (-32768, 32766, 32767): - status = {-32768: "ниже диапазона", 32766: "выше диапазона", 32767: "ошибка данных"}[raw] - result.fields.append(("Статус", status)) - result.summary += "; " + status - result.warnings.append(status) - elif unit and (subindex == 2 or family == 0x3000): - value = "%.1f %s" % (raw / 10, unit) - result.fields.append(("Значение", value)) - result.fields.append(("Масштаб", "RAW ×0.1")) - result.summary += "; " + value - elif family == 0x3420 and subindex == 2: - result.fields.append(("Масштаб / единицы", "RAW ×1; физическая единица не подтверждена")) - result.summary += "; RAW ×1 (физическая единица не подтверждена)" - else: - result.fields.append(("Масштаб / единицы", "не установлены")) - result.summary += "; масштаб и единицы не установлены" - if frame.data[6:] != b"\x00\x00": - result.warnings.append("Byte6..7: для I16 ожидается нулевое заполнение") - return result +def decode(frame): # Форматирует готовый результат C для обеих таблиц Desktop. + result = pc.Decoded(pc.ProtoCanId(frame.can_id, 0, 0, 0, 0, 0, 0), len(frame.data), bytes(frame.data), ide=frame.ide, rtr=frame.rtr, protocol="DEIF XDi-192") # Контейнер совместим со штатным монитором CAN. + result.fields = [("Протокол", "DEIF XDi-net / CANopen SAM-MPDO"), ("CAN ID", "0x%03X" % frame.can_id)] # Начальные подписи не зависят от структуры wire-полей. + code, metadata = _API.inspect_frame(frame.can_id, frame.data, frame.ide, frame.rtr) # Единственный разбор сообщения выполняется в C. + node, index, subindex, raw, field, instance, status, dam, padding, nmt = metadata[1:11] # Это поля документированного ABI, не смещения CAN-payload. + if code in (2, -2, -3): # C определяет принадлежность к CANopen Heartbeat/Boot-up. + result.device_label, result.message_label = "Node %d" % node, "Heartbeat / Boot-up" # Исходный тип пригоден также для ошибки DLC. + result.fields.append(("Node-ID", str(node))) # Номер уже вычислен общим кодеком. + if code != -2: # При корректной длине сохраняется исходный NMT-код, включая неизвестный. + states = {0: ("Boot-up", "запуск узла"), 4: ("Stopped", "узел остановлен"), 5: ("Operational", "рабочий режим"), 127: ("Pre-operational", "предоперационный режим")} # Локализация кодов состояния; допустимость уже проверена C. + state, meaning = states.get(nmt, ("состояние 0x%02X" % nmt, "неизвестное состояние NMT")) # Неизвестный байт не теряется в представлении. + message = "Boot-up" if nmt == 0 else "Heartbeat" if code == 2 else "Error control" # Подтверждённый тип heartbeat сообщает C-декодер. + result.message_label = "CANopen " + message # Отдельный тип исключает Boot-up из статистики периода HB. + result.fields[0] = ("Протокол", result.message_label) # Служебный кадр не маркируется как SAM-MPDO. + result.fields.extend([("COB-ID", "0x%03X = 0x700 + %d" % (frame.can_id, node)), ("NMT state", "0x%02X (%d)" % (nmt, nmt)), ("Состояние", "%s — %s" % (state, meaning))]) # Формулы выводятся для пояснения пользователю, а не для декодирования. + result.summary = "%s · Node %d: %s — %s" % (message, node, state, meaning) # Сводка остаётся полезной при скрытой колонке типа. + return result # Heartbeat не трактуется как измерение. + errors = {-1: "DEIF: ожидается STD data frame; EXT/RTR не интерпретируется", -2: "DEIF: Heartbeat Node %d — ожидается DLC=1" % node, -4: "DEIF RPDO1: ожидается DLC=8", -5: "DEIF: источник или получатель не соответствует COB-ID", -6: "DEIF: неизвестный объект/подиндекс 0x%04X:%02X" % (index, subindex)} # Причины задаёт C, здесь находятся только русские тексты. + if code in errors: # Неуспешный разбор не получает фиктивных RAW-полей. + result.summary = errors[code] # Понятная причина отказа видна в таблице без открытия подробностей. + result.warnings.append(result.summary) # Сохраняет существующий API диагностики. + return result # Порт не пытается повторно угадать формат байтов. + if code == 0: # COB-ID другого протокола не считается измерением DEIF. + result.summary = "DEIF: CAN ID не описан в журнале" # Исходный кадр сохраняется в raw-колонках монитора. + return result # Неизвестному ID не назначаются физические единицы. + result.message_label = "CANopen DAM-MPDO" if dam else "XDi-net broadcast / SAM-MPDO" # Режим уже определён общей проверкой адресации. + result.fields[0] = ("Протокол", "CANopen DAM-MPDO" if dam else "DEIF XDi-net / CANopen SAM-MPDO") # В подробностях показывается действующий режим. + result.device_label = ("Получатель Node %d" if dam else "Источник Node %d") % node # Node-ID получателя не подписывается источником SAM. + result.fields.extend([("COB-ID", "0x%03X" % frame.can_id), ("Селектор Byte0..3", bytes(frame.data[:4]).hex(" ").upper()), ("Получатель Node-ID" if dam else "Источник Node-ID", str(node)), ("Индекс объекта", "0x%04X" % index), ("Подиндекс", "0x%02X" % subindex)]) # Raw-байты показываются для проверки, алгоритм их не интерпретирует. + if code == 3: # C отделяет U8 диммера от переменных I16. + result.summary = "Node %d · 0x%04X:%02X · %s: %d" % (node, index, subindex, "Яркость, %" if field == 6 else "Color Day/Night/Dusk", raw) # Сохраняет понятную сводку команд подсветки. + return result # Диммер не получает ложный масштаб десятых долей RPM. + name, unit = _FIELD_NAMES[field] # Название выбирается по готовому field ID общего каталога. + kind = "фактическое значение" if subindex == 2 else "задание" # Тип значения показывается пользователю отдельно от физического числа. + parameter = "%s №%d — %s" % (name, instance, kind) # Номер экземпляра поступает из C-декодера. + result.fields.extend([("Параметр", parameter), ("RAW INT16 LE", str(raw)), ("Byte6..7", bytes(frame.data[6:]).hex(" ").upper())]) # Для диагностики сохраняется исходное значение и raw-хвост. + result.summary = "Node %d · 0x%04X:%02X · %s: RAW=%d" % (node, index, subindex, parameter, raw) # Формат совместим с прежними фильтрами и тестами. + if status: # Зарезервированный I16 проверен единственным C-кодеком. + text = {1: "ниже диапазона", 2: "выше диапазона", 3: "ошибка данных"}[status] # Статус локализуется без повторного сравнения raw-кодов. + result.fields.append(("Статус", text)) # Ошибка не выдаётся за огромную физическую величину. + result.warnings.append(text) # Сохраняет предупреждение для таблицы монитора. + result.summary += "; " + text # Причина видна без отдельного окна. + elif unit and (subindex == 2 or field == 2): # Физическое форматирование подтверждено для факта и азимутального задания рабочей библиотеки. + text = "%.1f %s" % (raw / 10, unit) # Это форматирование числа для человека, принятие и масштаб индикаторов выполняет C. + result.fields.extend([("Значение", text), ("Масштаб", "RAW ×0.1")]) # Подпись раскрывает используемое разрешение. + result.summary += "; " + text # Краткая сводка содержит единицу измерения. + elif field == 0 and subindex == 2: # Абсолютная POWER не имеет подтверждённой физической единицы. + result.fields.append(("Масштаб / единицы", "RAW ×1; физическая единица не подтверждена")) # Единица не достраивается по предположению. + result.summary += "; RAW ×1 (физическая единица не подтверждена)" # Сохраняет прежний смысл шкалы мощности. + else: # Разрешение иных set-point зависит от библиотеки прибора. + result.fields.append(("Масштаб / единицы", "не установлены")) # Неизвестный масштаб остаётся явным ограничением. + result.summary += "; масштаб и единицы не установлены" # Не назначает единицы неизвестному объекту. + if not padding: # C уже проверил старшие байты I16. + result.warnings.append("Byte6..7: для I16 ожидается нулевое заполнение") # Ненулевой хвост виден в диагностике и отклоняется моделью приёма. + return result # На выходе находится только представление результата C. -def master_frames(node_id, raw_values, can_id=None, mode="sam", angle_subindex=7): - """Build a five-parameter STD RPDO1 cycle, using signed INT16 LE values.""" - from .can_transport import build_frame - if not isinstance(node_id, int) or not 1 <= node_id <= 127: - raise ValueError("Node-ID должен быть от 1 до 127") - identifier = 0x200 + node_id if can_id is None else can_id - if mode not in ("sam", "dam"): - raise ValueError("Выберите SAM или DAM") - if angle_subindex not in (2, 7): - raise ValueError("Угол: 0x02 — фактический, 0x07 — задание") - if not isinstance(identifier, int) or not 0x201 <= identifier <= 0x57F: - raise ValueError("STD ID вне диапазона RPDO") - if mode == "sam" and identifier not in (0x200 + node_id, 0x27F): - raise ValueError("XDi-net STD ID: 0x200 + источник или 0x27F") - if mode == "dam" and identifier - node_id not in (0x200, 0x300, 0x400, 0x500): - raise ValueError("CANopen DAM: STD ID = база RPDO (200/300/400/500 hex) + получатель") - values = list(raw_values) - if len(values) != len(MASTER_SELECTORS): - raise ValueError("Нужны пять RAW-параметров") - frames = [] - for selector, value in zip(MASTER_SELECTORS, values): - if selector[1:] == bytes.fromhex("01 30 07"): - selector = selector[:3] + bytes([angle_subindex]) - if not isinstance(value, int) or not -32768 <= value <= 32767: - raise ValueError("RAW должен быть INT16: -32768…32767") - data = bytes([node_id | (0x80 if mode == "dam" else 0)]) + selector[1:] + value.to_bytes(2, "little", signed=True) + b"\x00\x00" - frames.append(build_frame(identifier, data, ide=False)) - return frames +def master_frames(node_id, raw_values, can_id=None, mode="sam", angle_subindex=7): # Совместимый API генерирует полный цикл через C. + from .can_transport import build_frame # Транспортный контейнер не задаёт правила DEIF. + values = list(raw_values) # Порт материализует входной iterable для фиксированного ABI. + if mode not in ("sam", "dam") or type(node_id) is not int or not 0 <= node_id <= 127 or len(values) != 5 or any(type(value) is not int or not -2147483648 <= value <= 2147483647 for value in values) or (can_id is not None and (type(can_id) is not int or not 0 < can_id <= 0x1FFFFFFF)): # Проверяются только представимость ABI и число аргументов цикла. + raise ValueError("DEIF: неверный Node-ID, режим, CAN ID или пять RAW-параметров") # Значения не усекаются ctypes незаметно. + source, output = (C.c_int32 * 5)(*values), (Frame * 5)() # Оба буфера имеют явный размер и принадлежат Python. + if _API.master(node_id, source, 0 if can_id is None else can_id, mode == "dam", angle_subindex, output) != 5: # Порядок объектов, I16 и адресацию проверяет общий C-код. + raise ValueError("DEIF: Node-ID, RPDO, подиндекс азимута или RAW вне диапазона") # Частично собранный цикл не передаётся. + return [build_frame(item.can_id, bytes(item.data[:item.dlc]), ide=False) for item in output] # Транспорт получает готовые wire-байты. -# Display binding catalogue. None means library-dependent resolution, not degrees/%. -DISPLAY_PRESETS = { - "power": ("POWER · AC2 (RAW)", 0x3420, 2, None), - "rpm": ("RPM · обороты (×0.1)", 0x3080, 2, 0.1), - "angle": ("Угол · задание (×0.1°)", 0x3000, 7, 0.1), - "angle_actual": ("Угол · фактический (×0.1°)", 0x3000, 2, 0.1), - "power_percent": ("POWER% · AC2 (×0.1%)", 0x3430, 2, 0.1), - "rpm_percent": ("RPM% (×0.1)", 0x3090, 2, 0.1), -} +_PRESET_FIELDS = {"power": 0, "rpm": 1, "angle": 5, "angle_actual": 2, "power_percent": 3, "rpm_percent": 4} # Совместимые имена редакторов связываются с field ID ABI. +_PRESET_NAMES = {"power": "POWER · AC2 (RAW)", "rpm": "RPM · обороты (×0.1)", "angle": "Угол · задание (×0.1°)", "angle_actual": "Угол · фактический (×0.1°)", "power_percent": "POWER% · AC2 (×0.1%)", "rpm_percent": "RPM% (×0.1)"} # Подписи относятся только к представлению. +DISPLAY_PRESETS = {} # Числовые индексы не дублируются таблицей Python. +for _key, _field in _PRESET_FIELDS.items(): # Значения каталога читаются из C при загрузке расширения. + _metadata = (C.c_int32 * 3)() # Публичный ABI выдаёт base/subindex/resolution. + _API.catalog(_field, _metadata) # Общая библиотека является источником объекта и разрешения. + DISPLAY_PRESETS[_key] = (_PRESET_NAMES[_key], _metadata[0], _metadata[1], None if _metadata[2] == 127 else 10.0 ** _metadata[2]) # Конвертация показателя степени нужна только существующему редактору коэффициента. -def display_preset(key, node, instance=1, dam=False): - """Return a catalogue selector and its known scale, or None for RAW.""" - if not 1 <= node <= 127 or not 1 <= instance <= 15: - raise ValueError("Node-ID: 1…127; instance: 1…15") - _, base, subindex, scale = DISPLAY_PRESETS[key] - selector = bytes([node | (0x80 if dam else 0)]) + (base + instance).to_bytes(2, "little") + bytes([subindex]) - return selector.hex(" ").upper(), scale +def display_preset(key, node, instance=1, dam=False): # Сохраняет прежний API выбора библиотечного объекта. + return _API.selector_bytes(_PRESET_FIELDS[key], node, instance, dam).hex(" ").upper(), DISPLAY_PRESETS[key][3] # Ни endian, ни арифметика индексов не повторяются в Python. diff --git a/python/set_devices/emulator_protocol.py b/python/set_devices/emulator_protocol.py new file mode 100644 index 0000000..ec56afb --- /dev/null +++ b/python/set_devices/emulator_protocol.py @@ -0,0 +1,140 @@ +"""SET v2/RTU session for emulator panels; no I/O or Qt dependencies. + +Only discovery may fall back to RTU. An application command is sent once; +failure after choosing v2 must never resend a write using another protocol. +""" +import secrets +import struct + +from setprotocol.core import (Frame, FrameFlag, FrameParser, MessageType, Status, + DeviceInfo, build_frame, decode_response) +from set_devices.tms_terminal import crc16_modbus +from set_devices.mcu_profiles import EMULATOR_PROFILES # Проверка DeviceInfo использует модель конкретной платы из общего аппаратного профиля. + +REG_REQUEST = 0x1000 +TMS_REQUEST = 0x1001 +WAVE_BLOCK = 0x1002 +MODEL = 'STM32F407-EMU-EXPERIMENT' + + +def with_crc(body): + return body + struct.pack('= 9 and raw[1] == 16: + return self._frame(WAVE_BLOCK, raw, raw[0]) + if len(raw) == 8 and raw[1] in (3, 6): + unit, fn, address, value = struct.unpack('>BBHH', raw[:6]) + return self._frame(REG_REQUEST, struct.pack('HH', raw[2:6]): + raise ValueError('SET v2: неверное подтверждение записи') + return raw + return with_crc(bytes([raw[0], 3, count * 2]) + struct.pack(f'>{count}H', *words)) diff --git a/python/set_devices/mcu_profiles.py b/python/set_devices/mcu_profiles.py new file mode 100644 index 0000000..ff7f2d9 --- /dev/null +++ b/python/set_devices/mcu_profiles.py @@ -0,0 +1,46 @@ +TEMPLATE_MCUS = { # Каталог отражает конкретные MCU-порты закреплённого templates; значения загрузчиков совпадают с FirmwareTab. + "stm32": ( # Порядок сохраняет прежние F103/F407 и группирует добавленные варианты по семействам. + ("STM32F103C8T6", "DS18B20, CAN Sensor, RS-485 Boot, Firmware Info и LED Indicator.", 2), # Порты ds18b20/stm32f1 и rs485-boot/stm32f103 используют имеющийся UART ROM Boot, индекс 2. + ("STM32F407", "STM32F407VET6: SETProtocol, DevBoard V1, эмуляторы, генератор ЦАП, Parallel NAND и USB Boot.", 7), # Порты set-protocol/stm32f407-* и parallel-nand/stm32f407ve; индекс 7 относится только к USB-загрузчику F407. + ("STM32F103RCT6", "Parallel NAND через GPIO, SETProtocol, DS18B20, Firmware Info и LED Indicator.", None), # Отдельный порт parallel-nand/stm32f103rc учитывает отсутствие FSMC в корпусе LQFP64; None открывает обзор MCU. + ("STM32F103ZET6", "Parallel NAND через FSMC, SETProtocol, эмуляторы УМП / 2812 / IGBT / ЦАП / DEIF, DS18B20, Firmware Info и LED Indicator.", None), # Порт parallel-nand/stm32f103ze использует аппаратный FSMC, поэтому вариант показан отдельно от RCT6. + ("STM32G431", "DS18B20 / 1-Wire, Firmware Info и LED Indicator.", None), # Поддержка задана конфигурацией ds18b20/stm32g4/onewire_config.g431.template.h и общими портами G4. + ("STM32G474", "SETProtocol, DS18B20 / 1-Wire, Firmware Info, LED Indicator и генератор ЦАП.", None), # Общие порты stm32g4 и set-protocol/stm32g474-wavegen подходят семейству; конкретные платы перечислены ниже. + ("STM32G474CEU6", "Parallel NAND через GPIO, DS18B20 / 1-Wire, Firmware Info и LED Indicator.", None), # Порт parallel-nand/stm32g474ce предназначен для корпуса UFQFPN-48. + ("STM32G474RB", "SETProtocol, периферийный эмулятор, генератор ЦАП и порт USB Boot в templates.", None), # Порты set-protocol/stm32g474-periph и stm32g474-usb-boot описывают RB; USB-клиент F407 не назначается этому MCU. + ("STM32G474VET6", "HOPE: эмуляторы УМП / 2812 / IGBT / ЦАП / DEIF; CANdle CAN / UART BOOT, STM Invertor, DS18B20 / 1-Wire.", None), # CAN_BOOTLOADER_G474.md проекта CANdle подтверждает BOOT именно VET6, отдельно от USB BOOT платы RB. + ), # Завершаем список STM32 без автоматического поиска каталогов, недоступных внутри собранного EXE. + "k1921": ( # К1921 использует те же общие инструменты SETProtocol, что описаны в PROJECT_RELATIONS.md. + ("K1921VK028", "RTC Service, Firmware Info и обмен SETProtocol через UART.", None), # Источники возможностей — rtc-service/k1921vk028, firmware-info/k1921vk028 и транспорт приложения. + ), # Единственный конкретный MCU этого семейства в текущем templates. +} # Чистые данные не создают Qt-виджеты и сохраняют отложенное построение платформ. + +EMULATOR_MODES = { # Номера режимов совпадают с config[3] общего set_emu_server и не зависят от MCU. + 0: ("ump", "УМП — логгер и сигналы", "УМП: запись логгера и управление эмуляцией пуска."), # Режим по умолчанию после сброса MCU. + 1: ("tms2812", "2812 — BALZAM_7 / CMD_STD", "2812: пуск, останов и задание частоты через CMD_STD."), # Обмен 2812 использует собственный адрес, обычно 1. + 2: ("igbt", "IGBT / драйвер — Vin / Vstat", "IGBT: после выбора включите эмуляцию в панели драйвера."), # Физические GPIO зависят от платы, сама модель общая. + 3: ("wavegen", "Генератор сигналов — ЦАП / PA4", "ЦАП: загрузите таблицу, затем отдельно нажмите «Пуск ЦАП»."), # Запись таблицы не запускает аппаратный вывод. + 4: ("deif", "DEIF Master — передача CAN", "DEIF Master: настройте профиль и RAW, затем нажмите «Пуск DEIF»."), # Общая C-модель передаёт SAM/DAM через аппаратный CAN выбранного MCU. + 5: ("deif", "DEIF Slave — приём CAN", "DEIF Slave: настройте Node-ID и привязки, затем нажмите «Пуск DEIF»."), # Роль Slave принимает NMT/MPDO и передаёт Boot-up, heartbeat и EMCY. +} # Режим применяется отдельной подтверждаемой транзакцией STM, запуск выполняется в панели модели. +EMULATOR_TOOLS = { # Один набор инструментов используется каждым реализованным аппаратным портом. + "settings": "Настройки STM", # Адрес, скорость и режим читаются и проверяются общим клиентом. + "ump": "УМП", # Логгер и синтетические сигналы используют set_emu_ump. + "tms2812": "2812", # Обмен BALZAM_7 использует set_emu_tms. + "igbt": "IGBT / драйвер", # Логические входы и выходы используют set_emu_igbt. + "wavegen": "Подключение генератора", # Таблица передаётся общему генератору с таймером выбранной платы. + "deif": "DEIF Master / Slave", # Одна панель управляет обеими ролями set_emu_deif. +} # Приложение предоставляет существующие панели и использует общую панель DEIF из templates. +EMULATOR_MENU_TITLE = "Эмуляторы: УМП / 2812 / IGBT / ЦАП / DEIF" # Обзор MCU и общая навигация используют одинаковый список поддержанных моделей. +EMULATOR_PROFILES = { # Каталог содержит платы с реальной прошивкой stm32-emulator; дополнительные порты подключаются здесь. + "STM32F407": {"title": "STM32F407VET6", "timer_hz": 72_000_000, "sample_max": 1_000_000, "settings": "stm_ump", "model": "STM32F407-EMU-EXPERIMENT", "igbt_inputs": tuple("PB%d" % pin for pin in range(8)), "igbt_gpio": True, "wave_port": "stm32f407-periph", "tools": tuple(EMULATOR_TOOLS)}, # TIM6 72 МГц и прежний ключ stm_ump сохраняют совместимость F407. + "STM32F103ZET6": {"title": "STM32F103ZET6", "timer_hz": 72_000_000, "sample_max": 1_000_000, "settings": "stm_emulator/STM32F103ZET6", "model": "STM32F103ZE-EMU-EXPERIMENT", "igbt_inputs": ("PB0", "PB1", "PB2", "PB10", "PB11", "PB12", "PB13", "PB14"), "igbt_gpio": True, "wave_port": "stm32f103-periph", "tools": tuple(EMULATOR_TOOLS)}, # High-density F103ZE имеет DAC/TIM6 72 МГц, UART/GAS и bxCAN; малые F103 без DAC не объявляются совместимыми автоматически. + "STM32G474RB": {"title": "STM32G474RB", "timer_hz": 160_000_000, "sample_max": 1_000_000, "settings": "stm_emulator/STM32G474RB", "model": "STM32G474RB-EMU-EXPERIMENT", "igbt_inputs": ("PB0", "PB1", "PB2", "PB10", "PB11", "PB12", "PB13", "PB14"), "igbt_gpio": True, "wave_port": "stm32g474-periph", "tools": tuple(EMULATOR_TOOLS)}, # RB использует свой USB BOOT, FDCAN и TIM6 160 МГц. + "STM32G474VET6": {"title": "HOPE STM32G474VET6", "timer_hz": 160_000_000, "sample_max": 1_000_000, "settings": "stm_emulator/STM32G474VET6", "model": "STM32G474VE-HOPE-EMU", "igbt_inputs": ("PB0", "PB1", "PB2", "PB10", "PB11", "PB12", "PB13", "PB14"), "igbt_gpio": False, "wave_port": "stm32g474-periph", "tools": tuple(EMULATOR_TOOLS)}, # HOPE подтверждает собственную USB-модель, USART1 PA9/PA10 и CAN1 PD0/PD1; GPIO IGBT отключены из-за CAN2 на PB12/PB13. +} # Модели общие, а идентичность, GPIO, частоты и сохранённое подключение принадлежат выбранной плате. +CANDLE_G474_BOOT = { # Профиль воспроизводит CAN_BOOTLOADER_G474.md и boot_profile.h проекта CANdle_stm32. + "app_base": 0x08008000, "app_size": 480 * 1024, # Начальные 32 КиБ из 512 КиБ Flash заняты BOOT; приложение занимает оставшиеся 480 КиБ. + "stack_base": 0x20000000, "stack_end": 0x20014000, # Валидатор pcan_boot_stm32g474.c проекта CANdle принимает начальный MSP только внутри используемых linker-скриптом 80 КиБ SRAM. + "device_type": 7, "device": 15, "product": 0, "hardware": 0, # Идентичность ProtoCAN BOOT: Type 7, Device 15, Product 0 и аппаратная ревизия 0. + "can_bitrate": 500_000, "uart_baud": 512_000, # Classic CAN работает на 500 кбит/с, USART1 PA9/PA10 — на 512000 бод, 8N1. +} # Адреса и скорости относятся только к CANdle G474VET6 и не подменяют профиль USB BOOT G474RB. diff --git a/python/set_devices/qt_ports/CONSOLE.md b/python/set_devices/qt_ports/CONSOLE.md new file mode 100644 index 0000000..7c32bbf --- /dev/null +++ b/python/set_devices/qt_ports/CONSOLE.md @@ -0,0 +1,68 @@ +# Общая консоль Qt + +`set_devices.qt_ports.console.ConsoleView` — общий порт представления для +журналов SETGUI. Он не управляет портами, опросом и отправкой команд. + +Приложение → `ConsoleView` → Qt 6 / Qt 5. Протокольные декодеры передают +готовые подписи и необязательные исходные байты; консоль не вычисляет CRC. + +| Файл | Назначение и зависимости | +|---|---| +| `set_devices/qt_ports/console.py` | Виджет и файловый экспорт; stdlib и PySide6 либо PySide2 | +| `examples/console_examples.py` | По одному примеру служебной консоли, CAN и RS485; действующие кодеки templates | +| `tests/test_console.py` | Проверки истории, паузы, фильтров, очистки и UTF-8; pytest и Qt | + +## Возможности, собранные из журналов SETGUI + +| Возможность | Источник / поведение общего компонента | +|---|---| +| Очистка | Канальные консоли платы, TX/RX, Modbus; удаляет также скрытые строки и очередь обновления | +| Пауза | Эмуляторы CAN; экран заморожен, история продолжает принимать данные до заданного предела | +| TX/RX | Диагностика и эмуляторы; служебные ошибки без направления остаются видны | +| Автопрокрутка | Мониторы CAN и RS; её можно отключить для чтения истории | +| Цвета | Консоль платы и монитор шины; сохраняются при переразборе фильтра | +| HEX/ASCII | Диагностика RS; формат применяется к явно переданному payload | +| Сохранение | Мониторы CAN и RS; экспорт фактически видимого текста в UTF-8 | +| Поиск, копирование, перенос, масштаб | Общие инструменты всех подключённых текстовых журналов | + +## Подключение + +```python +from set_devices.qt_ports.console import ConsoleView # Подключаем общий порт представления templates. +console = ConsoleView(limit=4000, payloads=True) # Храним не более 4000 строк, включая скрытые и поступившие на паузе. +layout.addWidget(console.panel, 1) # В layout вставляется контейнер с инструментами и редактором. +console.append_message("RX ответ", direction="RX", payload=b"OK") # Передаём готовую подпись и байты без повторного разбора протокола. +console.append_message("Ошибка связи", color="#ff7b7b") # Служебная ошибка остаётся видна при выключенных TX и RX. +console.userCleared.connect(clear_frame_history) # Отдельный буфер кадров очищается тем же пользовательским действием. +``` + +Старые вызовы `appendPlainText`, `appendHtml`, `setPlainText`, `clear`, +`toPlainText` и `setMaximumBlockCount` поддерживаются. `setPlainText` заменяет +снимок истории, учитывая текущую паузу. Для внешней истории кадров подключите +`userCleared`: программный `clear()` повторно этот сигнал не испускает. + +`directions=False` скрывает встроенные флажки, если приложение уже имеет свои +фильтры TX/RX. `payloads=True` показывает форматы HEX/ASCII. События должны +поступать в GUI-потоке Qt, как при работе с обычным `QPlainTextEdit`. + +При заполнении история обновляет экран пачками с интервалом 100 мс. +Количество строк на панели относится ко всей ограниченной истории. +На паузе сохранение и копирование используют замороженный видимый экран. + +## Три запускаемых примера + +Из каталога `python`, с установленными зависимостями `.[qt]`: + +```powershell +python examples/console_examples.py --kind service +python examples/console_examples.py --kind can +python examples/console_examples.py --kind rs485 +``` + +Без `--kind` открываются все три примера. Аппаратура не требуется. +В каждом примере можно проверить очистку, паузу, поиск, TX/RX, экспорт, +копирование, автопрокрутку, перенос и масштаб; в CAN и RS485 — HEX/ASCII. + +Используется в SETGUI: CAN/RS485 и служебная консоль ESP, журналы соединения +и TX/RX, эмуляторы CAN, CAN FD, Modbus, диагностика ПМ35 и ТМС2812, +спектр и логический анализатор Altera. diff --git a/python/set_devices/qt_ports/can_frame_builder.py b/python/set_devices/qt_ports/can_frame_builder.py new file mode 100644 index 0000000..7a1abe4 --- /dev/null +++ b/python/set_devices/qt_ports/can_frame_builder.py @@ -0,0 +1,176 @@ +"""Общие поля конструктора CAN и SETCAN для адаптеров и обоих каналов DevBoard.""" +from PySide6.QtCore import Signal # Сигнал изменений позволяет владельцу сбрасывать готовый кадр без зависимости от транспорта. +from PySide6.QtGui import QFont # Моноширинный шрифт сохраняет читаемость HEX-идентификатора и данных. +from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QFormLayout, QComboBox, QSpinBox, QLineEdit, QLabel # Один набор виджетов определяет форму всех потребителей. +from protocan import protocan as pc # Сборка полей протокола выполняется существующими обёртками общего C-ядра. +from set_devices import can_transport as tr # Проверка CAN ID и разбор HEX используют действующий общий транспорт. + + +DESCRIPTION = "Обычный CAN: задайте ID, DLC и Data. Для сборки ID по полям протокола выберите SETCAN." # Одинаковое пояснение режимов используется во всех панелях. + + +class CanFrameFields(QWidget): # Компонент содержит только ввод кадра; подключение и отправка остаются у владельца. + changed = Signal() # Любое изменение ввода отменяет ранее собранный кадр в соответствующем канале. + + def __init__(self, settings_factory, parent=None): # Редактор SETTINGS передаётся владельцем как визуальный компонент без копирования его реализации. + super().__init__(parent) # Родитель Qt управляет временем жизни всех полей формы. + layout = QVBoxLayout(self) # Единый вертикальный порядок исключает различия между вкладками. + layout.setContentsMargins(0, 0, 0, 0) # Внешние отступы задаёт панель приложения. + self.mode = QComboBox() # Переключатель сохраняет оба набора введённых значений. + self.mode.addItem("Обычный CAN — ID / DLC / Data", "can") # Исходный режим одинаков для всех трёх конструкторов. + self.mode.addItem("SETCAN — поля протокола", "setcan") # Протокольный режим всегда создаёт расширенный идентификатор. + mode_form = QFormLayout() # Первая строка остаётся видимой в обоих режимах. + mode_form.addRow("Режим", self.mode) # Подпись поясняет назначение переключателя. + layout.addLayout(mode_form) # Выбор режима предшествует зависимым полям. + self.can_panel = QWidget() # Контейнер скрывает вместе подписи и редакторы обычного CAN. + can_form = QFormLayout(self.can_panel) # Формат, идентификатор и длина выровнены общей формой. + can_form.setContentsMargins(0, 0, 0, 0) # Поля обоих режимов начинаются на одной вертикали. + self.format = QComboBox() # IDE задаётся явно независимо от численного значения идентификатора. + self.format.addItem("Стандартный — 11 бит (STD)", False) # STD соответствует диапазону CAN ID 0..0x7FF. + self.format.addItem("Расширенный — 29 бит (EXT)", True) # EXT соответствует диапазону CAN ID 0..0x1FFFFFFF. + self.can_id = QLineEdit("123") # Исходный пример идентификатора записан в HEX. + self.can_id.setToolTip("HEX, с префиксом 0x или без него. STD: 0..7FF; EXT: 0..1FFFFFFF.") # Указываем пределы CAN ID без неявного усечения. + self.dlc = QSpinBox() # Пользователь явно задаёт длину обычного CAN-кадра. + self.dlc.setRange(0, 8) # Классический CAN допускает от нуля до восьми байтов Data. + self.dlc.setToolTip("Количество байтов Data должно точно совпадать с DLC; дополнение и обрезка не выполняются.") # Описываем строгую проверку длины. + can_form.addRow("Формат ID (IDE)", self.format) # Формат отражает фактический флаг IDE. + can_form.addRow("CAN ID (HEX)", self.can_id) # Явно обозначаем систему счисления идентификатора. + can_form.addRow("DLC (0..8 байт)", self.dlc) # Длина дана в байтах полезной нагрузки. + layout.addWidget(self.can_panel) # Обычный CAN занимает то же место, что альтернативная форма SETCAN. + self.setcan_panel = QWidget() # Общий контейнер хранит поля составного 29-битного идентификатора. + form = QFormLayout(self.setcan_panel) # Подписи протокола выравниваются с остальными формами. + form.setContentsMargins(0, 0, 0, 0) # Убираем дополнительные внутренние отступы. + self.priority = QComboBox() # Приоритет соответствует старшему полю SETCAN ID. + self.priority.addItems(["0 — критический", "1 — стандартный"]) # Подписи сохраняют существующие значения приоритета протокола. + self.priority.setCurrentIndex(1) # По умолчанию используется стандартный приоритет. + self.route = QComboBox() # Направление отличает запрос мастера от сообщения устройства. + self.route.addItems(["0 — от мастера (PM)", "1 — от устройства"]) # Сохраняем совместимые значения поля ПМ. + self.dtype = QSpinBox() # Тип устройства выбирается отдельно от номера экземпляра. + self.dtype.setRange(0, 7) # Поле Device Type занимает три бита SETCAN ID. + self.dtype.setValue(1) # Сохраняем прежний исходный тип устройства. + self.did = QSpinBox() # Номер устройства задаёт адрес внутри выбранного типа. + self.did.setRange(0, 15) # Поле Device занимает четыре бита SETCAN ID. + self.did.setValue(2) # Сохраняем прежний исходный адрес устройства. + self.mtype = QComboBox() # Тип сообщения определяет подтип и назначение Body. + self.mtype.addItems([item.name for item in pc.MsgType]) # Каталог типов берётся из общего протокольного модуля. + self.mtype.setCurrentText(pc.MsgType.ANALOG.name) # Начальный протокольный пример остаётся аналоговым сообщением. + self.sub = QComboBox() # Набор подтипов меняется вместе с MsgType. + self.arg = QLineEdit("1") # Числовой аргумент поддерживает десятичный ввод и префикс 0x. + self.settings_body = settings_factory() # Используем переданный редактор байтов Z и Y без зависимости от приложения. + self.arg_panel = QWidget() # Альтернативные редакторы аргумента занимают одну строку. + arg_layout = QHBoxLayout(self.arg_panel) # Горизонтальная компоновка сохраняет левое выравнивание SETTINGS. + arg_layout.setContentsMargins(0, 0, 0, 0) # Исключаем сдвиг аргумента относительно остальных редакторов. + arg_layout.addWidget(self.arg) # Обычный аргумент виден для всех типов кроме SETTINGS. + arg_layout.addWidget(self.settings_body) # Два байта SETTINGS заменяют единое поле аргумента. + arg_layout.addStretch(1) # Свободная ширина остаётся справа от редакторов. + self.count = QSpinBox() # RegCount используется протокольными типами Modbus. + self.count.setRange(1, 4) # Два младших бита Body кодируют количество минус один, допустимы 1…4 регистра или бита. + self.count.setValue(1) # Исходный запрос относится к одному регистру. + self.sub_label = QLabel("Подтип") # Подпись уточняется при выборе типа сообщения. + self.arg_label = QLabel("SensorID / адрес") # Назначение аргумента зависит от MsgType. + rows = [("Priority", self.priority), ("ПМ", self.route), ("Device Type (0..7)", self.dtype), ("Device (0..15)", self.did), ("Msg Type", self.mtype), (self.sub_label, self.sub), (self.arg_label, self.arg_panel), ("RegCount (Modbus)", self.count)] # Единый порядок полей исключает расхождение форм. + for label, control in rows: # Все протокольные строки добавляются из одного визуального описания. + form.addRow(label, control) # Подпись связана с соответствующим редактором. + layout.addWidget(self.setcan_panel) # Протокольная форма показывается только в режиме SETCAN. + self.data = QLineEdit() # Полезная нагрузка общая для обоих способов ввода идентификатора. + self.data.setPlaceholderText("01 02 03 04 05 06 07 08") # Пример показывает формат ввода HEX-байтов. + data_form = QFormLayout() # Общая строка Data остаётся видимой при смене режима. + data_form.addRow("Data (HEX, до 8 байт)", self.data) # Указываем ограничение классического CAN. + layout.addLayout(data_form) # Данные завершают форму перед кнопками владельца. + for control in (self.mode, self.data): # Длинные поля получают достаточную ширину в обоих режимах. + control.setMaximumWidth(420) # Предел 420 пикселей сохраняет компактность исходного конструктора. + self.format.setMaximumWidth(340) # Название формата целиком помещается в строке шириной до 340 пикселей. + for control in (self.priority, self.route, self.mtype, self.sub, self.arg, self.can_id): # Одинаковая ширина полей ID задаётся в общем компоненте. + control.setMaximumWidth(220) # Предел 220 пикселей соответствует прежней форме SETCAN. + for control in (self.dtype, self.did, self.count, self.dlc): # Короткие числовые поля не растягиваются по ширине панели. + control.setMaximumWidth(100) # Предел 100 пикселей достаточен для всех допустимых значений. + font = QFont("Consolas", 10) # Шрифт с фиксированной шириной знаков упрощает чтение HEX. + for control in (self.can_id, self.data): # Числовой HEX и полезная нагрузка оформляются одинаково. + control.setFont(font) # Используем один шрифт для всех владельцев компонента. + self._subtype() # Настраиваем первоначальные подписи до вычисления ширины столбца. + labels = [part.labelForField(part.itemAt(row, QFormLayout.ItemRole.FieldRole).widget()) for part in (mode_form, can_form, form, data_form) for row in range(part.rowCount())] # Собираем подписи всех форм для общего выравнивания. + width = max(label.sizeHint().width() for label in labels) # Ширина столбца рассчитывается в пикселях по текущему шрифту Qt. + for label in labels: # Поля обоих режимов должны начинаться в одной позиции. + label.setMinimumWidth(width) # Самая длинная подпись задаёт единый левый столбец. + for container in (self, self.can_panel, self.setcan_panel, self.arg_panel): # Промежуточные контейнеры наследуют фон панели без тёмных полос. + container.setObjectName("canBuilderFields") # Локальный селектор ограничивает правило контейнерами формы. + container.setStyleSheet("QWidget#canBuilderFields { background: transparent; }") # Редакторы сохраняют собственный штатный фон. + self.mode.currentIndexChanged.connect(self._mode_changed) # Переключение режима одновременно меняет видимость и отменяет готовность кадра. + self.mtype.currentIndexChanged.connect(self._subtype) # Новый MsgType обновляет подтипы и редактор Body. + for control in (self.format, self.priority, self.route, self.mtype, self.sub): # Любой выбор из списка меняет будущий кадр. + control.currentIndexChanged.connect(lambda *_: self.changed.emit()) # Отбрасываем индекс Qt, поскольку владельцу нужен только сигнал устаревания результата. + for control in (self.can_id, self.arg, self.data): # Все текстовые поля участвуют в сборке кадра. + control.textChanged.connect(lambda *_: self.changed.emit()) # Отбрасываем текст сигнала Qt и отменяем старый кадр даже при неверном промежуточном вводе. + for control in (self.dlc, self.dtype, self.did, self.count, self.settings_body.z, self.settings_body.y): # Слежение включает оба байта SETTINGS. + control.valueChanged.connect(lambda *_: self.changed.emit()) # Отбрасываем числовой аргумент Qt, сохраняя единый сигнал необходимости новой сборки. + self._mode_changed() # Начальная видимость одинакова у всех потребителей. + + def _mode_changed(self): # Режим определяет только видимость; введённые значения сохраняются. + raw = self.mode.currentData() == "can" # Полный CAN ID вводится только в обычном режиме. + self.can_panel.setVisible(raw) # Показываем формат, ID и DLC для обычного CAN. + self.setcan_panel.setVisible(not raw) # Альтернативно показываем составные поля SETCAN. + self.changed.emit() # Смена способа ввода отменяет ранее собранный кадр. + + def _subtype(self): # Общие подписи и список подтипов используются всеми экземплярами формы. + msg_type = pc.MsgType[self.mtype.currentText()] # Значение выбирается из существующего общего каталога. + settings = msg_type == pc.MsgType.SETTINGS # Только SETTINGS редактируется отдельными байтами Z и Y. + self.arg.setVisible(not settings) # Единый числовой аргумент скрывается для SETTINGS. + self.settings_body.setVisible(settings) # Двухбайтовый редактор появляется вместо числового аргумента. + table = {pc.MsgType.BROADCAST: (pc.BroadcastType, "Broadcast.Type", "Body (0..15)"), pc.MsgType.DISCRETE: (pc.DiscreteType, "Discrete.Type", "Body (0..4095)"), pc.MsgType.ANALOG: (pc.AnalogType, "Analog.Type", "SensorID (0..4095)"), pc.MsgType.MODBUS: (pc.ModbusFunction, "Функция Modbus (1..4)", "StrAdr (0..4095)")} # Для единого Modbus селектор подтипа выбирает функцию Coil/Discrete/Holding/Input. + self.count.setEnabled(msg_type == pc.MsgType.MODBUS) # Количество доступно только для типа, использующего это поле Body. + current = self.sub.currentText() # Сохраняем выбранный подтип, если он допустим для нового сообщения. + self.sub.clear() # Старые варианты не должны остаться в новом типе сообщения. + self.sub.setEnabled(msg_type in table) # Подтип доступен для Broadcast/Discrete/Analog, а у Modbus выбирается функция 1…4. + if msg_type in table: # Подписи и значения перечислений берутся из одного места. + enum, sub_label, arg_label = table[msg_type] # Получаем визуальное описание выбранного MsgType. + self.sub.addItems([item.name for item in enum]) # Значения берутся из общего протокольного каталога. + if current in [item.name for item in enum]: # Совместимый выбор пользователя сохраняется. + self.sub.setCurrentText(current) # Восстанавливаем допустимый подтип после заполнения списка. + else: # Типы без отдельного подтипа используют Body по собственному назначению. + sub_label = "—" # Подпись явно показывает отсутствие подтипа. + arg_label = "Body (обычно 0)" # Для PULSE сохраняем исходное описание аргумента. + if msg_type == pc.MsgType.GENERAL_ADDRESS_SPACE: # GAS использует всё поле Body под адрес. + arg_label = "Адрес регистра (0..65535)" # Полный 16-битный диапазон указан в подписи. + elif msg_type == pc.MsgType.GAS_SLOT: # Новый тип 0x4 использует весь Body под номер слота, а не StrAdr/RegCount. + arg_label = "Адрес слота (0..65535), Data: маска + 3 слова" # Напоминаем оператору о Word0 с маской и фиксированных позициях трёх значений. + elif msg_type == pc.MsgType.ERROR: # Код ошибки вводится в отдельный байт Body. + arg_label = "ErrorCode (0..255)" # Показываем допустимый однобайтовый диапазон. + elif settings: # SETTINGS редактируется двухбайтовым компонентом. + arg_label = "Body: Z | Y" # Подпись соответствует порядку байтов протокола. + self.sub_label.setText(sub_label) # Одинаковая подпись подтипа обновляется во всех вкладках. + self.arg_label.setText(arg_label) # Аргумент всегда подписан по выбранному MsgType. + + def body(self, msg_type, arg, count): # Общая диспетчеризация вызывает существующие обёртки C-ядра без второй реализации wire-кодека. + if msg_type == pc.MsgType.BROADCAST: # BROADCAST объединяет подтип и четырёхбитный аргумент. + return pc.merge_broadcast(pc.BroadcastType[self.sub.currentText()], arg & 0xF) # Маска 0xF сохраняет прежнее ограничение аргумента четырьмя битами. + if msg_type == pc.MsgType.DISCRETE: # Дискретное сообщение использует собственное перечисление подтипов. + return pc.merge_discrete(pc.DiscreteType[self.sub.currentText()], arg) # Поле собирается общим протокольным модулем. + if msg_type == pc.MsgType.ANALOG: # Аналоговое сообщение передаёт SensorID в Body. + return pc.merge_analog(pc.AnalogType[self.sub.currentText()], arg) # Существующий кодек задаёт расположение подтипа и SensorID. + if msg_type == pc.MsgType.MODBUS: # Один MsgType содержит адрес, количество 1…4 и выбранную функцию. + return pc.merge_modbus(arg, count, pc.ModbusFunction[self.sub.currentText()]) # Общий упаковщик проверяет диапазоны и кодирует функцию и количество со смещением на единицу. + if msg_type == pc.MsgType.ERROR: # Сохраняем существующую категорию ошибки с нулевым кодом источника. + return pc.merge_error(0, arg) # Размещение кода ошибки остаётся ответственностью общего ядра. + return arg & 0xFFFF # Остальные типы сохраняют прежнее ограничение Body шестнадцатью битами. + + def frame_values(self): # Возвращаем проверенные параметры CAN без упаковки конкретного транспорта. + data = tr.parse_hex(self.data.text()) # Общий разбор сохраняет поддержку пробелов, запятых и префиксов 0x. + if len(data) > 8: # Классический CAN не допускает более восьми байтов данных. + raise ValueError("данные длиннее 8 байт") # Сообщаем об ошибке до передачи в транспорт. + if self.mode.currentData() == "can": # Обычный режим использует полный идентификатор и явный DLC. + identifier = int(self.can_id.text().strip(), 16) # Поле ID всегда интерпретируется как HEX. + extended = bool(self.format.currentData()) # Малый числовой ID также может иметь выбранный EXT. + tr.validate_can_id(identifier, extended) # Проверка общего транспорта запрещает усечение ID до допустимого диапазона. + if len(data) != self.dlc.value(): # Количество введённых байтов обязано точно совпадать с DLC. + raise ValueError(f"DLC = {self.dlc.value()}, а Data содержит {len(data)} байт; количество байтов должно совпадать.") # Оператор видит обе длины и может исправить ввод. + return identifier, extended, data, None # У обычного CAN нет отдельного протокольного Body. + msg_type = pc.MsgType[self.mtype.currentText()] # SETCAN использует выбранный тип сообщения. + arg = self.settings_body.value() if msg_type == pc.MsgType.SETTINGS else int(self.arg.text().strip() or "0", 0) # SETTINGS читается из Z/Y, остальные аргументы поддерживают привычные числовые префиксы. + body = self.body(msg_type, arg, self.count.value()) # Один путь сборки Body применяется ко всем владельцам формы. + identifier = pc.ProtoCanId.build(self.priority.currentIndex(), self.route.currentIndex(), self.dtype.value(), self.did.value(), msg_type, body) # Идентификатор собирается существующей обёрткой общего C-ядра. + return identifier, True, data, body # SETCAN всегда передаётся с расширенным 29-битным идентификатором. + + def bind(self, owner, prefix): # Сохраняем публичные имена полей приложения при переходе на общий компонент. + names = ("mode", "can_panel", "setcan_panel", "format", "can_id", "dlc", "priority", "route", "dtype", "did", "mtype", "sub", "arg", "settings_body", "count", "data", "sub_label", "arg_label") # Совместимые атрибуты позволяют не менять интеграцию транспорта и внешние потребители. + for name in names: # Каждое старое имя ссылается на настоящий виджет общего компонента. + setattr(owner, prefix + name, getattr(self, name)) # Префиксы build_, builder_ и rs485_builder_ разделяют три независимых состояния. diff --git a/python/set_devices/qt_ports/console.py b/python/set_devices/qt_ports/console.py new file mode 100644 index 0000000..a2efe2b --- /dev/null +++ b/python/set_devices/qt_ports/console.py @@ -0,0 +1,156 @@ +"""Общая консоль Qt: ограниченная история и инструменты просмотра без управления транспортом.""" # Модуль относится к порту представления templates и не реализует протоколы устройств. +from collections import deque # Кольцевая история ограничивает память при непрерывном обмене. +from html import escape # Текст устройства не должен становиться HTML-разметкой журнала. +from pathlib import Path # Экспорт сохраняет явно выбранный пользователем файл в UTF-8. +import re # Метки направления извлекаются только из начала строки после необязательного времени. +try: # Поддерживаем актуальный Qt и существующие установки на Python для Windows 7. + from PySide6.QtCore import QTimer, Signal # Таймер объединяет обновления заполненного журнала. + from PySide6.QtGui import QFont, QTextDocument # Документ извлекает обычный текст из уже оформленных сообщений приложения. + from PySide6.QtWidgets import QApplication, QCheckBox, QComboBox, QFileDialog, QHBoxLayout, QLabel, QLineEdit, QMessageBox, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget # Панель использует только стандартные элементы Qt. +except ImportError: # Старый порт сохраняет тот же публичный интерфейс консоли. + from PySide2.QtCore import QTimer, Signal # В Qt 5 доступны те же сигналы и таймеры. + from PySide2.QtGui import QFont, QTextDocument # Цвета и извлечение текста не зависят от версии Qt. + from PySide2.QtWidgets import QApplication, QCheckBox, QComboBox, QFileDialog, QHBoxLayout, QLabel, QLineEdit, QMessageBox, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget # Состав инструментов одинаков в обоих портах. + + +class ConsoleView(QPlainTextEdit): # Наследование сохраняет привычные appendPlainText, appendHtml и toPlainText у потребителей. + userCleared = Signal() # Владелец отдельной истории может удалить её при явном нажатии «Очистить». + + def __init__(self, parent=None, limit=4000, directions=True, payloads=False): # Предел задан в строках, включая скрытые и поступившие на паузе. + super().__init__(parent) # Владельца редактора впоследствии принимает контейнер panel. + self.records = deque(maxlen=max(1, int(limit))) # Каждая запись хранит текст, оформление, направление и необязательные байты. + self.setReadOnly(True) # Журнал показывает полученные события и не допускает ручной подмены текста. + self.setFont(QFont("Cascadia Mono", 9)) # Моноширинный шрифт выравнивает HEX, адреса и метки времени. + super().setMaximumBlockCount(self.records.maxlen) # Документ ограничен тем же количеством строк, что история. + self.timer = QTimer(self) # Таймер уничтожается вместе с редактором и не переживает закрытие вкладки. + self.timer.setSingleShot(True) # За одну пачку входящих строк достаточно одного полного обновления. + self.timer.setInterval(100) # Интервал 100 мс ограничивает перестроения десятью в секунду при полном буфере. + self.timer.timeout.connect(self.refresh) # Перестроение всегда читает последние записи и текущие фильтры. + self.panel = QWidget(parent) # Контейнер можно вставить в layout или вкладку вместо самого редактора. + layout = QVBoxLayout(self.panel) # Две компактные строки инструментов остаются над областью текста. + layout.setContentsMargins(0, 0, 0, 0) # Внешние отступы задаёт приложение-потребитель. + actions = QHBoxLayout() # Основные операции сгруппированы отдельно от фильтров просмотра. + self.clear_button = QPushButton("Очистить") # Очистка удаляет также скрытую историю и накопленное на паузе. + self.clear_button.clicked.connect(self._user_clear) # Сигнал владельцу позволяет очистить дополнительный буфер кадров. + actions.addWidget(self.clear_button) # Очистка постоянно доступна у левого края консоли. + self.pause = QCheckBox("Пауза") # Пауза замораживает экран, продолжая сохранять входящие сообщения. + actions.addWidget(self.pause) # Пауза относится только к этому экземпляру журнала. + self.follow = QCheckBox("Автопрокрутка") # Прокрутку можно отключить для чтения старых записей. + self.follow.setChecked(True) # По умолчанию новые события видны сразу. + actions.addWidget(self.follow) # Управление расположено рядом с паузой просмотра. + for title, callback in (("Копировать", self.copy_visible), ("Сохранить…", self.save_dialog), ("−", lambda: self.zoomOut(1)), ("+", lambda: self.zoomIn(1))): # Масштаб меняется на один шаг Qt без изменения данных. + button = QPushButton(title) # Кнопки используют тему и шрифт приложения. + button.clicked.connect(callback) # Обработчик вызывается только по явному действию пользователя. + actions.addWidget(button) # Одинаковый порядок действий используется всеми консолями. + actions.addStretch(1) # Свободное место не растягивает подписи инструментов. + layout.addLayout(actions) # Основная строка отделена от параметров отображения. + filters = QHBoxLayout() # Поиск и направления занимают вторую строку для умеренной минимальной ширины. + self.search = QLineEdit() # Фильтр работает по обычному тексту всех сохранённых строк. + self.search.setPlaceholderText("Поиск / фильтр текста") # Подпись показывает, что скрытые строки остаются в истории. + filters.addWidget(self.search, 1) # Поле поиска получает свободную ширину консоли. + self.show_tx, self.show_rx = QCheckBox("TX"), QCheckBox("RX") # Служебные сообщения не относятся ни к одному направлению. + for control in (self.show_tx, self.show_rx): # Оба фильтра действуют независимо и применяются к истории. + control.setChecked(True) # Первое открытие показывает весь обмен. + control.setVisible(directions) # Потребители со своими фильтрами могут скрыть дублирующие элементы. + filters.addWidget(control) # Направления расположены рядом с текстовым фильтром. + self.display = QComboBox() # Формат байтов относится только к сообщениям с явно переданным payload. + self.display.addItems(("Как получено", "HEX", "ASCII", "HEX + ASCII")) # Обычный текст и ответы устройства не перекодируются. + self.display.setToolTip("HEX/ASCII применяется к байтам, переданным через append_message(payload=…).") # Приложение явно определяет границы полезной нагрузки. + self.display.setVisible(payloads) # Выбор байтового представления показывается только потребителю с явным payload. + filters.addWidget(self.display) # Представление можно менять без повторной передачи данных. + self.wrap = QCheckBox("Перенос") # Перенос длинных строк удобен на узких панелях. + filters.addWidget(self.wrap) # Переключатель не изменяет исходный текст при экспорте. + self.count = QLabel() # Счётчик показывает объём ограниченной истории, включая скрытые строки. + filters.addWidget(self.count) # Количество остаётся видно при включённом фильтре. + layout.addLayout(filters) # Параметры находятся непосредственно над текстом. + layout.addWidget(self, 1) # Редактор занимает оставшуюся высоту контейнера. + for control in (self.pause, self.show_tx, self.show_rx, self.follow): # Изменения параметров применяются к уже накопленным данным. + control.toggled.connect(self.refresh) # Снятие паузы показывает сохранённые во время неё события. + self.search.textChanged.connect(self.refresh) # Поиск немедленно обновляет видимую часть истории. + self.display.currentIndexChanged.connect(self.refresh) # Выбор HEX/ASCII заново форматирует сохранённый payload. + self.wrap.toggled.connect(lambda checked: self.setLineWrapMode(QPlainTextEdit.WidgetWidth if checked else QPlainTextEdit.NoWrap)) # Отключённый перенос сохраняет горизонтальную прокрутку. + self.setLineWrapMode(QPlainTextEdit.NoWrap) # Начальный режим совпадает с выключенным флажком переноса. + self.refresh() # Пустой журнал сразу получает корректный счётчик. + + def setMaximumBlockCount(self, limit): # Сохраняем совместимость с существующими настройками журналов SETGUI. + self.records = deque(self.records, maxlen=max(1, int(limit))) # Предел ограничивает и скрытую историю, а не только документ. + super().setMaximumBlockCount(self.records.maxlen) # Согласуем вместимость редактора с кольцевым буфером. + self.refresh() # Уменьшение лимита сразу удаляет вытесненные строки с экрана. + + def append_message(self, text, direction="", color=None, payload=None, _html=None, _defer=False): # Принимаем готовый текст и данные, не выполняя разбор протокола. + for line in str(text).split("\n"): # Многострочные расшифровки также подчиняются общему лимиту строк. + match = re.match(r"^(?:\[[^\]]+\]\s*|\d\d:\d\d:\d\d(?:\.\d+)?\s*)?(TX|RX|>>>)\s", line) # Направление распознаётся только у начальной метки, а не по словам внутри ошибки. + role = direction or (("TX" if match[1] == ">>>" else match[1]) if match else "") # Явная роль имеет приоритет над текстовой эвристикой. + html = _html or ('%s' % (escape(color, quote=True), escape(line)) if color else "") # Безопасное оформление сохраняет исходный текст устройства. + record = (line, html, role, bytes(payload) if payload is not None else None) # Снимок payload не зависит от последующих изменений входного bytearray. + expired = len(self.records) == self.records.maxlen # Вытеснение требует убрать старую строку даже при скрытых новых событиях. + self.records.append(record) # На паузе и под фильтрами данные продолжают сохраняться в пределах лимита. + if not self.pause.isChecked() and not _defer: # Пауза и пакетная замена замораживают документ, но не историю. + if expired or self.timer.isActive(): # Заполненный буфер обновляется пачками для устойчивого интенсивного приёма. + if not self.timer.isActive(): self.timer.start() # Следующие события не отодвигают уже запланированное обновление. + elif self._visible(record): self._append_record(record) # Обычный поток дописывает одну строку без переразбора всей истории. + self.count.setText("%d строк" % len(self.records)) # Счётчик истории обновляется даже при замороженном экране. + + def appendPlainText(self, text): # Старые потребители могут продолжать писать обычный текст. + self.append_message(text) # Ограничения, пауза и фильтры применяются через единый путь записи. + + def appendHtml(self, html): # Прежнее цветное оформление приложения остаётся доступно через API QPlainTextEdit. + document = QTextDocument() # Временный документ преобразует форматированный фрагмент в строки для поиска. + document.setHtml(html) # Разметка поступает от приложения; внешние данные оно должно экранировать. + text = document.toPlainText() # Обычный текст используется для поиска и определения направления. + self.append_message(text, _html=html if "\n" not in text else None) # Однострочное оформление сохраняется без полного обновления истории. + + def setPlainText(self, text): # Снимок внешней истории полностью заменяет данные этого представления. + self.timer.stop() # Старое отложенное обновление не должно вернуть предыдущий снимок. + self.records.clear() # Сохраняется только актуальный результат форматирования потребителя. + if not self.pause.isChecked(): super().clear() # При паузе прежний экран сохраняется до возобновления. + if text: self.append_message(text, _defer=True) # Пустой снимок не создаёт фиктивную запись. + self.refresh() # Поиск и фильтры применяются к новому снимку целиком. + + def clear(self): # Программная очистка удаляет все данные и отменяет ожидающее обновление. + self.timer.stop() # Запланированное обновление больше не требуется. + self.records.clear() # Скрытые записи и накопленное на паузе не должны вернуться. + super().clear() # Явная очистка действует сразу даже при замороженном экране. + self.count.setText("0 строк") # Счётчик согласован с удалённой историей. + + def _user_clear(self): # Только действие оператора уведомляет владельца внешней истории. + self.clear() # Сначала очищаем собственный буфер и видимый документ. + self.userCleared.emit() # Потребитель может безопасно вызвать clear повторно без рекурсивного сигнала. + + def _visible(self, record): # Единое условие применяется при добавлении и полном обновлении. + text, _html, role, _payload = record # Поиск использует исходный текст сообщения независимо от выбранного формата байтов. + return (role != "TX" or self.show_tx.isChecked()) and (role != "RX" or self.show_rx.isChecked()) and self.search.text().casefold() in text.casefold() # Служебные сообщения сохраняются при отключённых направлениях. + + def _append_record(self, record): # Добавляем одну подготовленную запись, учитывая формат и положение прокрутки. + text, html, _role, payload = record # Байты присутствуют только при явной передаче payload приложением. + bar, position = self.verticalScrollBar(), self.verticalScrollBar().value() # Запоминаем позицию до изменения размера документа. + mode = self.display.currentIndex() # Нулевой режим сохраняет текст и цвета, заданные потребителем. + if payload is not None and mode: # Формат меняет только подписанную приложением полезную нагрузку. + hexadecimal = payload.hex(" ").upper() # HEX показывает каждый исходный байт двумя цифрами. + ascii_text = "".join(chr(value) if 32 <= value <= 126 else "." for value in payload) # Диапазон печатного ASCII задан стандартом; управляющие байты заменяются точками. + super().appendPlainText(text + " · " + (hexadecimal if mode == 1 else ascii_text if mode == 2 else hexadecimal + " | " + ascii_text)) # Исходная подпись не теряется при смене представления байтов. + elif html: super().appendHtml(html) # Сохраняем безопасное оформление или прежний фрагмент приложения. + else: super().appendPlainText(text) # Обычный текст не интерпретируется как HTML. + bar.setValue(bar.maximum() if self.follow.isChecked() else position) # Отключённая автопрокрутка сохраняет место чтения. + + def refresh(self, *_args): # Сигналы Qt могут передавать индекс, флаг или текст. + self.timer.stop() # Немедленное обновление заменяет ожидающее пакетное перестроение. + if self.pause.isChecked(): return # Изменения фильтров во время паузы применятся после её снятия. + bar, position = self.verticalScrollBar(), self.verticalScrollBar().value() # Сохраняем место чтения до очистки документа. + super().clear() # Очищаем только документ, сохраняя ограниченную историю. + for record in self.records: # Показываем оставшиеся записи в исходном порядке. + if self._visible(record): self._append_record(record) # Скрытые строки остаются доступными для следующего выбора фильтра. + bar.setValue(bar.maximum() if self.follow.isChecked() else min(position, bar.maximum())) # При сокращении документа ограничиваем прежнюю позицию новым диапазоном. + self.count.setText("%d строк" % len(self.records)) # Счётчик включает временно скрытые записи. + + def copy_visible(self): # Экспортируется фактически показанный текст, включая состояние паузы и фильтра. + QApplication.clipboard().setText(self.toPlainText()) # Копирование всей видимой консоли не требует ручного выделения. + + def save_to(self, path): # Отдельный метод позволяет проверить экспорт без системного диалога. + Path(path).write_text(self.toPlainText(), encoding="utf-8") # UTF-8 сохраняет русские сообщения и расшифровки протоколов. + + def save_dialog(self): # Пользователь самостоятельно выбирает назначение журнала. + path, _filter = QFileDialog.getSaveFileName(self, "Сохранить консоль", "console.txt", "Текст UTF-8 (*.txt);;Все файлы (*)") # Диалог не выполняет автоматической записи при отмене. + if path: # Записываем только явно выбранный файл. + try: self.save_to(path) # Обрабатываем отказ файловой системы без прерывания приёма данных. + except OSError as error: QMessageBox.warning(self, "Сохранение консоли", str(error)) # Причина ошибки остаётся доступна оператору. diff --git a/python/set_devices/qt_ports/deif_emulator.py b/python/set_devices/qt_ports/deif_emulator.py new file mode 100644 index 0000000..9077911 --- /dev/null +++ b/python/set_devices/qt_ports/deif_emulator.py @@ -0,0 +1,120 @@ +"""Асинхронное управление общим DEIF через SET v2 или RTU.""" # Обмен не зависит от приложения-потребителя и аппаратного порта MCU. +import struct # FC03 и FC06 используют порядок байтов Modbus big-endian внутри общего транспорта. +from .qt_compat import QObject, QTimer, Signal, QSerialPort # Поддерживает одинаковую машину обмена для Qt5 и Qt6. +from .emulator_serial import EmulatorSerialPort # Автомат обнаруживает протокол и проверяет модель выбранной платы. +from .stm_settings import request, decode_config # Настройки STM читаются тем же кодеком, что явный выбор эмулятора. +from set_devices.tms_terminal import crc16_modbus # CRC проверяется также при транспортировке RTU-команды внутри SET v2. +from set_devices.deif_emulator import DEIF_BASE, DEIF_WORDS, decode_snapshot # Адреса, сигнатура и интерпретация снимка общие для всех MCU. + + +class DeifEmulatorClient(QObject): # Каждая операция заканчивается закрытием COM, не удерживая общий порт между действиями. + finished = Signal(bool, str, object) # Возвращает подтверждённый снимок либо ошибку без ложного успеха записи. + + def __init__(self, parent=None, *, serial_factory=EmulatorSerialPort): # Подмена фабрики предназначена для проверки на реальном C-ядре без оборудования. + super().__init__(parent) # QObject освобождает таймеры вместе с владельцем панели. + self.serial = serial_factory(self) # Один адаптер хранит выбранный MCU и выполняет безопасный handshake. + self.serial.readyRead.connect(self._receive) # Разбор допускает произвольную фрагментацию USB/UART. + self.serial.errorOccurred.connect(self._error) # Ошибка открытия или передачи завершает только текущую операцию. + self.timeout = QTimer(self) # Ограничение ожидания применяется отдельно к каждому запросу. + self.timeout.setSingleShot(True) # Тайм-аут не создаёт повторных записей со сторонними эффектами. + self.timeout.timeout.connect(lambda: self._finish(False, "Тайм-аут DEIF; состояние записи проверьте повторным чтением")) # Потерянный ответ не означает, что команда не исполнилась. + self.delay = QTimer(self) # Следующий запрос отправляется вне стека readyRead. + self.delay.setSingleShot(True) # Каждое подтверждение разрешает ровно один следующий шаг. + self.delay.timeout.connect(self._next) # Последовательные FC06 не перемешиваются с финальной проверкой. + self.active = False # Новая операция разрешена только после полного завершения предыдущей. + + def start(self, port, unit, baud, timeout, writes=()): # Профиль связи передаётся потребителем явно, без глобального COM и адреса. + if self.active: # Повторное нажатие не должно сбросить ожидающую подтверждения запись. + return # Текущая операция сохраняет первоначальный профиль. + self.writes = tuple((int(offset), int(value) & 0xFFFF) for offset, value in writes) # RAW I16 кодируется теми же 16 битами без потери знака. + if any(offset not in (2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20) and not 32 <= offset < 44 for offset, _value in self.writes): # Только документированные writable слова версии 1 допускаются в очередь. + self.finished.emit(False, "Регистр DEIF недоступен для записи", None) # Локальная ошибка обнаруживается до открытия физического порта. + return # Чужие регистры и конфигурация STM не могут попасть в эту транзакцию. + self.unit, self.timeout_ms = unit, timeout # Адрес управления STM по умолчанию 16; тайм-аут задаётся в мс. + self.active, self.stage, self.rx = True, "config", bytearray() # Первая команда только читает действующий режим MCU. + self.serial.setPortName(port) # Выбор COM не открывает соединение до настройки формата. + self.serial.setBaudRate(baud) # USART использует выбранную скорость; для CDC это поле совместимости. + self.serial.setDataBits(QSerialPort.DataBits.Data8) # Восемь бит данных соответствуют аппаратным портам STM. + self.serial.setParity(QSerialPort.Parity.NoParity) # Проверку целостности выполняет CRC, формат UART без чётности. + self.serial.setStopBits(QSerialPort.StopBits.OneStop) # Один стоп-бит завершает формат 8N1. + self.serial.setFlowControl(QSerialPort.FlowControl.NoFlowControl) # RTS/CTS прошивкой не используются. + if not self.serial.open(QSerialPort.OpenModeFlag.ReadWrite): # COM может быть занят другой программой. + self._finish(False, self.serial.errorString()) # Ошибка сообщает реальную причину открытия. + return # Ни чтение, ни запись при закрытом порте не выполняются. + self._send(3, 0x1210, 10) # Адрес и длина блока настроек STM взяты из set_emu_server. + + def _send(self, function, address, value): # Запрос отправляется один раз; автоматического повтора записи нет. + self.packet = request(self.unit, function, address, value) # Общий кодек добавляет правильный CRC16. + self.rx.clear() # Байты предыдущего подтверждённого ответа не примешиваются к новому. + self.timeout.start(self.serial.response_timeout(self.timeout_ms)) # Первый обмен учитывает время определения SET v2/RTU. + if self.serial.write(self.packet) != len(self.packet): # Частичная постановка запроса в очередь не считается отправкой. + self._finish(False, "Не удалось передать запрос DEIF") # Операция останавливается без повторной передачи. + + def _receive(self): # Накапливает только ответ текущего FC03 или FC06. + chunk = bytes(self.serial.readAll()) # Готовые байты забираются даже при отменённой операции. + if not self.active or not self.timeout.isActive(): # Поздний ответ не возобновляет отменённую последовательность. + return # Команда остаётся завершённой до нового явного действия пользователя. + self.rx.extend(chunk) # USB может разрезать ответ по любым границам. + function = self.packet[1] # Функция текущего запроса определяет размер ответа. + while len(self.rx) >= 3: # Заголовок содержит unit, function и byte count либо exception code. + if self.rx[0] != self.unit or self.rx[1] not in (function, function | 0x80): # Чужие либо старые кадры не подтверждают текущую операцию. + del self.rx[0] # Сдвиг на байт позволяет восстановиться после шумового префикса. + continue # Повторно ищет подходящий заголовок в оставшихся байтах. + expected = self.packet[5] * 2 if function == 3 else 0 # Все чтения короче 256 слов, старший байт количества равен нулю. + size = 5 if self.rx[1] & 0x80 else expected + 5 if function == 3 else 8 # Exception имеет 5 байт, FC06 echo — 8, FC03 — данные плюс заголовок и CRC. + if len(self.rx) < size: # Незавершённый ответ остаётся в буфере до readyRead или тайм-аута. + return # Никаких записей до полного подтверждения не выполняется. + raw = bytes(self.rx[:size]) # Фиксирует кадр до удаления из транспортного буфера. + del self.rx[:size] # Следующий шаг начнёт новый обмен с чистым буфером. + self.timeout.stop() # Полный ответ больше не ожидает истечения тайм-аута. + try: # Ошибки протокола должны возвращаться через finished, не покидая слот Qt. + if crc16_modbus(raw): # Нулевая CRC полного кадра подтверждает целостность. + raise ValueError("Неверная CRC ответа DEIF") # Повреждённый кадр не подтверждает запись. + if raw[1] & 0x80: # Старая прошивка либо неверный режим возвращает Modbus exception. + raise ValueError("STM отклонила DEIF, код %d; проверьте режим и версию прошивки" % raw[2]) # Показывает реальный код без предположения об успешном исполнении. + if function == 6 and raw != self.packet or function == 3 and raw[2] != expected: # Echo и фактическая длина должны точно совпасть с запросом. + raise ValueError("Неверное подтверждение DEIF") # Ответ другой команды не продвигает очередь. + self._accept(raw) # Только проверенный ответ может разрешить следующий шаг. + except ValueError as error: # Локальная проверка сигнатуры или роли имеет тот же путь завершения. + self._finish(False, str(error)) # Все таймеры и COM закрываются одинаково при любой ошибке. + return # За один сигнал обрабатывается только текущий запрос последовательности. + + def _accept(self, raw): # Порядок: конфигурация, сигнатура DEIF, записи, итоговый снимок. + if self.stage == "config": # Чтение действующего режима предшествует любым командам DEIF. + self.mode = decode_config(raw)[8] # Общий декодер проверяет сигнатуру STM и допустимые режимы. + if self.writes and self.mode not in (4, 5): # Выбор режима выполняется отдельной явной транзакцией STM. + raise ValueError("Выберите DEIF Master или DEIF Slave в настройках STM и примените режим") # Чтение остаётся доступным для диагностики любой прошивки с DEIF. + self.stage = "probe" # Теперь нужно проверить версию и роль отдельного окна DEIF. + self.steps = [(3, DEIF_BASE, DEIF_WORDS)] # Одно чтение возвращает атомарный снимок 52 слов. + elif self.packet[1] == 3: # Окно читается перед записями и после них. + snapshot = decode_snapshot(struct.unpack(">%dH" % DEIF_WORDS, raw[3:-2]), self.mode) # Совместимость подтверждается данными реального MCU. + if self.stage == "probe" and self.writes: # Совместимый сервис разрешает подготовленные пользователем команды. + self.stage = "write" # С этой точки любой отказ может означать частично применённый профиль. + self.steps = [(6, DEIF_BASE + offset, value) for offset, value in self.writes] + [(3, DEIF_BASE, DEIF_WORDS)] # Финальное чтение обязательно даже после успешных echo. + else: # Чтение без записей и финальная проверка завершают транзакцию. + if any(snapshot.words[offset] != value for offset, value in dict(self.writes).items()): # Повторная запись того же регистра проверяется по последнему значению, включая временную сеть и нулевую маску при настройке. + raise ValueError("DEIF не подтвердил новые значения; повторите чтение состояния") # ACK передачи сам по себе не является проверкой применения. + self._finish(True, "Состояние DEIF прочитано и проверено", snapshot) # Только этот путь публикует подтверждённый снимок формы. + return # Завершённая операция не назначает следующий запрос. + self.delay.start(20) # Пауза 20 мс не блокирует GUI и совпадает с шагом клиента настроек STM. + + def _next(self): # Слот таймера продвигает ровно одну команду подтверждённой последовательности. + if self.active and self.steps: # Отмена удаляет разрешение последующих запросов. + self._send(*self.steps.pop(0)) # Следующая запись выполняется только после echo предыдущей. + + def _error(self, error): # Обрабатывает ошибки последовательного порта в том же GUI-потоке. + if self.active and error not in (QSerialPort.SerialPortError.NoError, QSerialPort.SerialPortError.TimeoutError): # Собственный таймер уже отвечает за тайм-аут транзакции. + self._finish(False, self.serial.errorString()) # Не скрывает причину отключения или отказа COM. + + def cancel(self): # Отмена доступна пользователю без смены режима на MCU. + if self.active: # Повторная отмена не создаёт повторных сигналов завершения. + self._finish(False, "Обмен DEIF отменён; проверьте состояние повторным чтением") # Уже подтверждённые записи не откатываются и не повторяются. + + def _finish(self, ok, message, snapshot=None): # Единое завершение используется при успехе, отмене и ошибке. + if not self.active: # Поздняя ошибка Qt после close не должна затронуть новую операцию. + return # finished публикуется ровно один раз за запуск. + self.active = False # Состояние сбрасывается раньше закрытия COM и внешних обработчиков. + self.timeout.stop() # Ожидание текущего ответа больше не действует. + self.delay.stop() # Следующие записи не отправляются после ошибки. + self.serial.close() # Общий COM освобождается для логгера и других панелей. + self.finished.emit(ok, message, snapshot) # UI получает результат после полного освобождения ресурсов. diff --git a/python/set_devices/qt_ports/deif_emulator_panel.py b/python/set_devices/qt_ports/deif_emulator_panel.py new file mode 100644 index 0000000..a2df214 --- /dev/null +++ b/python/set_devices/qt_ports/deif_emulator_panel.py @@ -0,0 +1,189 @@ +"""Общая панель аппаратного DEIF Master/Slave для всех реализованных MCU.""" # Приложение передаёт только параметры подключения и освобождение общего транспорта. +try: # Qt6 используется современными настольными приложениями. + from PySide6.QtWidgets import QWidget, QVBoxLayout, QFormLayout, QHBoxLayout, QLabel, QPushButton, QSpinBox, QComboBox, QCheckBox, QGroupBox, QScrollArea # Панель не импортирует виджеты конкретного приложения. +except ImportError: # На Windows 7 те же элементы предоставляет Qt5. + from PySide2.QtWidgets import QWidget, QVBoxLayout, QFormLayout, QHBoxLayout, QLabel, QPushButton, QSpinBox, QComboBox, QCheckBox, QGroupBox, QScrollArea # Состав и поведение управления сохраняются между версиями Qt. +from .qt_compat import Signal # Совместимый сигнал сообщает потребителю о занятости общего COM. +from .deif_emulator import DeifEmulatorClient # Обмен и проверка ответов принадлежат templates. +from set_devices.deif_emulator import DEIF_FIELDS, DEIF_INDICES # Порядок полей и OD взяты из переносимой C-модели. +from set_devices.mcu_profiles import EMULATOR_PROFILES # Строка модели USB и настройки MCU определяются единым каталогом. + + +class DeifEmulatorPanel(QWidget): # Единственный экземпляр панели обслуживает выбранную плату без дублирования моделей. + busy_changed = Signal(bool) # Приложение блокирует конфликтующие инструменты на время транзакции. + + def __init__(self, connection, prepare, parent=None): # Колбэки позволяют использовать панель вне SETGUI. + super().__init__(parent) # Владелец Qt управляет временем жизни панели и клиента. + self.connection, self.prepare = connection, prepare # connection возвращает COM, unit, baud, timeout; prepare освобождает транспорт либо возвращает причину отказа. + self.client = DeifEmulatorClient(self) # Общий клиент проверяет режим STM и сигнатуру DEIF перед записью. + self.client.finished.connect(self._finished) # Состояние формы обновляется только подтверждённым снимком. + self.snapshot = None # До первого чтения действия записи заблокированы. + outer = QVBoxLayout(self) # Внешняя компоновка оставляет статус доступным при прокрутке длинного профиля. + self.heading = QLabel() # Название платы меняется вместе с общим селектором MCU. + self.heading.setWordWrap(True) # Полное название HOPE не обрезается при узком окне. + outer.addWidget(self.heading) # Текущая аппаратная цель видна до любых команд. + note = QLabel("В «Настройки STM» выберите DEIF Master или DEIF Slave и примените режим. Управление платой идёт через выбранный COM; кадры DEIF передаются её CAN. Для изменения сетевого профиля сначала нажмите «Останов DEIF». Настройки действуют до сброса или смены роли.") # Объясняет пользователю разделение управления MCU и работы CAN без автоматического запуска. + note.setWordWrap(True) # Пояснение занимает доступную ширину. + outer.addWidget(note) # Инструкция остаётся рядом с кнопками даже после прокрутки профиля. + scroll = QScrollArea() # Настройки и шесть привязок должны помещаться при небольшом разрешении экрана. + scroll.setWidgetResizable(True) # Содержимое использует ширину панели. + content = QWidget() # Дочерний контейнер содержит только редактируемые параметры. + layout = QVBoxLayout(content) # Группы расположены последовательно без вложенных вкладок. + network = QGroupBox("Профиль CAN / DEIF") # Параметры соответствуют словам 4…15 окна 0x1600. + form = QFormLayout(network) # Подписи поясняют назначение каждого числа. + self.node = self._spin(1, 127, 1) # XDi-net разрешает узлы 1…126, CANopen дополнительно 127; firmware проверяет выбранную сеть. + self.peer = self._spin(1, 127, 11) # Для Master это DAM-получатель, для Slave — SAM-источник. + self.network = QComboBox() # Сеть задаёт способ адресации и допустимые RPDO. + self.network.addItems(("XDi-net / SAM", "CANopen / DAM")) # Значения индекса 0 и 1 совпадают с set_emu_deif.h. + self.pdo = self._spin(1, 4, 2) # RPDO2 — штатный профиль, RPDO1 разрешён только в чистом CANopen. + self.period = self._spin(1, 65535, 100) # Период цикла в мс: firmware хранит uint16, нулевой период запрещён. + self.period.setSuffix(" мс") # Единица времени указана непосредственно рядом со значением. + self.mask = self._spin(0, 255, 63, hexadecimal=True) # Биты 0…5 выбирают шесть измерений; 6…7 добавляют яркость и палитру Master. + self.group = self._spin(0, 9, 1) # DEIF поддерживает группы диммера 1…9; 0 означает локальный режим. + self.heartbeat = QCheckBox("Передавать heartbeat Master") # Slave передаёт heartbeat независимо от этого флага. + self.self_start = QCheckBox("Автозапуск Slave в CANopen") # В XDi-net самозапуск через 1 с обязателен по профилю. + self.self_start.setChecked(True) # Совпадает с начальной настройкой set_deif_init. + self.service_sam = QCheckBox("Сервисный SAM COB-ID 0x27F") # Специальный идентификатор включается только явным выбором. + for title, widget in (("Собственный Node-ID", self.node), ("DAM получатель / SAM источник", self.peer), ("Сеть", self.network), ("RPDO", self.pdo), ("Период Master", self.period), ("Маска объектов", self.mask), ("Группа диммера", self.group), ("Heartbeat", self.heartbeat), ("Запуск Slave", self.self_start), ("Сервисный SAM", self.service_sam)): # Группа содержит все изменяемые параметры сетевого профиля C-модели. + form.addRow(title, widget) # Числовые поля не скрываются в аппаратных настройках конкретной платы. + layout.addWidget(network) # Сетевые настройки одинаковы для bxCAN и FDCAN. + self.network_group = network # Запущенный эмулятор не разрешает менять сетевой профиль. + values = QGroupBox("Задания Master / показания Slave") # Одни и те же RAW показывают задания передатчика либо принятые значения. + value_form = QFormLayout(values) # Каждое поле сохраняет отдельную подпись и знак. + self.raw = [self._spin(-32768, 32767, 0) for _field in DEIF_FIELDS] # Весь диапазон I16 сохраняет служебные значения и отрицательные задания. + for title, widget in zip(DEIF_FIELDS, self.raw): # Порядок соответствует set_deif_emu.raw[6]. + value_form.addRow(title, widget) # Уставка угла Master отображается отдельно, но зеркалит фактический угол. + self.raw[5].setReadOnly(True) # Master передаёт одинаковый RAW угла для подиндексов 2 и 7; шестой RAW напрямую не записывается. + self.brightness = self._spin(0, 100, 100) # Яркость — U8 в процентах, допустимый диапазон проверяется firmware. + self.brightness.setSuffix(" %") # Единицы яркости не смешиваются с необработанными измерениями. + self.palette = QComboBox() # Палитра соответствует DEIF §11.3.2. + self.palette.addItems(("Day", "Night", "Dusk")) # Номера 0, 1 и 2 передаются без преобразования. + value_form.addRow("Яркость", self.brightness) # Master может изменять яркость во время работы. + value_form.addRow("Палитра", self.palette) # Slave показывает значения, полученные от CAN. + layout.addWidget(values) # Показания остаются доступными при запущенном эмуляторе. + bindings = QGroupBox("Привязки объектов Slave") # Привязки явно задают OD вместо предположений о словаре прибора. + binding_form = QFormLayout(bindings) # Шесть пар индекс/подиндекс соответствуют словам 32…43. + self.indices, self.subindices = [], [] # Пары сохраняются в порядке полей для чтения и записи. + for number, title in enumerate(DEIF_FIELDS): # Все шесть объектов могут настраиваться независимо. + row = QHBoxLayout() # Индекс и подиндекс располагаются рядом с общей подписью поля. + index = self._spin(0, 65535, DEIF_INDICES[number], hexadecimal=True) # Индекс OD хранится как uint16, семейство проверяет MCU. + sub = QComboBox() # Только поддерживаемые I16 подиндексы разрешены моделью. + sub.addItems(("2 — значение", "7 — задание")) # Подиндексы 2 и 7 заданы в set_deif_write. + sub.setCurrentIndex(int(number == 5)) # Последняя привязка соответствует уставке угла. + row.addWidget(index) # Значение OD отображается в привычном шестнадцатеричном виде. + row.addWidget(sub) # Назначение подиндекса видно без отдельной документации. + binding_form.addRow(title, row) # Подпись совпадает с таблицей показаний. + self.indices.append(index) # Сохраняет редактируемый индекс нужного поля. + self.subindices.append(sub) # Сохраняет подиндекс того же поля. + self.bindings_group = bindings # Привязки недоступны при работе и в роли Master. + layout.addWidget(bindings) # Пользователь может настроить словарь перед запуском Slave. + scroll.setWidget(content) # Область прокрутки принимает владение контейнером. + outer.addWidget(scroll) # Высота формы ограничивается размером окна. + buttons = QHBoxLayout() # Основные команды остаются видимыми независимо от прокрутки. + self.read = QPushButton("Прочитать DEIF") # Чтение не запускает передачу CAN. + self.apply = QPushButton("Применить профиль") # Настройки отправляются отдельным явным действием при остановке. + self.send_raw = QPushButton("Записать RAW / подсветку") # Живые задания разрешены только Master. + self.start = QPushButton("Пуск DEIF") # Пуск не совмещается с применением профиля либо выбором роли. + self.stop = QPushButton("Останов DEIF") # Останавливает модель и её фоновые CAN-события. + self.cancel = QPushButton("Отменить обмен") # Отмена относится к транзакции COM, а не к уже работающей модели MCU. + for button, action in ((self.read, lambda: self._request()), (self.apply, self._apply), (self.send_raw, self._write_raw), (self.start, lambda: self._request(((2, 1),))), (self.stop, lambda: self._request(((2, 0),))), (self.cancel, self.client.cancel)): # Кнопки привязаны к единственному клиенту без повторяющихся обработчиков протокола. + button.clicked.connect(action) # Нажатие является единственным источником команд, опрос таймером не запускается. + buttons.addWidget(button) # Все действия имеют видимые названия и одинаковое расположение для любого MCU. + outer.addLayout(buttons) # Команды находятся под прокручиваемым профилем. + self.status = QLabel("Сначала прочитайте состояние DEIF выбранной платы.") # Непрочитанное устройство не выглядит подключённым. + self.status.setWordWrap(True) # Ошибки связи и диагностика не обрезаются. + outer.addWidget(self.status) # После операции результат остаётся видимым. + self.set_mcu("STM32F407") # Начальная модель совпадает с прежней рабочей областью эмуляторов. + + @staticmethod # Создание однотипных числовых полей не зависит от состояния панели. + def _spin(minimum, maximum, value, hexadecimal=False): # Диапазоны берутся из описания регистров C-модели. + spin = QSpinBox() # Qt выполняет базовую проверку числового ввода. + spin.setRange(minimum, maximum) # Допустимый размер поля задаётся до начального значения. + spin.setValue(value) # Штатный профиль можно использовать после явного применения. + if hexadecimal: # Маски и индексы OD удобнее читать как hex. + spin.setDisplayIntegerBase(16) # Меняет только отображение, числовое значение остаётся целым. + spin.setPrefix("0x") # Основание видно рядом с вводимыми цифрами. + return spin # Поле встраивается в нужную группу общей формы. + + def set_mcu(self, key): # Смена цели не открывает порт и не запускает CAN. + self.client.serial.set_mcu(key) # Проверяемая USB-модель выбирается до следующего handshake. + self.snapshot = None # Состояние предыдущего устройства не разрешает запись новому. + self.heading.setText("DEIF Master / Slave · " + EMULATOR_PROFILES[key]["title"]) # Полное название аппаратного профиля всегда видно оператору. + self.status.setText("Выберите режим DEIF в настройках STM, затем прочитайте состояние.") # Явно сбрасывает прежнее подтверждение платы. + self._controls() # Новая цель требует нового чтения перед пуском и настройкой. + + def _controls(self): # Разрешения кнопок зависят только от подтверждённого снимка и текущей транзакции. + busy, snapshot = self.client.active, self.snapshot # Не доверяет вручную отредактированным полям роли. + verified = snapshot is not None and snapshot.mode in (4, 5) # Наличие сервиса не означает, что он выбран активным эмулятором. + self.read.setEnabled(not busy) # Чтение разрешено также до выбора роли для диагностики прошивки. + self.cancel.setEnabled(busy) # Отменять можно только выполняющийся обмен. + self.apply.setEnabled(not busy and verified and not snapshot.running) # Сетевой профиль меняется только у остановленной выбранной модели. + self.start.setEnabled(not busy and verified and not snapshot.running) # Первое чтение и выбор роли обязательны перед пуском. + self.stop.setEnabled(not busy and verified) # Повторная остановка допускается и не запускает новый сценарий. + master = verified and snapshot.role == 1 # Живые задания и подсветка принадлежат только Master. + self.send_raw.setEnabled(not busy and master) # Slave получает эти значения из CAN и не допускает подмены входов. + self.network_group.setEnabled(not busy and verified and not snapshot.running) # Заблокированные поля не создают впечатление применяемого на ходу профиля. + self.bindings_group.setEnabled(not busy and verified and not snapshot.running and not master) # Master использует заданные спецификацией OD, его привязки не изменяют формируемые кадры. + for widget in self.raw[:5] + [self.brightness, self.palette]: # Шестой RAW всегда является показанием либо зеркалом угла. + widget.setEnabled(not busy and master) # Во время операции запрещает редактирование отправляемых значений. + + def _request(self, writes=()): # Все действия используют один путь подготовки, блокировки и проверки. + if self.client.active: # Двойное нажатие не отменяет уже отправленную команду. + return # Дождаться завершения можно по статусу панели. + connection = self.connection() # Параметры берутся из текущей формы STM непосредственно перед действием. + if not connection[0]: # Без выбранного COM невозможно установить физическую цель. + self.status.setText("Выберите COM во вкладке «Настройки STM».") # Сообщает конкретное место выбора. + return # Остальные инструменты не отключаются при пустом профиле. + reason = self.prepare() # Потребитель проверяет конфликтующие операции и освобождает общий порт. + if reason: # Незавершённый обмен другого инструмента сохраняет исходную цель. + self.status.setText(reason) # Причина отказа видна рядом с кнопкой. + return # Конкурирующий COM не открывается. + self.busy_changed.emit(True) # Потребитель блокирует смену STM и конфликтующие панели до открытия COM. + self.status.setText("Обмен с DEIF…") # Начало операции не выдаётся за подтверждение записи. + self.client.start(*connection, writes=writes) # Очередь выполняется последовательно с финальным чтением. + self._controls() # Синхронная ошибка открытия также корректно обновляет состояние кнопок. + + def _apply(self): # Формирует явный набор сетевых настроек остановленной модели. + if self.snapshot is None: # Снимок мог быть сброшен сменой MCU. + return # Без подтверждения роли профиль не отправляется. + if self.network.currentIndex() == 0 and (self.node.value() > 126 or self.pdo.value() < 2): # XDi-net резервирует Node 127 и RPDO1 для служебных функций. + self.status.setText("Для XDi-net выберите Node-ID 1…126 и RPDO2…4.") # Проверка предшествует любой записи. + return # Неверный сетевой профиль не применяется частично. + if self.snapshot.role == 2 and (self.peer.value() > 126 or self.mask.value() > 63) or self.mask.value() & 0xC0 and not self.group.value(): # Источник SAM Slave ограничен 126, Slave использует шесть измерений, сетевой диммер требует группу. + self.status.setText("Проверьте SAM источник, маску объектов Slave и группу диммера.") # Сообщает ограничения переносимой C-модели. + return # Профиль остаётся только в форме до исправления. + writes = [(6, 1), (9, 0), (4, self.node.value()), (5, self.peer.value()), (7, self.pdo.value()), (6, self.network.currentIndex()), (8, self.period.value()), (10, int(self.heartbeat.isChecked())), (11, int(self.self_start.isChecked())), (12, self.group.value()), (15, int(self.service_sam.isChecked())), (9, self.mask.value())] # Временный CANopen и нулевая маска позволяют безопасно менять Node 127, RPDO1 и группу 0 в любом исходном профиле. + if self.snapshot.role == 2: # Привязки используются только принимающей ролью C-модели. + for number, (index, sub) in enumerate(zip(self.indices, self.subindices)): # Пары задают шесть независимых входов Slave. + family = index.value() & 0xFFF0 # Семейство OD исключает младший номер экземпляра. + if not index.value() & 15 or family not in (0x3000, 0x3080, 0x3090, 0x3420, 0x3430): # set_deif_write разрешает экземпляры 1…15 пяти измерительных семейств. + self.status.setText("Привязки DEIF должны использовать измерительные OD 300x/308x/309x/342x/343x, экземпляр 1…15.") # Локальный отказ не меняет часть профиля на MCU. + return # Проверяются все поля до передачи первого запроса. + writes.extend(((32 + 2 * number, index.value()), (33 + 2 * number, 7 if sub.currentIndex() else 2))) # Последовательность совпадает с парами индекс/подиндекс регистров 32…43. + self._request(writes) # Настройка не содержит команды пуска. + + def _write_raw(self): # Живое изменение заданий не меняет сетевой профиль либо состояние запуска. + writes = [(16 + number, widget.value()) for number, widget in enumerate(self.raw[:5])] # Пять RAW Master, угол задания firmware зеркалит автоматически. + self._request(writes + [(13, self.brightness.value()), (14, self.palette.currentIndex())]) # Подсветка и палитра подтверждаются итоговым снимком вместе с RAW. + + def _finished(self, ok, message, snapshot): # Единственный обработчик освобождает блокировки и обновляет форму. + self.snapshot = snapshot if ok else None # После ошибки неизвестно, какие команды уже применены; новое чтение обязательно. + if ok: # Только проверенные данные реального MCU заменяют значения формы. + words = snapshot.words # Все индексы взяты из set_deif_read версии 1. + for widget, offset in ((self.node, 4), (self.peer, 5), (self.pdo, 7), (self.period, 8), (self.mask, 9), (self.group, 12), (self.brightness, 13)): # Обновляет числовые настройки выбранной роли. + widget.setValue(words[offset]) # Снимок сохраняет фактически применённые значения, а не отправленные пожелания. + self.network.setCurrentIndex(words[6]) # Сеть определяет интерпретацию последующего профиля. + self.palette.setCurrentIndex(words[14]) # Slave может получить новую палитру по CAN. + for widget, offset in ((self.heartbeat, 10), (self.self_start, 11), (self.service_sam, 15)): # Флаги читаются независимо от текущего разрешения редактирования. + widget.setChecked(bool(words[offset])) # Правильная роль отображает собственные настройки. + for number, widget in enumerate(self.raw): # Знаковые RAW нужны также для служебных кодов и отрицательной частоты вращения. + widget.setValue(snapshot.raw[number]) # Показывает входы Slave либо задания Master. + self.indices[number].setValue(words[32 + 2 * number]) # Сохраняет явный словарь каждого поля. + self.subindices[number].setCurrentIndex(int(words[33 + 2 * number] == 7)) # Фактическое значение и задание остаются разными привязками. + received = words[26] | words[27] << 16 # RX счётчик состоит из младшего и старшего 16-битных слов. + transmitted = words[28] | words[29] << 16 # TX означает постановку в аппаратную CAN-очередь. + rejected = words[30] | words[31] << 16 # Ошибочные кадры показываются отдельно от успешно принятых. + message += f" · {'Master' if snapshot.role == 1 else 'Slave'} · {'работает' if snapshot.running else 'остановлен'} · NMT {words[22]} · RX {received} / TX {transmitted} / отклонено {rejected} · seen 0x{words[23]:02X} / invalid 0x{words[24]:02X} / lost 0x{words[25]:02X}" # Диагностика позволяет проверить поток без предположения, что ACK COM подтверждает физический CAN. + self.status.setText(message) # Ошибка либо подтверждение остаются видимыми после закрытия порта. + self._controls() # Права редактирования пересчитываются по новому проверенному состоянию. + self.busy_changed.emit(False) # Потребитель освобождает остальные инструменты после завершения клиента. diff --git a/python/set_devices/qt_ports/emulator_serial.py b/python/set_devices/qt_ports/emulator_serial.py new file mode 100644 index 0000000..21fcd61 --- /dev/null +++ b/python/set_devices/qt_ports/emulator_serial.py @@ -0,0 +1,181 @@ +"""Async COM adapter for direct RTU or automatic emulator discovery. + +Panels retain their register/TMS decoders. Only this boundary translates them +to SET v2 on the wire. No protocol cache survives closing/reopening a port. +""" +import time + +from .qt_compat import QObject, QTimer, Signal, QSerialPort # Общий порт не зависит от импортов SETGUI и поддерживает Qt6/Qt5. +from set_devices.emulator_protocol import EmulatorProtocol # Автомат SET v2/RTU находится рядом с остальными переносимыми моделями templates. + + +def response_timeout(port, milliseconds): + return port.response_timeout(milliseconds) if isinstance(port, EmulatorSerialPort) else milliseconds + + +def cancel_pending(port): + if isinstance(port, EmulatorSerialPort): + port.cancel_pending() + + +class EmulatorSerialPort(QObject): + readyRead = Signal() + errorOccurred = Signal(object) + protocolChanged = Signal(str) + wireEvent = Signal(str, bytes) + PROBE_MS = 300 + + def __init__(self, parent=None, port=None, *, protocol_mode='auto', rtu_suffix=b'', mcu="STM32F407"): # Профиль MCU фиксирует проверяемую модель прошивки, сохраняя все старые параметры порта. + super().__init__(parent) + self._port = port if port is not None else QSerialPort(self) + self._port.readyRead.connect(self._receive) + self._port.errorOccurred.connect(self.errorOccurred.emit) + self._probe = QTimer(self) + self._probe.setSingleShot(True) + self._probe.timeout.connect(self._probe_timeout) + self._protocol_mode = protocol_mode + self._rtu_suffix = bytes(rtu_suffix) + self._mcu = mcu # Аппаратная привязка сохраняется между закрытием и повторным открытием того же COM-адаптера. + self.protocol = EmulatorProtocol(protocol_mode, mcu=mcu) # Первичная конфигурация использует ожидаемую модель выбранного MCU. + self._rx = bytearray() + self._error = '' + self._deadline = 0 + + def __getattr__(self, name): + port = self.__dict__.get('_port') + if port is None: + raise AttributeError(name) + return getattr(port, name) + + def open(self, mode): + self._probe.stop() + self._deadline = 0 + self.protocol = EmulatorProtocol(self._protocol_mode, mcu=self._mcu) # Повторное открытие начинает новый handshake с той же аппаратной привязкой. + self._rx.clear() + self._error = '' + return self._port.open(mode) + + def configure_protocol(self, mode, *, rtu_suffix=b''): + """Choose the wire format before opening a new connection.""" + if self.isOpen(): + raise ValueError('Сначала отключите COM-порт для смены протокола') + protocol = EmulatorProtocol(mode, mcu=self._mcu) # Смена wire-формата не должна сбрасывать выбранный MCU на F407. + self.cancel_pending() + self._protocol_mode = mode + self._rtu_suffix = bytes(rtu_suffix) + self.protocol = protocol + self._rx.clear() + + def close(self): + self.cancel_pending() + self._port.close() + self._rx.clear() + + def set_mcu(self, mcu): # Профиль разрешается менять только до открытия физического соединения. + if self.isOpen(): # Открытая транзакция должна завершиться с первоначальной идентичностью устройства. + raise ValueError("Сначала отключите COM-порт для смены MCU") # Предотвращаем подмену цели незавершённого обмена. + protocol = EmulatorProtocol(self._protocol_mode, mcu=mcu) # Неизвестный профиль отвергается до изменения сохранённых параметров. + self._mcu = mcu # Следующее открытие порта проверит DeviceInfo именно этой платы. + self.protocol = protocol # Старое состояние обнаружения не переносится на другой MCU. + + def cancel_pending(self): + self._probe.stop() + self._deadline = 0 + self.protocol.cancel() + + def response_timeout(self, milliseconds): + return milliseconds + (2 * self.PROBE_MS if self.protocol.mode == 'auto' else 0) + + def errorString(self): + return self._error or self._port.errorString() + + def clear(self, *args): + self.cancel_pending() + self._rx.clear() + return self._port.clear(*args) + + def bytesAvailable(self): + return len(self._rx) + + @property + def supports_wave_blocks(self): + return self.protocol.mode == 'v2' + + def readAll(self): + result = bytes(self._rx) + self._rx.clear() + return result + + def write(self, data): + self._error = '' + self._rx.clear() + try: + packet = self.protocol.begin(bytes(data)) + return len(data) if self._send(packet) else -1 + except ValueError as error: + self._fail(str(error)) + return -1 + + def _send(self, packet): + self._probe.stop() + self._deadline = 0 + if self.protocol.phase in ('ping', 'info'): + self._deadline = time.monotonic() + self.PROBE_MS / 1000 + self._probe.start(self.PROBE_MS) + if self.protocol.mode == 'rtu': + packet += self._rtu_suffix + written = self._port.write(packet) + if written > 0: + self.wireEvent.emit('TX', packet[:written]) + if written != len(packet): + self._fail('Не удалось передать запрос целиком') + return False + return True + + def _receive(self): + raw = bytes(self._port.readAll()) + if not raw: + return + self.wireEvent.emit('RX', raw) + try: + old_mode = self.protocol.mode + outgoing, incoming = self.protocol.feed(raw) + if self.protocol.mode != old_mode: + self.protocolChanged.emit('SET v2') + if outgoing and not self._send(outgoing): + return + if incoming: + self._rx.extend(incoming) + self.readyRead.emit() + except ValueError as error: + self._fail(str(error)) + + def _probe_timeout(self): + if not self._deadline: + return + if time.monotonic() < self._deadline: + self._probe.start(max(1, int((self._deadline-time.monotonic())*1000)+1)) + return + try: + packet = self.protocol.fallback() + self.protocolChanged.emit('RTU') + self._send(packet) + except ValueError as error: + self._fail(str(error)) + + def _fail(self, message): + self._error = message + self.cancel_pending() + self.errorOccurred.emit(QSerialPort.SerialPortError.ReadError) + + def waitForReadyRead(self, milliseconds): + # Used only in WaveTransfer's worker. No GUI event loop is blocked. + deadline = time.monotonic() + milliseconds / 1000 + while not self._rx and not self._error and time.monotonic() < deadline: + if self._deadline and time.monotonic() >= self._deadline: + self._probe_timeout() + remaining = max(1, int((deadline-time.monotonic())*1000)) + self._port.waitForReadyRead(min(remaining, 20)) + if self._error: + raise OSError(self._error) + return bool(self._rx) diff --git a/python/set_devices/qt_ports/emulator_workspace.py b/python/set_devices/qt_ports/emulator_workspace.py new file mode 100644 index 0000000..fa8adbe --- /dev/null +++ b/python/set_devices/qt_ports/emulator_workspace.py @@ -0,0 +1,36 @@ +from .qt_compat import Signal # Общий сигнал Qt работает в портах PySide6 и PySide2 без зависимости от SETGUI. +try: # Настольные потребители могут использовать любую из поддерживаемых версий Qt. + from PySide6.QtWidgets import QComboBox, QTabWidget # Qt6 предоставляет контейнер общих панелей и явный выбор MCU. + from PySide6.QtCore import Qt, QSignalBlocker # Блокировка сигнала предотвращает рекурсивное переключение профиля. +except ImportError: # Порт Windows 7 использует тот же API поверх PySide2. + from PySide2.QtWidgets import QComboBox, QTabWidget # Состав и поведение панелей сохраняются в Qt5. + from PySide2.QtCore import Qt, QSignalBlocker # Оба поколения Qt поддерживают блокировку сигналов комбобокса. +from set_devices.mcu_profiles import EMULATOR_PROFILES, EMULATOR_TOOLS # Модели и аппаратные привязки задаёт общая библиотека. + + +class EmulatorWorkspace(QTabWidget): # Потребитель предоставляет UI-панели, а templates выбирает их состав для конкретного MCU. + mcu_changed = Signal(str) # Приложение обновляет локальные настройки и подписи после явного выбора аппаратного профиля. + + def __init__(self, parent=None): # Контейнер не открывает COM/CAN и не создаёт экземпляров аппаратных моделей. + super().__init__(parent) # Qt владеет переданными страницами в течение жизни рабочей области. + self.mcu = "STM32F407" # Сохраняем профиль прежнего эмулятора для существующих пользователей и вызовов. + self.mcu_selector = QComboBox(self) # Общая панель явно показывает MCU, которому предназначены команды. + for key, profile in EMULATOR_PROFILES.items(): # В списке появляются только платы с реализованными портами set_emu_server. + self.mcu_selector.addItem(profile["title"], key) # Стабильный ключ отделяет совместимость устройства от отображаемой подписи. + self.setCornerWidget(self.mcu_selector, Qt.Corner.TopRightCorner) # Выбор MCU доступен рядом с вкладками общих инструментов. + self.mcu_selector.currentIndexChanged.connect(lambda index: self.select_mcu(self.mcu_selector.itemData(index))) # Пользовательский выбор проходит тот же метод, что переход из меню конкретного MCU. + self._emulator_pages = {} # Реестр хранит единственные экземпляры переданных панелей, сохраняя общие транспорты приложения. + + def add_emulator_page(self, key, widget): # Приложение связывает собственный виджет с публичным ключом общего сервиса. + self._emulator_pages[key] = widget # Повторное использование панели не копирует её обработчики или состояние модели. + self.addTab(widget, EMULATOR_TOOLS[key]) # Название инструмента берётся из общего каталога templates. + + def select_mcu(self, key): # Смена профиля меняет только UI и настройки; команды активации остаются явными действиями пользователя. + profile = EMULATOR_PROFILES[key] # Неизвестный MCU отвергается до изменения текущей рабочей области. + self.mcu = key # Текущий ключ используется потребителем для выбора настроек и аппаратных параметров. + with QSignalBlocker(self.mcu_selector): # Программный переход из раздела MCU не вызывает повторный вход через комбобокс. + self.mcu_selector.setCurrentIndex(self.mcu_selector.findData(key)) # Видимый выбор всегда совпадает с применённым профилем. + for name, widget in self._emulator_pages.items(): # Доступность каждого инструмента определяется сервисами выбранного порта. + self.setTabVisible(self.indexOf(widget), name in profile["tools"]) # Новая плата может подключать подмножество тех же панелей без изменения их реализации. + self.mcu_changed.emit(key) # Локальный адаптер обновляет настройки после завершения общего переключения. + return True # Вызывающая навигация может отличить выполненный переход от отказа занятого адаптера. diff --git a/python/set_devices/qt_ports/igbt_client.py b/python/set_devices/qt_ports/igbt_client.py new file mode 100644 index 0000000..132bdd0 --- /dev/null +++ b/python/set_devices/qt_ports/igbt_client.py @@ -0,0 +1,154 @@ +"""Асинхронный обмен IGBT с определением версии, записью и проверкой состояния.""" # Общий клиент последовательно проверяет плату, записывает задания и подтверждает результат полным чтением. +import struct # Распаковывает сетевые 16-битные регистры независимо от порядка байтов компьютера. + +from .qt_compat import QObject, QTimer, Signal, QSerialPort # Клиент общий для Qt6 и Qt5 и не импортирует приложение-потребитель. +from set_devices.qt_ports.stm_settings import request # Использует штатный формирователь кадров RTU управления STM. +from set_devices.tms_terminal import crc16_modbus # Проверяет CRC тем же общим алгоритмом, что остальные последовательные клиенты. +from .emulator_serial import EmulatorSerialPort, response_timeout # Тот же транспорт SET v2/RTU обслуживает эмуляторы всех поддержанных MCU. + + +class IgbtClient(QObject): # Один Qt-автомат обслуживает версии 3/мс и 4/нс без параллельного захвата COM. + finished = Signal(bool, str, object) # Возвращает успех, русское описание и подтверждённые 112 слов состояния либо None. + + def __init__(self, parent=None): # Родитель QObject связывает время жизни клиента и панели приложения. + super().__init__(parent) # Регистрирует объект в дереве Qt без открытия подключения к плате. + self.serial = EmulatorSerialPort(self) # Создаёт общий транспорт MCU с определением SET v2/RTU и проверкой DEVICE_INFO. + self.serial.readyRead.connect(self._receive) # Направляет произвольные порции принятых байтов в единственный приёмный автомат. + self.serial.errorOccurred.connect(self._error) # Обрабатывает физические ошибки COM отдельно от протокольных исключений. + self.timer = QTimer(self) # Создаёт таймер ожидания ответа транспорта, который не отмеряет длительности импульсов. + self.timer.setSingleShot(True) # Один запрос имеет один предельный срок ожидания до явного перезапуска. + self.timer.timeout.connect(lambda: self._finish(False, 'Тайм-аут ответа IGBT')) # По истечении срока освобождает COM и сообщает об отсутствии ответа платы. + self.active = False # До явного start клиент не удерживает COM и не принимает ответы как действующие. + self.rx = bytearray() # Накапливает фрагментированный RTU-кадр без предположения о границах readyRead. + + def start(self, port, unit, baud, timeout, writes=(), *, expected_version=None): # Ожидаемая версия фиксирует единицы времени, которые пользователь видел перед записью. + if self.active: # Повторный start не должен смешивать адреса и ответы двух выполняемых планов. + return # Прекращает текущую ветвь автомата после завершения действия либо отказа. + self.writes = list(writes) # Сохраняет план, но допускает его к отправке только после чтения версии платы. + self.expected_version = expected_version if expected_version is not None else 3 # Прежний публичный API записи по умолчанию использует миллисекунды версии 3. + if any(not isinstance(off, int) or not isinstance(value, int) or not 0 <= off < 112 or not 0 <= value <= 65535 for off, value in self.writes): # До открытия COM проверяет только тип и размер протокольного слова; единицы определит probe. + self.finished.emit(False, 'Недопустимые параметры IGBT', None) # Неверный план отвергается до открытия порта и не имеет физических действий. + return # Не продолжает start после отказа предварительной проверки. + self.unit, self.timeout_ms = unit, timeout # Сохраняет адрес устройства и пользовательский тайм-аут в миллисекундах ожидания связи. + self.active, self.write_sent = True, False # Отмечает активный сеанс и сбрасывает признак уже отправленных записей. + self.stage = 'probe' # Начинает новый сеанс чтением версии, чтобы не переносить единицы времени с прежней платы. + self.serial.setPortName(port) # Применяет выбранный пользователем COM к общему транспорту MCU. + self.serial.setBaudRate(baud) # Сохраняет выбранную скорость UART в бодах; для USB CDC это не скорость USB. + self.serial.setDataBits(QSerialPort.DataBits.Data8) # Устанавливает восемь бит данных штатного формата UART 8N1. + self.serial.setParity(QSerialPort.Parity.NoParity) # Отключает бит чётности согласно формату UART эмулятора. + self.serial.setStopBits(QSerialPort.StopBits.OneStop) # Задаёт один стоп-бит штатного 8N1. + self.serial.setFlowControl(QSerialPort.FlowControl.NoFlowControl) # Эмулятор не требует аппаратных RTS/CTS либо программного управления потоком. + if not self.serial.open(QSerialPort.OpenModeFlag.ReadWrite): # Не начинает запрос, если COM занят либо не может быть открыт для чтения и записи. + self._finish(False, self.serial.errorString()) # Передаёт точную аппаратную ошибку Qt и освобождает состояние автомата. + return # Не отправляет запрос после отказа открытия COM. + self._send(3, 0x1400, 16) # FC03 читает 16 слов заголовка по адресу 0x1400 до первой возможной FC06-записи. + + def _valid_writes(self, version): # Проверяет диапазоны в единицах уже опознанной прошивки, сохраняя прежние ограничения версии 3. + limits = {2: (0, 1), 6: (0, 255), 9: (0, 0), 12: (0, 1), 13: (0, 255), 14: (1, 255)} # Общие команды имеют одинаковые адреса, но их физический смысл определяется версией. + if version == 3: # Старая логическая модель продолжает принимать только миллисекундные значения. + limits.update({7: (0, 1000), 8: (1, 255)}) # Прежние общие задержка и ширина существуют только у модели версии 3. + timing = [(50, 60000)] * 5 if version == 4 else [(0, 1000), (1, 1000), (0, 1000), (1, 1000), (1, 60000)] # Версия 4 принимает реальные интервалы 50…60000 нс, без преобразования в мс. + fields = [(0, 7), (0, 3), *timing, (0, 3), (0, 60000)] # Формирует поканальные ограничения флагов, режима, времён, фронтов и FAULT. + for ch in range(8): # Проверяет все восемь независимых блоков по 12 регистров. + limits.update({16 + ch * 12 + field: bounds for field, bounds in enumerate(fields)}) # Сохраняет прежние смещения без зависимости от выбранного MCU. + if version == 4: # Измеренная компенсация входного тракта отсутствует в миллисекундной модели. + limits[26 + ch * 12] = (0, 1000) # Поле 10 блока версии 4 задаёт компенсацию в наносекундах. + return all(off in limits and limits[off][0] <= value <= limits[off][1] and not (version == 4 and off >= 16 and (off - 16) % 12 == 8 and 0 < value < 50) for off, value in self.writes) # Ненулевой FAULT также должен воспроизводиться аппаратным таймером. + + def _send(self, function, register, value): # Отправляет один кадр и устанавливает ожидание соответствующего ответа. + self.rx.clear() # Удаляет остаток прежнего кадра перед отдельным новым запросом. + self.packet = request(self.unit, function, register, value) # Сохраняет точные байты запроса для проверки адреса, длины и echo записи. + self.write_sent |= function == 6 # FC06 помечает возможность частично изменённых либо подготовленных заданий при дальнейшей потере связи. + self.timer.start(response_timeout(self.serial, self.timeout_ms)) # Добавляет транспортное время определения SET v2/RTU к ожиданию ответа IGBT. + if self.serial.write(self.packet) != len(self.packet): # Неполная передача кадра не может подтверждаться как записанная команда. + self._finish(False, 'Ошибка передачи IGBT') # Завершает сеанс при отказе записи байтов и не продолжает план. + + def _receive(self): # Собирает ответы COM независимо от фрагментации, проверяя CRC, длину и прочитанную версию. + chunk = bytes(self.serial.readAll()) # Получает текущую порцию байтов до проверки активного состояния сеанса. + if not self.active: # Поздние байты завершённого обмена не могут изменить его уже сообщённый результат. + return # Не анализирует байты вне активной транзакции. + self.rx.extend(chunk) # Сохраняет неполный ответ до получения оставшихся байтов. + function = self.packet[1] # Ожидает ту же FC03 либо FC06, которая реально отправлена текущим запросом. + while len(self.rx) >= 3: # Минимальные три байта определяют адрес, функцию и длину ответа. + if self.rx[0] != self.unit or self.rx[1] not in (function, function | 0x80): # Ищет ответ нужного узла и ожидаемой функции, включая код исключения с битом 0x80. + del self.rx[0] # Пропускает один чужой байт, сохраняя возможность найти правильный заголовок далее. + continue # Продолжает синхронизацию кадра после удаления постороннего байта. + size = 5 if self.rx[1] & 0x80 else (5 + self.rx[2] if function == 3 else 8) # Исключение занимает 5 байт, FC03 содержит byte-count плюс 5 служебных байт, echo FC06 занимает 8 байт. + if len(self.rx) < size: # Незавершённый кадр остаётся в буфере до следующего readyRead. + return # Ожидает недостающие байты, не объявляя неполный ответ ошибочным. + raw = bytes(self.rx[:size]) # Проверяет ровно ожидаемый кадр без включения следующих байтов потока. + self.timer.stop() # После полного кадра прекращает ожидание текущего запроса до его проверки. + if crc16_modbus(raw): # Ненулевой остаток Modbus CRC означает повреждённый ответ. + self._finish(False, 'Неверная CRC ответа IGBT') # Не разрешает дальнейшие записи после ошибки целостности ответа. + return # Прекращает обработку повреждённого кадра. + if raw[1] & 0x80: # Старший бит функции обозначает протокольное исключение устройства. + self._finish(False, f'Устройство отклонило запрос IGBT, код {raw[2]}') # Показывает реальный код отказа платы вместо ложного подтверждения задания. + return # Прекращает транзакцию после исключения устройства. + if function == 6: # Запись FC06 требует буквального совпадения echo с адресом и значением запроса. + if raw != self.packet: # Иное echo не может продвинуть последовательность подготовленных команд. + self._finish(False, 'Неверное подтверждение записи IGBT') # Сообщает отказ подтверждения записи и освобождает COM. + return # Не продолжает план после неверного echo. + self._next() # Переходит к следующей записи либо полному чтению подтверждённого результата. + return # Один вызов обработчика подтверждает только один ожидаемый кадр. + count = int.from_bytes(self.packet[4:6], 'big') # Число слов извлекается из реально переданного FC03 в сетевом порядке байтов. + if len(raw) != 5 + count * 2 or raw[2] != count * 2: # Проверяет и общую длину кадра, и byte-count, где каждое слово занимает два байта. + self._finish(False, 'Неверная длина состояния IGBT') # Не распаковывает короткий либо чрезмерный снимок состояния. + return # Прекращает обработку кадра неверной длины. + words = struct.unpack(f'>{count}H', raw[3:-2]) # Распаковывает ровно count беззнаковых 16-битных регистров big-endian, исключая адрес, заголовок и CRC. + version = words[1] # Версия задаёт единицы времени и проверяется заново при каждом открытии COM. + if words[0] != 0x4947 or version not in (3, 4) or words[10:12] != (8, 0 if version == 4 else 1) or words[15] != 12: # Принимает только известные структуры и явный код наносекунд у аппаратной версии 4. + self._finish(False, 'Требуется IGBT версии 3 (мс) или версии 4 (аппаратные нс) с 8 каналами') # Не допускает управление неизвестным форматом регистров. + return # Не управляет неизвестной структурой либо кодом единиц времени. + if self.stage == 'probe': # Заголовок должен подтвердить версию и единицы до чтения полного состояния и FC06. + self.interface_version = version # Сохраняет результат probe для проверки полного снимка и запрета смены единиц посреди обмена. + if self.writes and any(item != (2, 0) for item in self.writes) and version != self.expected_version: # Запись времён требует совпадения единиц; безусловный останов одинаков у обеих версий и остаётся доступным. + self._finish(False, 'Версия IGBT и единицы времени изменились; прочитайте состояние и примените задания заново') # Завершает обмен до первой записи, сохраняя выходы платы. + return # Не отправляет подготовленные в других единицах значения. + if not self._valid_writes(version): # Проверяет все записи до первой команды FC06. + self._finish(False, 'Недопустимые параметры IGBT для прочитанной версии прошивки') # Ошибка диапазона также не оставляет частично отправленного задания. + return # Не начинает запись неверного профиля. + self.stage = 'state' # После probe начинает этап полного чтения известных поканальных заданий. + self._send(3, 0x1400, 112) # Полный FC03 запрашивает 112 слов окна IGBT, включая все восемь каналов. + return # Ожидает полный снимок отдельным следующим ответом. + if version != self.interface_version: # Не допускает подмену протокола между заголовком и полным чтением. + self._finish(False, 'Версия IGBT изменилась во время обмена; повторите чтение') # Прерывает транзакцию до дальнейших записей или ложного подтверждения. + return # Требует нового определения единиц времени. + if self.stage == 'state' and self.writes: # Записи выполняются только после успешного полного чтения известной версии. + self.pending = list(self.writes) # Копирует проверенный план, сохраняя исходный список для сравнения чтением. + self.stage = 'write' # Отмечает этап последовательного выполнения FC06. + self._next() # Отправляет первую подготовленную команду после завершения всех предварительных чтений. + else: # Ветка без новых записей либо после их выполнения возвращает фактический снимок. + # Счётчик может измениться сразу после сброса из-за нового внешнего фронта. + expected = dict(self.writes) # При повторной записи одного смещения проверяется последнее отправленное значение. + if any(words[off] != value for off, value in expected.items() if off not in (9, 14)): # Команда импульса 14 и изменяемый фронтами счётчик 9 исключены из буквального readback; остальные задания должны совпасть. + self._finish(False, 'Записанные параметры IGBT не подтвердились') # Отклоняет успешное echo, если последующее чтение не подтвердило задания. + else: # Подтверждение выдаётся только после сравнения фактических регистров с планом. + self._finish(True, 'IGBT: параметры записаны и проверены' if self.writes # Отличает успешную запись с проверкой от обычного чтения без физических действий. + else 'IGBT: состояние прочитано', words) # Передаёт панели полный подтверждённый снимок после чтения либо readback. + return # Завершает обработку одного ожидаемого ответа текущего шага. + + def _next(self): # Продвигает проверенный план без параллельных запросов на общий COM. + if self.pending: # Следующая запись разрешается только после echo предыдущей команды. + off, value = self.pending.pop(0) # Извлекает одно относительное смещение и соответствующее 16-битное значение. + self._send(6, 0x1400 + off, value) # FC06 использует прежнюю абсолютную базу 0x1400 плюс смещение регистра. + else: # После последнего echo начинается подтверждение всего результата чтением. + self.stage = 'verify' # Отмечает этап проверки, чтобы полный ответ уже не запускал новый план записи. + self._send(3, 0x1400, 112) # Подтверждает все восемь каналов одним FC03 на 112 слов. + + def _error(self, error): # Значимые физические ошибки Qt завершают обмен, тайм-ауты обрабатываются собственным таймером. + if self.active and error not in (QSerialPort.SerialPortError.NoError, # Не выдаёт NoError за отказ и не завершает неактивный сеанс поздним сигналом. + QSerialPort.SerialPortError.TimeoutError): # Qt TimeoutError не дублирует собственный контролируемый тайм-аут ответа IGBT. + self._finish(False, self.serial.errorString()) # Показывает точную аппаратную причину отказа COM и освобождает транспорт. + + def cancel(self): # Отмена прерывает текущую транзакцию, не заменяя команду физического останова платы. + self._finish(False, 'Обмен IGBT отменён') # Запрещает дальнейшую отправку плана и сообщает пользователю отмену обмена. + + def _finish(self, ok, message, words=None): # Единая точка завершения освобождает COM, таймер и блокировку UI при любом исходе. + if not self.active: # Поздний timeout либо error не должен отправлять повторный результат завершённого обмена. + return # Не изменяет состояние и не повторяет finished для уже завершённого сеанса. + self.active = False # Снимает блокировку последовательного автомата до уведомления панели. + self.timer.stop() # Прекращает транспортное ожидание, которое уже не относится к активному запросу. + self.serial.close() # Освобождает общий COM для настроек STM и других разрешённых инструментов. + if not ok and self.write_sent: # После отправленной FC06 нельзя считать прежнее состояние платы подтверждённым при потере связи. + message += '. Часть настроек могла примениться; прочитайте состояние повторно.' # Напоминает перечитать действующие и подготовленные задания после частичного обмена. + self.finished.emit(ok, message, words) # Передаёт панели успех, причину отказа и только подтверждённый снимок либо None. diff --git a/python/set_devices/qt_ports/stm_settings.py b/python/set_devices/qt_ports/stm_settings.py index 3f41bee..bfa0f8b 100644 --- a/python/set_devices/qt_ports/stm_settings.py +++ b/python/set_devices/qt_ports/stm_settings.py @@ -7,6 +7,7 @@ import struct from .qt_compat import QObject, QTimer, Signal from .qt_compat import QSerialPort +from set_devices.mcu_profiles import EMULATOR_MODES # Допустимые номера режимов берутся из общего каталога, включая обе роли DEIF. from set_devices.tms_terminal import crc16_modbus BAUDRATES = (9600, 19200, 38400, 57600, 115200) @@ -24,7 +25,7 @@ def decode_config(raw): if words[0] != 0x5343 or words[1] not in (2, 3): raise ValueError("Прошивка STM не поддерживает настройку связи (нужна новая версия)") address, tms, rate = words[2:5] - if not 1 <= address <= 247 or not 1 <= tms <= 255 or address == tms or rate >= len(BAUDRATES) or words[8] > (3 if words[1] == 3 else 1) or words[9] > (3 if words[1] == 3 else 1): + if not 1 <= address <= 247 or not 1 <= tms <= 255 or address == tms or rate >= len(BAUDRATES) or words[8] not in (EMULATOR_MODES if words[1] == 3 else (0, 1)) or words[9] not in (EMULATOR_MODES if words[1] == 3 else (0, 1)): # Версия 3 C-сервера поддерживает режимы 0…5; версия 2 сохраняет только УМП и 2812. raise ValueError("STM вернула неверные параметры связи") return words @@ -52,7 +53,7 @@ class StmSettingsClient(QObject): return if desired is not None: addr, tms, rate, mode = desired - if not 1 <= addr <= 247 or not 1 <= tms <= 255 or addr == tms or rate not in BAUDRATES or mode not in (0, 1, 2, 3): + if not 1 <= addr <= 247 or not 1 <= tms <= 255 or addr == tms or rate not in BAUDRATES or mode not in EMULATOR_MODES: # Номера 4 и 5 выбирают DEIF Master/Slave того же общего C-сервера. self.finished.emit(False, "Адреса УМП и 2812 должны различаться; проверьте диапазоны и скорость", None) return self.unit, self.baud, self.timeout_ms = unit, baud, timeout @@ -120,7 +121,7 @@ class StmSettingsClient(QObject): return addr, tms, baud, mode = self.desired if mode >= 2 and words[1] < 3: - raise ValueError("Обновите прошивку STM: для отдельных режимов IGBT и ЦАП нужна версия настроек 3") + raise ValueError("Обновите прошивку STM: для IGBT, ЦАП и DEIF нужна версия настроек 3") # Сообщение учитывает обе роли DEIF и возможное применение настроек при потере ответа. self.staged = (addr, tms, BAUDRATES.index(baud), mode) self.steps = [(6, 0x1218, 0), (6, 0x1215, addr), (6, 0x1216, tms), (6, 0x1217, self.staged[2]), (6, 0x1219, mode), (3, 0x1210, 10)] @@ -173,5 +174,5 @@ class StmSettingsClient(QObject): if self.serial.isOpen(): self.serial.close() if not ok and self.committed: - message += " Возможно, STM уже применила новые значения: адрес УМП %d, адрес 2812 %d, %d бод, режим %d (0=УМП, 1=2812, 2=IGBT, 3=ЦАП). Повторите чтение по ним или перезагрузите плату." % self.desired + message += " Возможно, STM уже применила новые значения: адрес УМП %d, адрес 2812 %d, %d бод, режим %d (0=УМП, 1=2812, 2=IGBT, 3=ЦАП, 4=DEIF Master, 5=DEIF Slave). Повторите чтение по ним или перезагрузите плату." % self.desired # Сообщение учитывает обе роли DEIF и возможное применение настроек при потере ответа. self.finished.emit(ok, message, values) diff --git a/python/set_devices/ump_logger.py b/python/set_devices/ump_logger.py index def1a43..dd5e312 100644 --- a/python/set_devices/ump_logger.py +++ b/python/set_devices/ump_logger.py @@ -22,6 +22,12 @@ FAST_CAPABILITY = 0x1220 FAST_DATA = 0x2000 WORDS = 40 CAPACITY = 64000 // (2 * WORDS) +# Компактная запись v4 имеет 12 слов; старые 40/42 слова остаются поддержанными для чтения архивов. +COMPACT_WORDS = 12 +# Ёмкость 760 точек сохраняет прежнее число записей постинтервала и поведение кольцевых банков. +COMPACT_CAPACITY = 760 +# Ключи соответствуют индексам оставшихся полей v2/v3, значения — индексам этих же каналов в компактном v4. +COMPACT_INDEX = {2: 2, 3: 3, 4: 4, 5: 5, 9: 6, 24: 7, 25: 8, 40: 9, 41: 10} FIELDS = ( ('off_trigger', 'Событие отключения', 2, 8), ('post_truncated', 'Усечение постинтервала', 2, 9), @@ -33,68 +39,37 @@ FIELDS = ( ('start_out', 'Выход START_DPTB', 5, 0), ('stop_out', 'Выход STOP_DPTB', 5, 1), ('res_out', 'Выход RES_OUT_2', 5, 2), - ('impulse', 'Остаток импульса, мс', 6, None), - ('wake', 'Инициализация ЦАП, тики ЦАП', 7, None), - ('dac', 'Код ЦАП', 8, None), ('current', 'Расчётное задание тока, мА', 9, None), - ('sensor0', 'Измерение 0', 10, None), - ('sensor1', 'Измерение 1', 11, None), - ('sensor2', 'Измерение 2', 12, None), - ('sensor3', 'Измерение 3', 13, None), - ('error0', 'Ошибки 0 (маска)', 14, None), - ('error1', 'Ошибки 1 (маска)', 15, None), - ('error2', 'Ошибки 2 (маска)', 16, None), - ('error3', 'Ошибки 3 (маска)', 17, None), - ('can_header', 'CAN адрес/маска', 18, None), - ('can0', 'CAN слово 0', 19, None), - ('can1', 'CAN слово 1', 20, None), - ('can2', 'CAN слово 2', 21, None), - ('can_count', 'Количество CAN RX (mod 65536)', 22, None), - ('can_timeout', 'Таймауты CAN TX (mod 65536)', 23, None), - ('commands', 'Команды (маска)', 3, None), ('go', 'Начальная уставка, мА', 24, None), ('stop', 'Конечная уставка, мА', 25, None), - ('dac_min', 'Код калибровки 4 мА', 26, None), - ('dac_max', 'Код калибровки 20 мА', 27, None), - ('dac_cal', 'Калибровочный код ЦАП', 28, None), - ('dac04', 'DAC_04 (регистр)', 29, None), - ('dac20', 'DAC_20 (регистр)', 30, None), - ('ramp', 'Счётчик разгона', 31, None), - ('duration', 'Длительность разгона, тики ЦАП', 32, None), - ('effective_go', 'Начальная уставка после ограничений, мА', 33, None), - ('effective_stop', 'Конечная уставка после ограничений, мА', 34, None), - ('position', 'Положение разгона (kod)', 35, None), - ('adc0', 'АЦП канал 0', 36, None), - ('adc1', 'АЦП канал 1', 37, None), - ('adc2', 'АЦП канал 2', 38, None), - ('adc3', 'АЦП канал 3', 39, None), ('zpt1', 'ЗПТ1: U1 + U2 (ПМ67, рег. 306)', 40, None), ('zpt2', 'ЗПТ2: U3 + U4 (ПМ67, рег. 9)', 41, None), ) -def request(controller: int, function: int, address: int, value: int, *, record_words: int = WORDS) -> bytes: - if not 0 <= controller <= 255 or not 0 <= value <= 65535: - raise ValueError('Недопустимый адрес контроллера или значение') - if record_words not in (40, 42): - raise ValueError('Неверный размер записи логгера') - capacity = {40: 800, 42: 760}[record_words] - if function == 3: - valid = ((address == PROTECTION and value == 8) or (address == BASE and value == 16) or - (address == DATA and 1 <= value <= 120 and (value % WORDS == 0 or value in (42, 84))) or (address == LIVE and value == 124) or (address == EMU_CONTROL and value == 4) - or (address == FAST_CAPABILITY and value == 4) - or (FAST_DATA <= address < FAST_DATA + capacity * record_words - and (address - FAST_DATA) % record_words == 0 - and 1 <= value <= 120 and value % record_words == 0 - and address + value <= FAST_DATA + capacity * record_words)) - else: - valid = function == 6 and ((address == PROTECTION + 2 and value in (0, 1, 2, 3)) or - (address == PROTECTION + 3 and 1 <= value <= 60000) or - address in (BASE, BASE + 1, BASE + 2, BASE + 3) or - (address == EMU_CONTROL + 2 and value in (0, 1))) - if not valid: - raise ValueError('Недопустимый запрос логгера УМП') - return protocol.with_crc(bytes((controller, function)) + address.to_bytes(2, 'big') + value.to_bytes(2, 'big')) +def request(controller: int, function: int, address: int, value: int, *, record_words: int = WORDS) -> bytes: # Проверяет запрос с учётом ширины записи, прочитанной из статуса платы. + if not 0 <= controller <= 255 or not 0 <= value <= 65535: # Ограничивает адрес одним октетом, значение — 16-битным словом. + raise ValueError('Недопустимый адрес контроллера или значение') # Запрещает усечение входных параметров при упаковке. + if record_words not in (COMPACT_WORDS, 40, 42): # Допускает только известные компактный и прежние форматы записи. + raise ValueError('Неверный размер записи логгера') # Не позволяет строить адреса по неизвестной ширине. + capacity = {COMPACT_WORDS: COMPACT_CAPACITY, 40: 800, 42: 760}[record_words] # Выбирает реальную границу банка по формату. + if function == 3: # Разрешает только существующие диагностические блоки чтения. + valid = ((address == PROTECTION and value == 8) or (address == BASE and value == 16) # Читает полный блок защиты либо дескриптор журнала. + or (address == DATA and 1 <= value <= 120 and (value % COMPACT_WORDS == 0 or value in (40, 80, 42, 84))) # Принимает целые записи v4 и исторические блоки v2/v3. + or (address == LIVE and value == 124) or (address == EMU_CONTROL and value == 4) # Сохраняет фиксированные размеры онлайн-блока и управления эмуляцией. + or (address == FAST_CAPABILITY and value == 4) # Проверяет возможность ускоренного архивного чтения. + or (FAST_DATA <= address < FAST_DATA + capacity * record_words # Ограничивает адрес началом и концом реального банка. + and (address - FAST_DATA) % record_words == 0 # Требует начала блока на границе записи. + and 1 <= value <= 120 and value % record_words == 0 # Передаёт до 120 слов, содержащих целое число записей. + and address + value <= FAST_DATA + capacity * record_words)) # Исключает пересечение конца банка. + else: # Запись разрешена только прежним управляющим адресам. + valid = function == 6 and ((address == PROTECTION + 2 and value in (0, 1, 2, 3)) # Проверяет маску эмуляции защиты. + or (address == PROTECTION + 3 and 1 <= value <= 60000) # Проверяет тайм-аут свежести CAN в миллисекундах. + or address in (BASE, BASE + 1, BASE + 2, BASE + 3) # Оставляет команды управления журналом без запуска УМП. + or (address == EMU_CONTROL + 2 and value in (0, 1))) # Сохраняет двоичное включение эмулятора. + if not valid: # Запрещает запросы вне согласованных адресов и размеров. + raise ValueError('Недопустимый запрос логгера УМП') # Возвращает прежнее понятное сообщение вызывающему коду. + return protocol.with_crc(bytes((controller, function)) + address.to_bytes(2, 'big') + value.to_bytes(2, 'big')) # Передаёт 16-битный адрес и добавляет общий Modbus CRC. @dataclass(frozen=True) @@ -114,27 +89,27 @@ class Status: @classmethod def decode(cls, words): if (len(words) != 16 or words[0] != 0x554D or - (words[1], words[4], words[5]) not in ((2, 40, 800), (3, 42, 760))): - raise ValueError('Прошивка не поддерживает логгер УМП v2/v3') + (words[1], words[4], words[5]) not in ((2, 40, 800), (3, 42, 760), (4, COMPACT_WORDS, COMPACT_CAPACITY))): # Проверяет согласованные версию, ширину и ёмкость. + raise ValueError('Прошивка не поддерживает логгер УМП v2/v3/v4') # Перечисляет известные форматы без разрешения неизвестной прошивки. if words[9] != 6: raise ValueError('Логгер УМП доступен только на плате нагрузки dsk_LOAD') - if words[2] not in (0, 1, 2, 3) or words[3] > words[5] or not 1 <= words[6] <= 1000 or words[11] != 1000 or words[13] > words[5] or words[14] > 1000 or words[15] not in (0, 1, 3): + post_limit = max(1000, min(65535, words[5] // 10 * words[6])) if words[1] >= 3 else 1000 # Постинтервал v3/v4 занимает 10% точек; при 760 точках и 20 мс его оценка достигает 1520 мс. + if words[2] not in (0, 1, 2, 3) or words[3] > words[5] or not 1 <= words[6] <= 1000 or words[11] != 1000 or words[13] > words[5] or words[14] > post_limit or words[15] not in (0, 1, 3): raise ValueError('Повреждён статус логгера') return cls(words[2], words[3], words[6], words[10], words[11], *words[12:16], words[4], words[5]) def sample(words, frequency=1000): - if len(words) not in (40, 42) or frequency <= 0: + if len(words) not in (COMPACT_WORDS, 40, 42) or frequency <= 0: # Допускает только известную ширину записи и положительную частоту времени. raise ValueError('Неверная запись логгера') result = {'time_ms': (words[0] | words[1] << 16) * 1000 / frequency, 'event': words[2]} for key, _label, index, bit in FIELDS: - value = words[index] if index < len(words) else float('nan') + physical_index = COMPACT_INDEX[index] if len(words) == COMPACT_WORDS else index # Выбирает индекс оставшегося поля по фактической версии записи. + value = words[physical_index] if physical_index < len(words) else float('nan') # ЗПТ в старых 40-словных архивах остаётся неизвестным. if bit is not None: value = (value >> bit) & 1 - elif 10 <= index <= 13 and value >= 32768: - value -= 65536 # Физические единицы приводим здесь, одинаково для CSV и графика. - if key in ('current', 'effective_go', 'effective_stop'): + if key == 'current': # Сохранившееся задание имеет масштаб 0,1 мА; уставки и напряжения передаются целыми единицами. value /= 10.0 result[key] = value return result diff --git a/python/set_devices/ump_logger_can.py b/python/set_devices/ump_logger_can.py index 6e23c5e..902de20 100644 --- a/python/set_devices/ump_logger_can.py +++ b/python/set_devices/ump_logger_can.py @@ -27,7 +27,8 @@ def build_request(mode, token, function, address, value): if not 1 <= token <= 255: raise ValueError('Неверный номер CAN-запроса') valid = ((function == 3 and ((address == PROTECTION and value == 8) or (address == BASE and value == 16) or - (address == DATA and value in (40, 80, 120, 42, 84)) or + # До 120 слов передают целые 12-словные записи v4; старые блоки v2/v3 остаются разрешены. + (address == DATA and (value in (40, 80, 42, 84) or 0 < value <= 120 and value % 12 == 0)) or (address == LIVE and value == MAX_WORDS) or (address == EMU_CONTROL and value == 4))) or (function == 6 and ((BASE <= address <= BASE+3 and 0 <= value <= 65535) or (address == PROTECTION+2 and value in (0, 1, 2, 3)) or diff --git a/python/tests/test_can_boot_services.py b/python/tests/test_can_boot_services.py new file mode 100644 index 0000000..ede386f --- /dev/null +++ b/python/tests/test_can_boot_services.py @@ -0,0 +1,86 @@ +from types import SimpleNamespace +import struct +import pytest + +from protocan.can_boot import CanBootServices, CanBootTarget, CanBootTransfer, CanBootPingExchange +from protocan.protocan import ProtoCanId +from protocan.transport import build_frame + + +def response(command, data, device=7): + return build_frame(ProtoCanId.build(1, 1, 3, device, 13, command), data, to_can=False) + + +def test_passport_and_discovery_address_filters(): + service = CanBootServices(CanBootTarget(device_type=3, device=7, product_type=0x2833)) + identify = response(1, struct.pack('", direction="RX", payload=b"A\x00\xff") # Payload содержит печатный, управляющий и не-ASCII байты. + console.display.setCurrentText("HEX + ASCII") # Выбираем совместное представление байтов. + assert console.toPlainText() == "RX пакет <текст> · 41 00 FF | A.." # Непечатные байты заменяются точками без потери HEX. + path = tmp_path / "журнал.txt" # Проверяем кириллицу в имени и содержимом файла. + console.save_to(path) # Экспорт выполняется без диалога, сохраняя тот же код записи. + assert path.read_text(encoding="utf-8") == console.toPlainText() # UTF-8 сохраняет фактически видимый текст. + console.copy_visible() # Кнопка копирует весь показанный журнал. + assert QApplication.clipboard().text() == console.toPlainText() # Буфер обмена совпадает с экспортом. + + +def test_multiline_html_and_snapshot_obey_limit(console): # Предел относится к строкам, а не к числу вызовов записи. + console.appendPlainText("0\n1\n2\n3\n4") # Один пакет расшифровки превышает лимит документа и истории. + console.refresh() # Применяем запланированное пакетное обновление. + assert console.toPlainText() == "2\n3\n4" # Старые строки не возвращаются при смене фильтра. + console.setPlainText("снимок") # Потребитель может передать результат повторного разбора кадров целиком. + console.appendHtml('<ошибка>') # Проверяем совместимость прежнего цветного API SETGUI. + console.search.setText("ошибка") # Поиск должен работать по тексту без тегов разметки. + assert console.toPlainText() == "<ошибка>" # Спецсимволы устройства остаются обычным текстом. + console.search.clear() # Возвращаем обе записи с исходным оформлением. + assert console.toPlainText() == "снимок\n<ошибка>" # Фильтр не теряет предыдущий снимок истории. + + +def test_clear_notifies_external_owner_once(console): # Владелец может очистить свой буфер и повторно вызвать clear без рекурсии. + external = ["старый кадр"] # Имитируем отдельную историю протокольных кадров приложения. + def clear_owner(): # Обработчик очищает внешний источник повторного форматирования. + external.clear() # Старые кадры не вернутся после смены парсера. + console.clear() # Повторный программный вызов не должен снова эмитировать пользовательский сигнал. + console.userCleared.connect(clear_owner) # Подключаем тот же контракт, что консоли платы и TX/RX SETGUI. + console.appendPlainText("строка") # До очистки журнал содержит данные. + console.clear_button.click() # Нажимаем настоящую кнопку Qt. + assert not external and not console.toPlainText() # Обе истории очищены одним действием. diff --git a/python/tests/test_deif_shared.py b/python/tests/test_deif_shared.py new file mode 100644 index 0000000..a859f1c --- /dev/null +++ b/python/tests/test_deif_shared.py @@ -0,0 +1,19 @@ +"""Общие DEIF-векторы проверяют ctypes теми же данными, что C и Android/JVM.""" # Тесты не требуют Qt или структуры Desktop-приложения. +from pathlib import Path # Fixture входит в общий репозиторий templates. +import pytest # Параметризация даёт независимый результат для каждой эталонной строки. +from set_devices.deif_native import get_deif_native # Python не использует альтернативный декодер при отсутствии C. +from set_devices.deif_display import DeifDisplay # Пассивная модель является общим API библиотеки. +FIXTURE = Path(__file__).resolve().parents[2] / 'c/set-protocol/tests/fixtures/deif-xdi-v1.tsv' # Точный общий источник тестов для трёх портов. +CASES = [line.split() for line in FIXTURE.read_text(encoding='utf-8').splitlines() if line and not line.startswith('#')] # Здесь разбирается текст fixture, а не протокол CAN. +@pytest.mark.parametrize('row', CASES) # Каждый ошибочный или валидный wire-кадр проверяется отдельно. +def test_ctypes_matches_c_and_jni_vectors(row): # Числовой результат должен совпасть с независимым описанием ожидаемого кадра. + identifier, payload, flags, result, raw, index, sub = row # Столбцы fixture не зависят от внутреннего layout C. + flags = int(flags) # EXT/RTR являются входными метаданными теста. + code, meta = get_deif_native().inspect_frame(int(identifier, 16), bytes.fromhex(payload), bool(flags & 1), bool(flags & 2)) # Wire-разбор выполняется единственным C-кодеком. + assert (code, meta[4], meta[2], meta[3]) == (int(result), int(raw), int(index, 16), int(sub, 16)) # RAW и адрес объекта совпадают с C- и Kotlin-проверкой. +def test_passive_angle_is_received_without_gui_or_simulation(): # Ошибка со снимка воспроизводится без запуска серверных сервисов. + model = DeifDisplay(source='CAN / мост', device_node=13) # Физический адрес SLAVE не становится источником SAM. + assert model.accept('CAN / мост', 0x201, bytes.fromhex('01 01 30 07 84 03 00 00'), now=10) # Точный кадр пользователя несёт RAW 900. + assert model.angle_selection(now=10) == (90.0, True) # Сетевое задание видно как 90°, с явной пометкой. + assert model.value('angle', now=10) is None # Принятое задание не превращается в фиктивный фактический объект 0x02. + assert model.angle_selection(now=15.001) == (None, False) # При полном молчании наблюдатель уважает прежний срок свежести пять секунд. diff --git a/python/tests/test_firmware_clients.py b/python/tests/test_firmware_clients.py index ced0d52..32bbf7d 100644 --- a/python/tests/test_firmware_clients.py +++ b/python/tests/test_firmware_clients.py @@ -126,7 +126,10 @@ def test_legacy_can_full_transaction_and_retransmission(): assert all(ProtoCanId.parse(f.can_id).msg_type == 11 for f in frames) frames, _ = t.handle_status(status(t, 0, code=8, expected=8)) assert ProtoCanId.parse(frames[0].can_id).body == 8 - assert frames[-1].data == bytes([128,129]) + b"\xff" * 6 + assert [ProtoCanId.parse(frame.can_id).body for frame in frames] == list(range(8, 16)) # Восстановление повторяет хвост до абсолютной границы ACK 16 и не посылает преждевременно блок следующего окна. + frames, _ = t.handle_status(status(t, 0, expected=16)) # Настоящее ядро подтверждает блок 16 до передачи последнего неполного блока 16. + assert len(frames) == 1 and ProtoCanId.parse(frames[0].can_id).body == 16 # После ACK предыдущего окна остаётся ровно один блок образа из 130 байт. + assert frames[0].data == bytes([128,129]) + b"\xff" * 6 # Дополнение последнего блока до восьми байт сохраняет прежний wire-формат. frames, _ = t.handle_status(status(t, 0, expected=17)) assert t.stage == "verify" for cmd in (6, 7, 9): diff --git a/python/tests/test_gas_slots.py b/python/tests/test_gas_slots.py new file mode 100644 index 0000000..cf3aec3 --- /dev/null +++ b/python/tests/test_gas_slots.py @@ -0,0 +1,63 @@ +import json # Общие машинные эталоны независимы от клиентского построителя кадра. +from pathlib import Path # Находим спецификацию относительно репозитория. +import unittest # Проверяем реальные ctypes-привязки без заглушки протокольного ядра. +from protocan.gas_slots import GasSlots # Все правила wire-формата выполняет C, а не тестовая модель. +from protocan import protocan as pc # Проверяем штатный CAN-декодер, который вызывают GUI и журналы. + +class GasSlotTests(unittest.TestCase): # Интеграционные проверки обоих типов GAS и границ адресного API. + def setUp(self): # Каждая проверка использует настоящую собранную shared-библиотеку. + self.codec = GasSlots() # Отсутствующая библиотека не заменяется Python fallback. + + def test_vectors(self): # Проверяем ID, маску и три значения по нормативным независимым байтам. + path = Path(__file__).resolve().parents[2] / 'doc/setcan/protocan/examples/gas-slot-vectors.json' # Те же примеры опубликованы в документации. + vectors = json.loads(path.read_text(encoding='utf-8')) # UTF-8 сохраняет названия и описание профиля. + for item in vectors['vectors']: # Охватываем обе группы адресов и неполный последний слот PERIPH. + words = item.get('words', vectors['words']) # Последний слот имеет только два действующих значения. + expected = item.get('payload_hex', vectors['payload_hex']) # Его отдельный эталон не включает несуществующее третье значение. + can_id, data = self.codec.frame(item['mode'], item['local_slot']) # Пустой запрос не несёт служебной маски. + self.assertEqual((can_id, data), (int(item['request_id'], 16), b'')) # Тип 0x4 и адрес должны совпасть с фиксированным эталоном. + reply, payload = self.codec.frame(item['mode'], item['local_slot'], words, route=1) # Ответ явно содержит маску достоверности. + self.assertEqual(reply, int(item['response_id'], 16)) # Направление не меняет узел или слот. + self.assertEqual(payload.hex().upper(), expected) # Проверяем все восемь октетов, включая расположение Word0. + self.assertEqual(self.codec.decode(reply, payload), (item['mode'], item['local_slot'], tuple(words))) # Полный round-trip сохраняет маску отдельно от трёх значений. + + def test_invalid(self): # Неверные координаты, маски и длины не должны стать другой командой. + for mode, slot in ((32, 0), (5, 67), (-1, 0), (2**32, 0)): # Верхняя граница страницы после маски — LocalSlot 66. + with self.assertRaises(ValueError): self.codec.frame(mode, slot) # Ошибка не маскируется до допустимого адреса. + for payload in (b'\0', b'\0' * 6, b'\0' * 9, b'\0' * 8): # В том числе запрещена полная запись с пустой маской. + with self.assertRaises(ValueError): self.codec.decode(0x19540500, payload) # Точный размер и Word0 проверяет C. + for mask in (0, 1, 0x10, 0xFFFF): # Бит 0 и старшие биты не адресуют данные слота. + with self.assertRaises(ValueError): self.codec.frame(5, 0, [mask, 1, 2, 3]) # Не заменяем отвергнутую маску полной записью. + with self.assertRaises(ValueError): self.codec.frame(5, 66, [14, 1, 2, 3]) # Третье значение неполного слота не существует. + with self.assertRaises(ValueError): self.codec.frame(5, 0, [2, 65536, 0, 0]) # Переполнение u16 не превращается в допустимый ноль. + can_id, payload = self.codec.frame(5, 0, [4, 0, 0x1234, 0], route=1) # Корректный частичный ответ для проверки транспортных флагов. + with self.assertRaises(ValueError): self.codec.decode(can_id, payload, flags=3) # RTR отвергается до обращения к provider. + + def test_types_are_unambiguous(self): # Один и тот же payload получает разный смысл только по номеру типа. + can_id, payload = self.codec.frame(5, 0, [4, 0, 0x1234, 0], route=1) # Word2 выбран, Word1/Word3 передаются в фиксированных позициях и игнорируются. + slot = pc.decode(can_id, payload) # Никакого параметра gas_profile для типа 0x4 больше нет. + self.assertIn('slot=0x0500', slot.summary) # Адрес показывается в единицах слота. + self.assertIn('mask=0x0004', slot.summary) # В CAN-журнале видна частичная запись. + self.assertIsNone(slot.registers) # Старые потребители не получают фиктивный последовательный список регистров. + self.assertTrue(any('Word2' in name for name, value in slot.fields)) # Только выбранная позиция отображается как достоверное значение. + self.assertFalse(any('Word1' in name or 'Word3' in name for name, value in slot.fields)) # Неотмеченные поля не публикуются как измерения. + register = pc.decode(0x19530500, payload) # Тип 0x3 всегда интерпретируется как обычные последовательные слова. + self.assertEqual(register.registers, [(0x0500, 4), (0x0501, 0), (0x0502, 0x1234), (0x0503, 0)]) # Нулевое слово payload не является маской регистрового GAS. + self.assertTrue(pc.decode(can_id, payload + b'\0').warnings) # Девятый октет не теряется до проверки слотного формата. + overflow = pc.decode(0x1953FFFF, b'\x01\x00\x02\x00') # По максимальному адресу нельзя разместить два последовательных регистра. + self.assertTrue(overflow.warnings) # Ошибка диапазона должна быть видна в журнале. + self.assertIsNone(overflow.registers) # Некорректный адрес 0x10000 не становится источником тренда. + + def test_generic_address_and_analyzer(self): # Тип 0x4 должен работать также за пределами PERIPH и его HEX-страниц. + can_id, payload = self.codec.frame_address(7, 14, 0xFFFF, [2, 0x5678, 0xDEAD, 0], route=1) # Неотмеченное значение сохраняется как обычный заполнитель и не является командой записи. + self.assertEqual(can_id, 0x1FE4FFFF) # Полный адрес FFFF принадлежит отдельному инвертору 7/E. + self.assertEqual(self.codec.decode_address(can_id, payload), (2, 0x5678, 0xDEAD, 0)) # Общий декодер проверяет маску, не навязывая страницу mode. + self.assertIn('slot=0xFFFF', pc.decode(can_id, payload).summary) # Штатный GUI-декодер использует общий адресный API. + with self.assertRaises(ValueError): self.codec.frame_address(7, 14, 0x10000) # Не допускаем оборачивания в слот ноль. + from logic_analyzer.decoders.set_can import legacy # Проверяем тот же публичный путь анализа аппаратного захвата. + decoded = legacy(can_id, payload) # Анализатор вызывает общий C-кодек слотного формата. + self.assertEqual(decoded['slot_words'], [(1, 0x5678)]) # Служебная маска и невыбранные слова не становятся данными анализатора. + self.assertNotIn('registers', decoded) # Не смешиваем координаты слота с плоским регистровым адресом. + +if __name__ == '__main__': # Поддерживаем прямой запуск без pytest. + unittest.main() # Любой отказ native-кодека отражается стандартным статусом тестов. diff --git a/python/tests/test_gas_watch.py b/python/tests/test_gas_watch.py new file mode 100644 index 0000000..4b5460a --- /dev/null +++ b/python/tests/test_gas_watch.py @@ -0,0 +1,169 @@ +# Проверяем неизменяемые модели и настоящий C ABI GAS_WATCH2 на общих эталонных байтах. +# Python не подменяет C-кодек: проверки wire-пакетов выполняются только с указанной SETPROTOCOL_LIBRARY. + +import ctypes # Загружаем настоящую общую библиотеку для проверки границы Python/C. +import json # Читаем общий JSON-fixture, используемый также C- и JVM-проверками. +import os # Путь к проверяемой сборке получает тестовый процесс через SETPROTOCOL_LIBRARY. +import unittest # Запускаем воспроизводимые проверки модели, подписок и ошибочных данных. +from dataclasses import FrozenInstanceError # Проверяем запрет изменения уже созданных моделей. +from pathlib import Path # Находим эталон относительно исходников независимо от текущего каталога. + +from protocan.gas_watch import GasWatchConfig, GasWatchSample, NativeGasWatch # Проверяем публичный тонкий порт без доступа к другому Python-кодеку. +from protocan.protocol import MessageType # Проверяем выделение новых типов сообщений без изменения старых значений. + +FIXTURE_PATH = Path(__file__).resolve().parents[2] / "c/set-protocol/tests/fixtures/gas-watch-v2.json" # Общие байты находятся рядом с C-тестами как единый контракт портов. + + +class GasWatchModelTests(unittest.TestCase): # Эти проверки не требуют DLL, поскольку относятся к представлению моделей Python. + def test_models_copy_sequences_and_are_frozen(self): # Изменение исходных списков не должно менять ожидаемый ACK и принятую выборку. + addresses = [0, 1, 0xFF01] # Повторяем три разрозненных адреса из пользовательского примера. + config = GasWatchConfig(1, 100, addresses) # Переданный список должен быть независимо сохранён как кортеж. + addresses[0] = 99 # Моделируем последующее редактирование таблицы сигналов GUI. + self.assertEqual((0, 1, 0xFF01), config.addresses) # Проверяем сохранение исходного порядка подписки. + with self.assertRaises(FrozenInstanceError): # Идентификатор уже сформированной модели нельзя менять на месте. + config.config_id = 2 # Присваивание проверяет защиту frozen dataclass, а не изменение состояния устройства. + values = [0, None, 65535] # Корректный ноль и недостоверное значение должны оставаться различимыми. + sample = GasWatchSample(1, 2, 3, values) # Публичная модель также должна копировать изменяемый контейнер. + values[0] = 5 # Моделируем повторное использование входного списка вызывающим приложением. + self.assertEqual((0, None, 65535), sample.values) # Ранее созданная выборка не должна изменяться вслед за списком. + with self.assertRaises(FrozenInstanceError): # Метка времени проверенной выборки остаётся неизменяемой. + sample.timestamp_ms = 4 # Присваивание должно быть отклонено механизмом dataclass. + + def test_integer_ranges_prevent_ctypes_narrowing(self): # Python обязан отвергать значения, которые ctypes незаметно усекло бы до C-типа. + for config_id in (0, -1, 0x100000000, True, 1.5): # Проверяем нулевой, отрицательный, переполненный и нецелые идентификаторы. + with self.subTest(config_id=config_id), self.assertRaises(ValueError): # Каждый ошибочный id должен отказать до вызова C. + GasWatchConfig(config_id, 100, (0,)) # Остальные поля допустимы и не маскируют проверяемую ошибку. + for period in (-1, 65536, True, 1.5): # Период представляет uint16_t в миллисекундах без преобразования bool и float. + with self.subTest(period=period), self.assertRaises(ValueError): # Проверяем все источники возможного сужения периода. + GasWatchConfig(1, period, (0,)) # Валидный идентификатор и адрес изолируют неверный период. + for address in (-1, 65536, True, 1.5): # GAS-регистр задаётся uint16_t, а не произвольным Python-числом. + with self.subTest(address=address), self.assertRaises(ValueError): # Любой недопустимый элемент массива должен отказать. + GasWatchConfig(1, 100, (address,)) # Один адрес позволяет проверить границу независимо от числа каналов. + with self.assertRaises(ValueError): # Подписка не должна превышать общий предел 64 каналов. + GasWatchConfig(1, 100, tuple(range(65))) # 65 уникальных допустимых адресов изолируют ограничение размера. + with self.assertRaises(ValueError): # Значения публичной модели также не должны выходить за 16 бит. + GasWatchSample(1, 2, 3, (65536,)) # Отдельная ошибочная величина проверяет защиту модели результата. + + def test_old_library_has_explicit_rebuild_error(self): # Устаревшая библиотека должна дать понятную ошибку без Python fallback. + with self.assertRaisesRegex(RuntimeError, "set_gas_watch.c"): # Сообщение должно назвать недостающую реализацию для пересборки. + NativeGasWatch(object()) # Объект без новых ABI-символов воспроизводит отсутствие функции в старой DLL. + + def test_message_types_preserve_legacy_values(self): # Новые wire-типы не должны переопределять существующий GAS_WATCH. + self.assertEqual((0x12, 0x13), (MessageType.GAS_WATCH_SET, MessageType.GAS_WATCH_DATA)) # Сохраняем совместимость старого профиля v1. + self.assertEqual((0x14, 0x15), (MessageType.GAS_WATCH2_SET, MessageType.GAS_WATCH2_DATA)) # Выделенные типы однозначно выбирают новый формат. + + +@unittest.skipUnless(os.environ.get("SETPROTOCOL_LIBRARY"), "Укажите SETPROTOCOL_LIBRARY для проверки настоящего C-ядра") # Без явного пути не подменяем C тестовым Python-кодеком. +class NativeGasWatchTests(unittest.TestCase): # Проверяем реальные builder, ACK-валидатор и DATA-декодер общей библиотеки. + @classmethod # Одну DLL и общий fixture безопасно переиспользуют отдельные экземпляры адаптера каждого теста. + def setUpClass(cls): # Загружаем внешний контракт один раз до тестов C ABI. + cls.library = ctypes.CDLL(os.environ["SETPROTOCOL_LIBRARY"]) # Указанный путь должен вести к сборке с set_gas_watch.c. + cls.fixture = json.loads(FIXTURE_PATH.read_text(encoding="utf-8")) # Эталонные данные читаются в обязательной кодировке UTF-8. + cls.request_bytes = bytes.fromhex(cls.fixture["request_hex"]) # Фиксированные байты отделяют ожидаемый wire-вектор от реализации C. + cls.sample_bytes = bytes.fromhex(cls.fixture["sample_hex"]) # DATA проверяется теми же байтами, что и другие языковые порты. + + def setUp(self): # Изолируем pending и active между независимыми сценариями. + self.core = NativeGasWatch(self.library) # Каждый тест начинает с отсутствующей подтверждённой конфигурацией. + self.config = GasWatchConfig(self.fixture["config_id"], self.fixture["period_ms"], self.fixture["addresses"]) # Сохраняем порядок общих трёх адресов. + + def activate(self): # Повторяем нормальный цикл отправки конфигурации и её точного подтверждения. + payload = self.core.request(self.config) # Запрос формирует настоящий C-builder. + self.core.validate_ack(payload, self.config) # Полное эхо устройства проверяет настоящий C ACK-валидатор. + + def test_shared_fixture_request_ack_and_sample(self): # Основной сценарий фиксирует совместимость байтов и семантику признаков достоверности. + self.assertEqual(self.request_bytes, self.core.request(self.config)) # Сопоставляем результат C-builder с общим независимым эталоном. + with self.assertRaises(RuntimeError): # DATA до ACK не имеет подтверждённого соответствия каналам. + self.core.sample(self.sample_bytes) # Даже корректный пакет должен быть отвергнут до активации конфигурации. + self.core.validate_ack(self.request_bytes, self.config) # Активируем подписку только по полному точному эху. + sample = self.core.sample(self.sample_bytes) # C проверяет config_id, количество, длину, padding и значения invalid-каналов. + expected_values = tuple(value if valid else None for value, valid in zip(self.fixture["values"], self.fixture["valid"])) # Преобразуем семантику fixture, не декодируя wire-пакет. + self.assertEqual(GasWatchSample(self.config.config_id, self.fixture["sequence"], self.fixture["timestamp_ms"], expected_values), sample) # Сверяем всю неизменяемую модель результата. + zero_sample = bytes.fromhex("0200030078563412040302014433221105000000003412") # Фиксированный вектор содержит достоверный ноль, invalid-ноль и слово 0x1234. + self.assertEqual((0, None, 0x1234), self.core.sample(zero_sample).values) # Недостоверное значение не должно превращаться в отображаемый ноль. + + def test_native_request_rejects_duplicates_and_inconsistent_stop(self): # Логические ограничения протокола должны проверяться C, а не вторым валидатором Python. + self.activate() # Действующая подписка нужна для проверки сохранения состояния при отказе builder. + invalid = (GasWatchConfig(2, 100, (0, 0)), GasWatchConfig(2, 0, (0,)), GasWatchConfig(2, 100, ())) # Проверяем дубликаты и оба несовместимых сочетания периода с количеством. + for config in invalid: # Каждая ошибочная конфигурация должна быть отвергнута независимо от предыдущей попытки. + with self.subTest(config=config), self.assertRaises(ValueError): # Отказ C-builder преобразуется в явную ошибку Python. + self.core.request(config) # Никакой неправильный запрос не должен менять активную подписку. + self.assertEqual(self.config.config_id, self.core.sample(self.sample_bytes).config_id) # После отказа прежние подтверждённые DATA продолжают приниматься. + stop = GasWatchConfig(self.config.config_id + 1, 0, ()) # Пустой список с нулевым периодом представляет правильную команду отключения. + self.assertEqual(bytes.fromhex("020000007956341200000000"), self.core.request(stop)) # C-builder должен поддерживать отдельный идентификатор остановки. + self.core.validate_ack(bytes.fromhex("020000007956341200000000"), stop) # Полный ACK пустой конфигурации также должен проходить C-проверку. + + def test_ack_checks_full_configuration_and_preserves_active(self): # Равного количества каналов недостаточно для принятия подтверждения. + self.activate() # Создаём активную подписку, которая должна пережить ошибочный ACK следующей команды. + changed = GasWatchConfig(self.config.config_id + 1, 200, (0xFF01, 1, 0)) # Новый порядок того же числа адресов получает новый идентификатор. + changed_request = self.core.request(changed) # Pending меняется, а действующий профиль остаётся активным до ACK. + self.assertEqual(self.config.config_id, self.core.sample(self.sample_bytes).config_id) # Старые DATA разрешены, пока устройство не подтвердило переключение. + for supplied in (self.config, changed): # Отдельно проверяем поздний ACK и пакет, не соответствующий новой конфигурации. + with self.subTest(supplied=supplied), self.assertRaises(ValueError): # Ни один вариант не должен активировать неподтверждённую подписку. + self.core.validate_ack(self.request_bytes, supplied) # Вариант old отвергает pending-проверка, вариант new — C-сравнение эха. + altered = bytearray(changed_request) # Моделируем ACK с тем же id, периодом и count, но другим порядком адресов. + altered[-2:] = b"\x02\x00" # Меняем один адрес в конце вектора, не затрагивая геометрию ответа. + with self.assertRaises(ValueError): # Полное сравнение адресов должно обнаружить подмену при прежнем количестве каналов. + self.core.validate_ack(bytes(altered), changed) # C проверяет весь список и не разрешает частичную подписку. + self.core.validate_ack(changed_request, changed) # Корректное полное эхо атомарно переводит pending в active. + with self.assertRaises(ValueError): # Пакет прежнего id после успешного переключения становится устаревшим. + self.core.sample(self.sample_bytes) # Количество осталось тем же, поэтому проверка должна опираться на идентификатор. + new_sample = bytes.fromhex("0200030079563412fffffffff0ffffff037b00feff0000") # Фиксированный DATA-вектор относится к новому config_id 0x12345679. + self.assertEqual(changed.config_id, self.core.sample(new_sample).config_id) # Новый подтверждённый id разрешает данные именно новой конфигурации. + + def test_malformed_ack_and_sample_do_not_poison_subscription(self): # Ошибки отдельных пакетов не должны разрушать рабочую подписку. + self.core.request(self.config) # Pending необходим для проверки точного формата первого подтверждения. + for payload in (self.request_bytes[:-1], self.request_bytes + b"\x00"): # Отсечённые и дополненные ACK имеют неправильную длину. + with self.subTest(ack=payload), self.assertRaises(ValueError): # C должен отвергнуть и неполное, и нестрогое эхо. + self.core.validate_ack(payload, self.config) # Pending сохраняется, позволяя принять следующий корректный ACK. + self.core.validate_ack(self.request_bytes, self.config) # Корректное подтверждение после ошибок всё ещё активирует исходную подписку. + malformed = ( # Список фиксированных искажений покрывает геометрию, достоверность и привязку к конфигурации. + self.sample_bytes[:-1], # Отбрасываем последнее слово частично: общая длина больше не соответствует count. + self.sample_bytes + b"\x00", # Лишний байт также нарушает точную геометрию пакета. + bytes.fromhex("0100030078563412fffffffff0ffffff037b00feff0000"), # Версия 1 не должна интерпретироваться как новый формат версии 2. + bytes.fromhex("0200030079563412fffffffff0ffffff037b00feff0000"), # Другой id с прежним count моделирует поздние DATA другой подписки. + bytes.fromhex("0200020078563412fffffffff0ffffff037b00feff"), # Корректная геометрия двух значений не совпадает с тремя ожидаемыми адресами. + bytes.fromhex("0200030078563412fffffffff0ffffff837b00feff0000"), # Старший padding-бит bitmap для трёх каналов обязан быть нулём. + bytes.fromhex("0200030078563412fffffffff0ffffff037b00feff0100"), # Значение invalid-канала обязано быть нулём, иначе данные неоднозначны. + ) # Закрываем перечень независимых отрицательных векторов C-декодера. + for payload in malformed: # Проверяем каждый отказ с тем же неизменным состоянием подписки. + with self.subTest(data=payload), self.assertRaises(ValueError): # Ни один некорректный пакет не должен превращаться в модель. + self.core.sample(payload) # Все проверки структуры пакета выполняются общим C-декодером. + self.assertEqual(self.config.config_id, self.core.sample(self.sample_bytes).config_id) # Следующий корректный пакет доказывает сохранение active после ошибки. + + def test_failed_decode_keeps_all_c_outputs_unchanged(self): # Проверяем обещание ABI не публиковать частичные результаты при ошибке пакета. + data = (ctypes.c_uint8 * len(self.sample_bytes)).from_buffer_copy(self.sample_bytes) # Передаём эталонные байты, изменяя только ожидаемый id C-вызова. + sequence = ctypes.c_uint32(11) # Отличимый sentinel обнаруживает запись счётчика до окончания проверки. + timestamp = ctypes.c_uint32(22) # Независимый sentinel защищает проверку метки времени. + values = (ctypes.c_uint16 * 3)(31, 32, 33) # Отличимые слова обнаруживают частичное заполнение выходного массива. + valid = (ctypes.c_uint8 * 3)(41, 42, 43) # Признаки также не должны перезаписываться при устаревшем id. + result = self.core.lib.set_gas_watch_decode(data, len(data), self.config.config_id + 1, 3, ctypes.byref(sequence), ctypes.byref(timestamp), values, valid, 3) # Проверяем настоящий C ABI без обёртки создания модели. + self.assertEqual(-1, result) # Несовпадающий expected_config_id обязан отвергнуть даже корректно сформированный пакет. + self.assertEqual((11, 22, (31, 32, 33), (41, 42, 43)), (sequence.value, timestamp.value, tuple(values), tuple(valid))) # Каждый выход должен сохранить исходный sentinel. + + def test_pending_replacement_id_reuse_and_reset(self): # Проверяем гонки нескольких запросов и очистку состояния при переподключении. + self.activate() # Ранее подтверждённая конфигурация задаёт исходный active. + changed = GasWatchConfig(self.config.config_id + 1, 100, (1, 0, 0xFF01)) # Первый новый порядок начинает ожидать подтверждение. + self.core.request(changed) # Старый active остаётся доступным, пока новый pending не подтверждён. + newest = GasWatchConfig(self.config.config_id + 2, 100, (0xFF01, 0, 1)) # Следующая команда заменяет ожидаемый список ещё до первого ACK. + newest_request = self.core.request(newest) # Актуальным pending становится только последний запрос. + with self.assertRaises(ValueError): # ACK уже заменённого pending не должен возвращать старое ожидание. + self.core.validate_ack(self.request_bytes, changed) # Проверка pending срабатывает до анализа неподходящего payload. + for reused in (GasWatchConfig(self.config.config_id, 200, self.config.addresses), GasWatchConfig(newest.config_id, 200, newest.addresses)): # Active и pending id нельзя переиспользовать с другим содержимым. + with self.subTest(reused=reused), self.assertRaises(ValueError): # Такая подмена лишила бы DATA возможности определить порядок значений. + self.core.request(reused) # Ошибка не должна уничтожать последний ожидаемый запрос. + self.core.validate_ack(newest_request, newest) # Последний корректный pending всё ещё подтверждается после отвергнутых попыток. + self.core.reset() # Переподключение удаляет как ожидаемую, так и подтверждённую подписку. + with self.assertRaises(RuntimeError): # Старая выборка после reset требует нового цикла подтверждения. + self.core.sample(self.sample_bytes) # Данные прошлого соединения не должны отображаться автоматически. + with self.assertRaises(ValueError): # Ни один ACK прошлого соединения больше не ожидается. + self.core.validate_ack(newest_request, newest) # Reset запрещает позднее восстановление прежнего active. + + def test_maximum_subscription_uses_real_c_builder(self): # Проверяем безопасную передачу полного массива из 64 каналов через ctypes. + config = GasWatchConfig(0xFFFFFFFF, 65535, tuple(range(64))) # Используем максимальные id и период при допустимом числе уникальных адресов. + payload = self.core.request(config) # Размер payload определяет настоящий C-builder в общем транспортном буфере. + self.assertEqual(140, len(payload)) # Версия 2 задаёт 12 байт заголовка и 64 двухбайтных адреса, всего 140 байт. + self.core.validate_ack(payload, config) # Полное эхо максимального массива проверяется без усечения и частичного принятия. + + +if __name__ == "__main__": # Разрешаем запуск этого набора проверок напрямую наряду с unittest discovery. + unittest.main() # Стандартный runner сообщает результаты, ошибки DLL и пропущенные C-проверки. diff --git a/python/tests/test_modbus_unified.py b/python/tests/test_modbus_unified.py new file mode 100644 index 0000000..a13c445 --- /dev/null +++ b/python/tests/test_modbus_unified.py @@ -0,0 +1,38 @@ +import unittest # Стандартный тестовый раннер проверяет wire-контракт без зависимости от GUI. +from protocan import protocan as pc # Используем публичный построитель и декодер CAN-сообщений. +from logic_analyzer.decoders.set_can import legacy # Тот же формат должен распознаваться при анализе аппаратного захвата. + + +class ModbusTests(unittest.TestCase): # Проверяем объединение банков, битовую упаковку и отбраковку неверных окон. + def test_functions_and_counts(self): # Все шестнадцать сочетаний должны сохранять функцию, количество и значения. + for function in range(1, 5): # Номера 1…4 соответствуют Coil, Discrete, Holding и Input. + for count in range(1, 5): # Количество ограничено 1…4 независимо от размера элемента банка. + body = pc.merge_modbus(0x123, count, function) # Адрес выбран так, чтобы старшие биты отличались от младших служебных полей. + self.assertEqual(body, 0x1230 | ((function - 1) << 2) | (count - 1)) # Эталон явно задаёт адрес [15:4], функцию [3:2] и количество [1:0]. + self.assertEqual(pc.split_modbus(body), (0x123, count, function)) # Обратное преобразование возвращает физические значения 1…4. + values = [index % 2 for index in range(count)] if function <= 2 else [0x1234 + index for index in range(count)] # Битовые и регистровые банки содержат различимые последовательности. + data = bytes([sum(value << index for index, value in enumerate(values))]) if function <= 2 else b''.join(value.to_bytes(2, 'little') for value in values) # Биты начинаются с младшего, слова передаются little-endian. + identifier = pc.ProtoCanId.build(1, 1, 7, 3, pc.MsgType.MODBUS, body) # Каждый ответ имеет единый MsgType=0x5 и направление от устройства. + decoded = pc.decode(identifier, data) # Проверяем штатный путь CAN-журнала приложения. + self.assertFalse(decoded.warnings, decoded.warnings) # Допустимое окно не должно сопровождаться предупреждениями. + self.assertEqual(decoded.registers, list(zip(range(0x123, 0x123 + count), values))) # Для каждого бита и слова публикуется точный адрес. + captured = legacy(identifier, data) # Проверяем согласованность анализатора захватов с протокольной библиотекой. + self.assertEqual((captured['function'], captured['count'], captured['registers']), (function, count, decoded.registers)) # Оба публичных пути возвращают одинаковые физические значения. + + def test_invalid_inputs_and_payloads(self): # Ошибки должны отклоняться до превращения в другой допустимый wire-код. + for args in ((0, 0, 1), (0, 5, 1), (0, 1, 0), (0, 1, 5), (-1, 1, 1), (4096, 1, 1), (4095, 2, 4)): # Охватываем обе границы полей и переполнение окна. + with self.assertRaises(ValueError): pc.merge_modbus(*args) # Неверные значения не маскируются и не оборачиваются. + self.assertEqual(pc.merge_modbus(4095, 1, 4), 0xFFFC) # Последний адрес остаётся доступным для одного регистра Input. + for body, data in ((0x1233, b'\x10'), (0x123B, b'\x01\x02'), (0xFFFF, b'\0' * 8), (0x123B, b'\0' * 9)): # Проверяем лишний бит, короткие данные, выход окна за 0xFFF и запрет молчаливой обрезки девятого октета. + decoded = pc.decode(0x1F350000 | body, data) # Формируем ответ устройства с единым типом 0x5. + self.assertTrue(decoded.warnings) # Каждая ошибка должна быть видима в журнале. + self.assertFalse(decoded.registers) # Некорректный payload не становится источником значений для тренда. + with self.assertRaises(ValueError): legacy(0x1F350000 | body, data) # Анализатор захвата использует те же проверки. + self.assertFalse(pc.decode(0x1735123F, b'').warnings) # Запрос ПМ с функцией 4 и количеством 4 не содержит данных. + self.assertTrue(pc.decode(0x1F35123F, b'').warnings) # Пустой ответ прибора является ошибкой протокола. + for msg_type in (6, 7): # Бывшие отдельные типы Modbus освобождены. + self.assertTrue(pc.decode(0x1F300000 | (msg_type << 16), b'').warnings) # Декодер не трактует старые MsgType как единый Modbus. + + +if __name__ == '__main__': # Допускаем прямой запуск теста на хосте. + unittest.main() # Стандартный код завершения отражает результат проверок. diff --git a/tools/c2000-linker/.gitignore b/tools/c2000-linker/.gitignore new file mode 100644 index 0000000..919cfec --- /dev/null +++ b/tools/c2000-linker/.gitignore @@ -0,0 +1,4 @@ +# Кэш Python создаётся локальными проверками и не входит в переносимый исходный комплект. +__pycache__/ +# Скомпилированные модули не являются поставляемыми исходниками helper. +*.pyc diff --git a/tools/c2000-linker/README.md b/tools/c2000-linker/README.md new file mode 100644 index 0000000..55569bd --- /dev/null +++ b/tools/c2000-linker/README.md @@ -0,0 +1,83 @@ +# Помощник linker для TMS320F28335 и TMS320F2812 + +Переносимая утилита Python 3.10+ из стандартной библиотеки. Она создаёт стартовые карты **COFF** для RAM и внутренней Flash, объясняет память и проверяет поддерживаемую часть текстовых CMD/MAP. Работает офлайн без SDK, платы и программатора. EABI сейчас не поддерживается. + +Все адреса, длины MEMORY, размеры секций и copy-symbols выражены в **16-битных словах C28x**. Например, `0x1000` слов занимает 8192 физических октета. PAGE 0 и PAGE 1 — логические страницы линкера; одинаковые адреса RAM/Flash на них не означают независимую память. Высокое зеркало L0–L3 F28335 также не даёт дополнительную RAM. H0 F2812 — самостоятельный блок. + +## Быстрый запуск + +Команды приведены относительно корня общего `templates`: + +```powershell +python tools/c2000-linker/c2000_linker.py profiles # Показывает поддерживаемые устройства, boot modes и ABI. +python tools/c2000-linker/c2000_linker.py explain --device 2812 # Объясняет адреса RAM, Flash, BEGIN, CSM и OTP в hex. +python tools/c2000-linker/c2000_linker.py generate --device 28335 --boot flash --output board_flash.cmd # Создаёт стартовый COFF CMD для внутренней Flash. +python tools/c2000-linker/c2000_linker.py generate --device 2812 --boot ram --output board_ram.cmd # Создаёт отдельную RAM-карту F2812 с входом в H0. +python tools/c2000-linker/c2000_linker.py inspect board_flash.cmd --device 28335 --boot flash # Показывает регионы и потенциальные назначения до линковки. +python tools/c2000-linker/c2000_linker.py validate board_flash.cmd --device 28335 --boot flash --map build/board.map --json # Сверяет фактические адреса и размеры MAP той же сборки. +``` + +`generate` атомарно отказывается заменять существующий файл. Для осознанной замены используйте `--force`. Утилита не создаёт родительские каталоги молча, не переписывает исходный CMD при проверке и не меняет проект CCS. + +## Подключение карты к проекту + +1. Выберите ровно нужный MCU, `ram`/`flash` и COFF. Сгенерируйте новый CMD и добавьте его в проект вместо прежней карты памяти. Периферийный `DSP2833x_Headers_nonBIOS.cmd` либо соответствующий F281x headers CMD подключается отдельно из TI SDK: генератор не копирует регистры периферии. +2. Добавьте официальный `CodeStartBranch.asm` выбранного семейства, чтобы `codestart` содержал длинную ветвь к C runtime. Минимальная ASM-ветвь тестов проверяет только синтаксис/адреса линкера и не заменяет штатный стартовый код TI. +3. Согласуйте ABI, RTS-библиотеку и параметры всех объектов. Общий проверенный минимум — `--abi=coffabi -v28 --float_support=softlib`. **F2812 не имеет FPU32**. Линковке обычно нужны `--rom_model`, `--stack_size=0x100`, `--heap_size=0x40` и вывод `--map_file=...`. Размеры стека/heap подбираются для приложения; приведённые значения служат примером. Не превышайте 1024 слова M1 выделенного стеку шаблона. +4. Для Flash скопируйте `ramfuncs` из LOAD во Flash в RUN в RAM **до первого вызова** функции из этой секции, в частности `InitFlash`. Проверьте порядок внутри своего `InitSysCtrl`. Генератор объединяет входные секции `ramfuncs` и `.TI.ramfunc` в один выходной блок и создаёт COFF-символы `_RamfuncsLoadStart`, `_RamfuncsLoadEnd`, `_RamfuncsLoadSize`, `_RamfuncsRunStart`. +5. Выполните настоящую TI линковку и проверьте её MAP. После добавления реальных модулей места может не хватить даже при корректной начальной карте; утилита не выбирает автоматически split-секции, trampolines или overlay. + +Пример использования linker-символов из C COFF: + +```c +#include /* Объявляет memcpy; на C28x один char соответствует адресуемому 16-битному слову. */ +extern unsigned int RamfuncsLoadStart, RamfuncsLoadSize, RamfuncsRunStart; /* C-имена соответствуют linker-именам с ведущим подчёркиванием COFF. */ +memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize); /* Адрес символа LoadSize кодирует число копируемых слов; значение по этому адресу не читается. */ +``` + +Эту операцию помещают в стартовую функцию, не в глобальную область C. Допустим и исторический контракт `LOAD_END`: размер вычисляется по разности адресов `LoadEnd` и `LoadStart`. Проверка принимает `LOAD_SIZE` **или** `LOAD_END` вместе с обоими начальными адресами. + +Flash API, обработчики во время erase/program, частоты/тайминги Flash и внешняя SRAM зависят от приложения и платы. Генератор их не добавляет и не запускает erase/program. Области CSM/OTP не получают загружаемых секций и паролей. + +## Что именно проверяется + +Поддерживаются буквальные десятичные/hex `origin`/`length` (`org`/`len`), один регион на строку, PAGE 0/1 и обычные SECTIONS: `> REGION`, `LOAD = REGION`, `RUN = REGION`, `PAGE`, `TYPE`, `LOAD_START/END/SIZE`, `RUN_START/END/SIZE`, выбор входных `*(ramfuncs)`/`*(.TI.ramfunc)`. + +Находятся физические пересечения RAM/Flash между PAGE и зеркалами F28335, выход за известную встроенную память, поглощение BEGIN/CSM/OTP/reset/ADC_cal общим регионом, загрузка обычных секций в резервы/BootROM, ошибочный Flash `codestart`, потеря постоянной Flash LOAD-копии обычных инициализированных секций и отсутствие контракта копирования RAM-функций. Первые `0x50` слов M0 консервативно оставлены загрузчику; при RAM boot F28335 первые два слова выделены BEGIN. + +С `--map` проверяются текстовые таблицы TI `MEMORY CONFIGURATION`/`SECTION ALLOCATION MAP`, соответствие MEMORY текущему CMD, непустые фактические LOAD/RUN, размещение секций внутри регионов, пересечения и значения copy-symbols. Поддержан перенос имени секции и отметка `*` в MAP TI CGT 22.6. Загружаемый Flash `codestart` должен реально занимать два слова. Без MAP анализируются **потенциальные назначения**, а фактические размеры неизвестны. + +Коды завершения: + +| Код | Значение | +|---|---| +| `0` | В поддерживаемой части не найдено нарушений. Это не проверка стартового C/ASM-кода или аппаратуры. | +| `1` | Найдено нарушение карты либо не удалось прочитать/создать файл. | +| `2` | Проверка неполная: неподдерживаемый синтаксис/память/MAP; также обычная ошибка CLI argparse. | + +При наличии и ошибок, и неполных частей возвращается `1`; все причины остаются в отчёте. JSON содержит `scope`, `issues`, `regions`, `sections` и фактические `allocations`. + +`#include`, `#if`, макросы, выражения в MEMORY, `GROUP`/`UNION`, отдельные `LOAD_PAGE`/`RUN_PAGE`, split `>>`, внешние регионы и чужие MAP-форматы явно дают неполную проверку. TI linker с препроцессором остаётся окончательным инструментом. Передавайте предварительно обработанный числовой CMD, если нужно убрать влияние include/условных ветвей; помощник не исполняет их сам. + +Исходный CMD проекта может перечислять внутреннюю Flash, CSM и `codestart`, хотя RAM COFF/SCI8 загружает только RAM, а перечисленные выходные секции пусты. Поэтому без MAP предупреждение о потенциальной загрузке в CSM не доказывает запись этих слов. С MAP пустые CSM/codestart-секции не считаются фактической записью. RAM COFF может запускаться JTAG или boot-таблицей по её entry point без аппаратного Boot-to-SARAM `codestart`; отсутствие такой секции не считается ошибкой RAM-профиля. Сгенерированный RAM-шаблон всё же предоставляет стандартный BEGIN, подтверждённый тестом TI. + +Внешняя SPI EEPROM хранит SCI8 boot-таблицу и **не расширяет RAM процессора**. Переход с AT25256B на M95M02 увеличивает ёмкость носителя, но не устраняет переполнение RAM при укладке `.text`, `.cinit`, `.ebss`. Она не является CPU-addressable MEMORY-регионом. + +## Проверки + +```powershell +python tools/c2000-linker/tests/run_tests.py -v # Выполняет переносимые stdlib-регрессии без установленного SDK. +python tools/c2000-linker/tests/run_tests.py --ti C:/ti/ccs1230/ccs/tools/compiler/ti-cgt-c2000_22.6.0.LTS -v # Дополнительно компилирует и линкует4 настоящих COFF-профиля, без платы. +``` + +Тесты проверяют обе модели и оба режима, пересечения разных PAGE и зеркала, резерв CSM/OTP, copy-symbols и альтернативный LOAD_END, отказ перезаписи и явную неполноту неподдерживаемого входа. TI smoke создаёт `.text`, `.econst`, `.ebss`, обе входные RAM-секции и `codestart`, затем анализирует **настоящий MAP TI**. Временные C/ASM/OBJ/OUT/MAP удаляются вместе с собственным временным каталогом. Сохранённый результат выполненной проверки — `TEST_RESULTS.md`. + +## Первичные источники и происхождение адресов + +- [TI TMS320F2833x datasheet, SPRS439Q](https://www.ti.com/lit/ds/symlink/tms320f28335.pdf): карта F28335, зеркальные L0–L3, Flash, boot entry, CSM и заводской ADC_cal. +- [TI TMS320F281x datasheet, SPRS174V](https://www.ti.com/lit/ds/symlink/tms320f2812.pdf): раздел 9.3, таблица 9-15 и boot modes; отдельный H0, Flash, OTP, BEGIN и CSM F2812. +- [TI C28x Assembly Language Tools, linker](https://downloads.ti.com/docs/esd/SPRU513P/Content/SPRU513P_HTML/linker-description.html): MEMORY/PAGE, SECTIONS, LOAD/RUN и linker-generated copy-symbols. +- [TI Linker Command File Primer](https://software-dl.ti.com/ccs/esd/documents/sdto_cgt_Linker-Command-File-Primer.html): физическая память и логические страницы C28x. +- [TI Running an Application from Internal Flash, SPRA958L](https://www.ti.com/lit/an/spra958l/spra958l.pdf): boot-to-Flash, перенос RAM-функций и стартовая настройка Flash. + +Числа дополнительно сопоставлены с локальными официальными TI примерами `C2000Ware_5_03_00_00/device_support/f2833x/common/cmd/F28335.cmd`, `28335_RAM_lnk.cmd` и `controlSUITE/libs/math/IQmath/v160/examples/cmd/2812_IQmath_lnk.cmd`. Генератор содержит собственную компактную карту на основе документированных аппаратных фактов; не копирует целиком распространяемые TI linker-файлы и не требует этих абсолютных путей у пользователя. diff --git a/tools/c2000-linker/TEST_RESULTS.md b/tools/c2000-linker/TEST_RESULTS.md new file mode 100644 index 0000000..c6f53b5 --- /dev/null +++ b/tools/c2000-linker/TEST_RESULTS.md @@ -0,0 +1,22 @@ +# Выполненная проверка + +Дата: 19.10.2026. Python 3.13; TI C2000 CGT 22.6.0.LTS для Windows. + +Команда: + +```powershell +python tests/run_tests.py --ti C:/ti/ccs1230/ccs/tools/compiler/ti-cgt-c2000_22.6.0.LTS -v # Выполняет переносимые регрессии и четыре настоящие COFF-линковки. +``` + +Результат: **14 тестов PASS**, включая четыре сочетания: + +| MCU | Режим | TI compiler/linker | CMD/MAP helper | +|---|---|---|---| +| TMS320F28335 | RAM | PASS | PASS | +| TMS320F28335 | Flash | PASS | PASS | +| TMS320F2812 | RAM | PASS | PASS | +| TMS320F2812 | Flash | PASS | PASS | + +В каждой линковке использованы `--abi=coffabi -v28 --float_support=softlib`; fixture содержит `.text`, `.econst`, `.ebss`, `ramfuncs`, `.TI.ramfunc` и двухсловный `codestart`. Проверены фактические LOAD/RUN и значения Flash copy-symbols в MAP TI. + +Регрессии Python дополнительно подтвердили пересечение RAM между PAGE, конфликт высокого зеркала F28335, CSM/OTP, альтернативный LOAD_END, защиту существующего файла и неполную проверку неподдерживаемых конструкций. Прошивка в MCU не записывалась; smoke не проверяет стартовый код и периферию конкретной платы. diff --git a/tools/c2000-linker/c2000_linker.py b/tools/c2000-linker/c2000_linker.py new file mode 100644 index 0000000..30ad0e3 --- /dev/null +++ b/tools/c2000-linker/c2000_linker.py @@ -0,0 +1,317 @@ +"""Создаёт и проверяет стартовые карты COFF TMS320F28335/F2812; не заменяет TI linker.""" # Утилита работает офлайн, читает текстовые CMD/MAP и не обращается к устройству. +import argparse # Стандартная библиотека обеспечивает переносимый CLI без пакетов SDK. +from dataclasses import dataclass # Числовые записи отделяют слова C28x от физических октетов файла. +import json # Структурированный отчёт пригоден для CI без разбора русского текста. +from pathlib import Path # Пути не зависят от установленного SDK и рабочего каталога. +import re # Ограниченная грамматика не исполняет макросы или выражения пользовательского CMD. +import sys # Передаёт отдельные коды ошибок и неполной проверки вызывающей сборке. + +@dataclass(frozen=True) # Адреса исходной карты остаются неизменяемыми при проверке. +class Region: # Один MEMORY-регион в 16-битных адресуемых словах C28x. + name: str # Название связывает регион с выходной секцией. + page: int # PAGE разделяет пространство линкера, но не физическую память. + origin: int # Первый адрес слова в интервале. + length: int # Число слов до исключённого правого конца. + +DEVICES = { # Числа сверены с первичными TI datasheet и официальными linker-примерами, указанными в README. + '28335': {'flash': (0x300000, 0x340000), 'begin': 0x33FFF6, 'otp': (0x380400, 0x380800), 'rom': (0x3FE000, 0x400000), 'ram': ((0, 0x800), (0x8000, 0x10000)), 'ram_entry': 0, 'alias': (0x3F8000, 0x3FC000, 0x8000)}, # SPRS439Q: L0–L3 имеют высокое зеркало, Flash содержит 256K слов. + '2812': {'flash': (0x3D8000, 0x3F8000), 'begin': 0x3F7FF6, 'otp': (0x3D7800, 0x3D7C00), 'rom': (0x3FF000, 0x400000), 'ram': ((0, 0x800), (0x8000, 0xA000), (0x3F8000, 0x3FA000)), 'ram_entry': 0x3F8000, 'alias': None}, # SPRS174V: H0 является отдельной RAM8K слов; Flash128K слов. +} # Внешняя SRAM, EEPROM и Flash API зависят от платы и сюда не добавляются. +NUM = r'(?:0[xX][0-9A-Fa-f]+|[0-9]+)' # Принимает только буквальные значения без выполнения C-выражений. +NAME = r'[A-Za-z_.$][\w.$]*' # Обычные имена MEMORY/SECTIONS TI без расширенного GROUP-синтаксиса. + + +def issue(level, code, message): # Формирует единый формат машиночитаемой и русской диагностики. + return {'level': level, 'code': code, 'message': message} # incomplete влияет на код возврата, а не скрывается как справочный текст. + + +def clean_text(text): # Удаляет C-комментарии без изменения номеров строк. + return re.sub(r'/\*.*?\*/|//[^\n]*', lambda m: ''.join('\n' if c == '\n' else ' ' for c in m[0]), text, flags=re.S) # Скобки внутри пояснений не становятся языком linker-файла. + + +def body(text, keyword): # Выделяет MEMORY или SECTIONS по парным скобкам. + match = re.search(r'\b' + keyword + r'\s*\{', text) # Требует фактическую директиву с телом. + if not match: # Отсутствующий блок означает неверный или неполный вход. + raise ValueError('Не найден блок ' + keyword) # Не возвращает пустую карту под видом успешной проверки. + start, depth = match.end(), 1 # Начальная открывающая скобка уже найдена. + for index in range(start, len(text)): # Вложенные тела обычных секций допускаются. + depth += (text[index] == '{') - (text[index] == '}') # Подсчитывает только уже очищенный от комментариев текст. + if not depth: # Нулевой уровень закрывает именно искомую директиву. + return text[start:index] # Сохраняет внутренние тела секций для дальнейшей проверки. + raise ValueError('Незакрытый блок ' + keyword) # Усечённый файл не может дать положительный результат. + + +def parse_cmd(text): # Разбирает числовые регионы и обычные назначения, явно отмечая всё неподдерживаемое. + text, issues = clean_text(text), [] # Синтаксические ограничения входят в общий отчёт. + for line in re.findall(r'^\s*(#[^\n]+)', text, re.M): # TI-препроцессор не воспроизводится средствами Python. + issues.append(issue('incomplete', 'PREPROCESSOR', line.strip() + ': передайте предварительно обработанный CMD TI.')) # include и условные ветки никогда не игнорируются молча. + if any(len(re.findall(r'\b' + word + r'\s*\{', text)) != 1 for word in ('MEMORY', 'SECTIONS')): # Несколько директив нельзя свести к первому блоку без потери физической карты. + issues.append(issue('incomplete', 'MULTIPLE_BLOCKS', 'Поддерживается ровно один MEMORY и один SECTIONS; объедините предварительно обработанный CMD.')) # Не выдаёт первый разобранный блок за проверку всего файла. + memory, section_text = body(text, 'MEMORY'), body(text, 'SECTIONS') # Требует обе основные директивы. + regions, page = [], 0 # MEMORY без PAGE относится к стандартной странице 0. + rule = re.compile(r'(' + NAME + r')\s*(?:\([RWIX]+\))?\s*:\s*(?:origin|org)\s*=\s*(' + NUM + r')\s*,?\s*(?:length|len)\s*=\s*(' + NUM + r')\s*[,;]?\s*$', re.I) # Выражения длины и неизвестные атрибуты дают incomplete. + for raw in memory.splitlines(): # Один числовой MEMORY-регион задаётся одной строкой. + line = raw.strip() # Отступы и пустые комментарии не влияют на смысл. + if not line: # Пропускает только заведомо пустые строки. + continue # Не увеличивает число неподдерживаемых конструкций. + mark = re.fullmatch(r'PAGE\s+([01])\s*:', line, re.I) # Страница учитывается при разрешении имени региона. + if mark: # Переключение действует на следующие объявления. + page = int(mark[1]) # Номер страницы не изменяет физическую адресацию. + continue # PAGE не является MEMORY-регионом. + match = rule.fullmatch(line) # Полное совпадение исключает незаметное отбрасывание выражений. + if match: # Только полностью понятная запись попадает в проверяемую карту. + regions.append(Region(match[1], page, int(match[2], 0), int(match[3], 0))) # Адрес и длина остаются в словах TI. + else: # Даже часть корректного региона не подтверждает всю строку. + issues.append(issue('incomplete', 'MEMORY_SYNTAX', 'Не разобрана строка MEMORY: ' + line)) # Показывает пользователю точную границу анализа. + heads = list(re.finditer(r'(?m)^\s*(' + NAME + r')\s*:', section_text)) # Обычные выходные секции могут содержать точки в имени. + if heads and section_text[:heads[0].start()].strip(): # Непонятный текст до первой обычной секции не принадлежит телу уже распознанного назначения. + issues.append(issue('incomplete', 'SECTION_PREFIX', 'Не разобран префикс SECTIONS перед первым обычным назначением.')) # Не скрывает потерянное назначение .text или неизвестную конструкцию в начале блока. + sections = [] # Результат связывает LOAD/RUN с конкретными регионами. + for index, head in enumerate(heads): # Охватывает все обычные назначения, включая многострочные LOAD/RUN. + text_body = section_text[head.end():heads[index + 1].start() if index + 1 < len(heads) else len(section_text)] # Следующий заголовок завершает текущее назначение. + target = re.search(r'(?)>\s*(' + NAME + r')', text_body) # Простой > задаёт совпадающие адреса хранения и исполнения. + load = re.search(r'\bLOAD\s*=\s*(' + NAME + r')', text_body, re.I) # LOAD указывает место хранения секции. + run = re.search(r'\bRUN\s*=\s*(' + NAME + r')', text_body, re.I) # RUN определяет адрес исполнения копируемого RAM-кода. + pg = re.search(r'\bPAGE\s*=\s*([01])', text_body, re.I) # Без PAGE однозначность проверяется по всем регионам. + typ = re.search(r'\bTYPE\s*=\s*(NOLOAD|DSECT|COPY|NOINIT)', text_body, re.I) # Различает программирование и фиктивное представление ROM. + section = {'name': head[1], 'load': load[1] if load else target[1] if target else None, 'run': run[1] if run else load[1] if load else target[1] if target else None, 'page': int(pg[1]) if pg else None, 'type': typ[1].upper() if typ else '', 'body': text_body.strip()} # Не подставляет предполагаемый регион при неизвестном синтаксисе. + rest = re.sub(r'\b(?:LOAD|RUN)\s*=\s*' + NAME + r'|(?)>\s*' + NAME + r'|\bPAGE\s*=\s*[01]|\bTYPE\s*=\s*(?:NOLOAD|DSECT|COPY|NOINIT)|\b(?:LOAD_START|LOAD_END|LOAD_SIZE|RUN_START|RUN_END|RUN_SIZE|SIZE)\s*\(\s*' + NAME + r'\s*\)|\*\s*\(\s*[.\w]+\s*\)', '', text_body, flags=re.I) # Поддерживает copy-symbols и выбор входных ramfuncs без полного языка TI. + if re.sub(r'[\s{},;]', '', rest) or not section['load']: # Неизвестный остаток запрещает полный успех. + issues.append(issue('incomplete', 'SECTION_SYNTAX', section['name'] + ': назначение разобрано не полностью.')) # Понятные адреса всё ещё можно показать через inspect. + sections.append(section) # Неполный разбор не скрывает подтверждённые ошибки соседних секций. + if not regions or not sections: # Пустой частичный результат не является проверкой linker-карты. + issues.append(issue('incomplete', 'EMPTY_PARSE', 'Не получены MEMORY-регионы или выходные секции.')) # Требует поддерживаемый числовой вход. + if re.search(r'\b(?:GROUP|UNION|LOAD_PAGE|RUN_PAGE)\b|>>', text): # Раздельные страницы LOAD/RUN и overlay требуют полноценного TI linker. + issues.append(issue('incomplete', 'ADVANCED_SYNTAX', 'GROUP/UNION, >> и LOAD_PAGE/RUN_PAGE не поддерживаются.')) # Ограничение явно включено в статус 2. + return regions, sections, issues # Вызывающий код объединяет синтаксические и аппаратные нарушения. + + +def physical(region, device): # Приводит высокое зеркало L0–L3 F28335 к тем же физическим словам. + alias = DEVICES[device]['alias'] # F2812 H0 преобразовывать нельзя: это отдельная RAM. + start = region.origin - alias[0] + alias[2] if alias and alias[0] <= region.origin < region.origin + region.length <= alias[1] else region.origin # Переносит только целиком расположенный в зеркале интервал. + return start, start + region.length # Во всех расчётах правая граница исключена. + + +def inside(start, end, ranges): # Проверяет полное вхождение интервала в один известный аппаратный блок. + return any(left <= start < end <= right for left, right in ranges) # Нулевая длина и выход за конец не принимаются. + + +def reserves(device, boot): # Описывает стандартные резервы без платоспецифичных EEPROM/Flash API. + p, begin = DEVICES[device], DEVICES[device]['begin'] # Для 2812 и 28335 адреса безопасности различаются. + result = [('BOOT_RSVD', 2 if device == '28335' and boot == 'ram' else 0, 0x50), ('CSM_RSVD', begin - 0x76, begin), ('FLASH_BEGIN', begin, begin + 2), ('CSM_PWL', begin + 2, begin + 10), ('OTP', *p['otp']), ('RESET', 0x3FFFC0, 0x400000)] # Первые 80 слов M0 резервируются консервативно; RAM entry28335 занимает только первые 2. + if device == '28335': # У этой модели имеется заводской код калибровки ADC. + result.append(('ADC_CAL', 0x380080, 0x380089)) # Приложение не должно перезаписывать девять слов ADC_cal. + return result # Секции безопасности не получают загружаемых назначений в генераторе. + + +def validate_cmd(regions, sections, device, boot, active_sections=None): # Проверяет физическую память независимо от логических PAGE. + issues, p = [], DEVICES[device] # Все аппаратные пределы берутся из выбранного, а не угаданного MCU. + known = (*p['ram'], p['flash'], p['rom'], p['otp']) + (((0x380080, 0x380089),) if device == '28335' else ()) # Заводской ADC-регион существует только у 28335. + for index, region in enumerate(regions): # Один регион сравнивается со всеми ранее объявленными. + start, end = physical(region, device) # Высокое зеркало и обычная RAM теперь имеют общую координату. + if region.length <= 0 or region.origin + region.length > 0x400000: # Адреса C28x22-битные, а длина должна выделять реальные слова. + issues.append(issue('error', 'REGION_RANGE', region.name + ': недопустимые адрес или длина.')) # Запрещает выход за адресное пространство. + if not inside(start, end, known): # Периферия и XINTF нуждаются в дополнительных данных платы. + issues.append(issue('incomplete', 'UNKNOWN_MEMORY', region.name + ': вне известных блоков RAM/Flash/ROM; внешнюю память и периферию проверьте отдельно.')) # Не объявляет неподтверждённую память конкретной платы безопасной. + for old in regions[:index]: # Отдельные PAGE не исключают физическое пересечение. + left, right = physical(old, device) # Учитывает зеркало второго региона. + if start < right and left < end and inside(max(start, left), min(end, right), (*p['ram'], p['flash'])): # Соседние интервалы разрешены; вложенные ROM-представления не занимают RAM/Flash. + issues.append(issue('error', 'PHYSICAL_OVERLAP', f'{old.name}/PAGE{old.page} и {region.name}/PAGE{region.page}: общая физическая память 0x{max(start, left):X}..0x{min(end, right):X}.')) # Объясняет источник конфликта, а не только номера страниц. + for name, left, right in reserves(device, boot): # Общий FLASH/RAM-регион не должен поглощать резерв безопасности. + special = region.name == name or name == 'FLASH_BEGIN' and region.name == 'BEGIN' and region.origin == p['begin'] and region.length == 2 or name == 'RESET' and region.name in ('RESET', 'VECTORS', 'ROM') # Точные именованные резервы можно описывать без программирования. + if start < right and left < end and not special: # Проверяет также широкие регионы, пока не занятые секциями. + issues.append(issue('error', 'RESERVED_REGION', f'{region.name} захватывает {name}: 0x{left:X}..0x{right:X}.')) # Требует выделить защищённый интервал отдельно. + for section in sections: # Теперь проверяет потенциальные назначения CMD либо только непустые секции переданного MAP. + if active_sections is not None and section['name'] not in active_sections: # Пустая секция CSM/codestart в RAM COFF не означает фактическую запись Flash. + continue # При наличии MAP вывод о загрузке делается только по реально размещённым секциям. + targets = {} # LOAD и RUN остаются разными даже для одинакового адресного пространства. + for key in ('load', 'run'): # Обе стороны должны однозначно ссылаться на MEMORY. + matches = [r for r in regions if r.name == section[key] and (section['page'] is None or r.page == section['page'])] # PAGE разрешает имя, не создавая физическую память. + if len(matches) != 1: # Пропущенное либо неоднозначное назначение не исправляется догадкой. + issues.append(issue('error', 'SECTION_TARGET', f"{section['name']}: {key.upper()}={section[key]} не определён однозначно; проверьте имя и PAGE.")) # Даёт конкретную сторону LOAD/RUN. + else: # Однозначный регион доступен для аппаратных проверок. + targets[key] = matches[0] # Сохраняет назначение без изменения исходной карты. + if section['type'] not in ('DSECT', 'NOLOAD', 'COPY'): # Эти типы не загружают содержимое в ROM/OTP. + for target in set(targets.values()): # Обычный совпадающий LOAD/RUN проверяется один раз. + start, end = physical(target, device) # Зеркала не обходят защиту памяти. + for name, left, right in reserves(device, boot): # Даже именованный резерв нельзя занять обычной секцией. + if start < right and left < end and not (name == 'FLASH_BEGIN' and section['name'] == 'codestart' and boot == 'flash'): # Исключение — аппаратный двухсловный branch Flash. + issues.append(issue('error', 'RESERVED_SECTION', section['name'] + ': загрузка в резерв ' + name)) # CSM/OTP не программируются автоматически. + if inside(start, end, (p['rom'],)): # Таблицы BootROM существуют, но не являются записываемой памятью. + issues.append(issue('error', 'ROM_LOAD', section['name'] + ': BootROM допускается только как NOLOAD/DSECT.')) # Не выпускает загружаемую секцию в ROM. + if boot == 'flash' and section['name'] in ('.text', '.cinit', '.pinit', '.econst', '.switch') and section['type'] not in ('DSECT', 'NOLOAD', 'COPY'): # После холодного Flash reset обычные инициализированные секции должны иметь сохраняемую копию. + if 'load' not in targets or not inside(*physical(targets['load'], device), (p['flash'],)): # RUN в RAM допустим только при явной стороне LOAD во Flash. + issues.append(issue('error', 'FLASH_LOAD', section['name'] + ': Flash boot требует LOAD во внутренней Flash; загружаемая только в RAM секция исчезнет после reset.')) # Не принимает JTAG-образ RAM за автономно запускаемую Flash-прошивку. + if section['name'] == 'codestart' and 'load' in targets: # Проверяет место длинной ветви независимо от имени региона BEGIN. + target, entry = targets['load'], p['begin'] if boot == 'flash' else p['ram_entry'] # RAM boot2812 использует H0; RAM boot28335 — M0. + if target.origin != entry or target.length != 2 or section['load'] != section['run'] or section['type'] in ('DSECT', 'NOLOAD', 'COPY'): # Пустое или копируемое представление не запускается аппаратным boot ROM. + issues.append(issue('error', 'CODESTART', f'codestart должен загружаться в отдельные 2 слова по адресу 0x{entry:X}.')) # Фактическая длина branch дополнительно проверяется MAP. + if section['name'] in ('ramfuncs', '.TI.ramfunc') and boot == 'flash': # Эти функции исполняются из RAM после копирования из Flash. + load_ok = 'load' in targets and inside(*physical(targets['load'], device), (p['flash'],)) # Адрес хранения должен принадлежать Flash выбранного MCU. + run_ok = 'run' in targets and inside(*physical(targets['run'], device), p['ram']) # Адрес исполнения должен принадлежать встроенной RAM. + symbols_ok = all(re.search(r'\b' + op + r'\s*\(', section['body']) for op in ('LOAD_START', 'RUN_START')) and any(re.search(r'\b' + op + r'\s*\(', section['body']) for op in ('LOAD_SIZE', 'LOAD_END')) # Требует минимальные символы адреса источника, назначения и длины memcpy. + if not (load_ok and run_ok and symbols_ok): # Обычное размещение ramfuncs во Flash не считается выполнением условия. + issues.append(issue('error', 'RAMFUNCS_COPY', section['name'] + ': нужны LOAD=Flash, RUN=RAM и LOAD_START/RUN_START и LOAD_SIZE либо LOAD_END.')) # Сам memcpy приложение обязано выполнить до InitFlash. + if boot == 'flash' and not any(s['name'] == 'codestart' for s in sections): # Прямой запуск main отладчиком не заменяет аппаратную точку входа. + issues.append(issue('error', 'NO_CODESTART', 'Нет codestart; добавьте TI CodeStartBranch.asm и двухсловный BEGIN.')) # Подсказывает обязательный стартовый исходник. + if boot == 'flash' and not any(s['name'] in ('ramfuncs', '.TI.ramfunc') for s in sections): # Flash-карта должна описывать место кода настройки Flash в RAM. + issues.append(issue('error', 'NO_RAMFUNCS', 'Нет ramfuncs/.TI.ramfunc с копированием Flash→RAM.')) # Не обещает безопасную InitFlash только по наличию .text. + return issues # Неполнота синтаксиса добавляется отдельно результатом parse_cmd. + + +def generate(device, boot): # Возвращает стартовый CMD COFF без предположений о внешней плате. + p, regions = DEVICES[device], [] # Берёт профиль ровно указанной модели. + regions.append(Region('BEGIN', 0, p['begin'] if boot == 'flash' else p['ram_entry'], 2)) # Два слова оставлены только branch codestart. + if device == '28335': # RAML0–L3 используют только нижний адрес, без одновременного высокоадресного зеркала. + regions.extend((Region('RAM_CODE', 0, 0x8000, 0x1000 if boot == 'flash' else 0x4000), Region('RAM_DATA', 1, 0x9000 if boot == 'flash' else 0xC000, 0x7000 if boot == 'flash' else 0x4000))) # Код и данные физически разделены, а Flash имеет отдельную RAM для RUN. + else: # У 2812 H0 выделяется коду при RAM boot и данным при Flash boot. + regions.extend((Region('RAM_CODE', 0, 0x8000 if boot == 'flash' else 0x3F8002, 0x1000 if boot == 'flash' else 0x1FFE), Region('RAM_DATA', 1, 0x3F8000 if boot == 'flash' else 0x8000, 0x2000))) # H0 не перекрывает L0/L1 и не подменяется XINTF. + regions.extend((Region('RAMM0', 1, 0x50, 0x3B0), Region('RAMM1', 1, 0x400, 0x400))) # Первые 80 слов M0 консервативно зарезервированы для BootROM; M1 предназначен стеку. + if boot == 'flash': # Объединённый Flash-регион заканчивается до CSM_RSVD. + regions.append(Region('FLASH_APP', 0, p['flash'][0], p['begin'] - 0x76 - p['flash'][0])) # Поддерживает доступные секторы без программирования пароля и boot-entry обычными данными. + regions.extend((Region('RESET', 0, 0x3FFFC0, 2), Region('CSM_RSVD', 0, p['begin'] - 0x76, 0x76), Region('CSM_PWL', 0, p['begin'] + 2, 8))) # CSM показан явно, но не получает загружаемых секций. + lines = [f'/* Стартовая карта TMS320F{device}, {boot.upper()}, COFF; все адреса и размеры — слова 16 бит. */', '/* Добавьте TI CodeStartBranch.asm и Headers_nonBIOS.cmd; настройте RTS, стек и копирование RAM-функций по README. */', 'MEMORY /* PAGE0/PAGE1 не являются независимой физической RAM. */', '{ /* Начало встроенной памяти выбранного MCU. */'] # Русские пояснения сопровождают каждую генерируемую строку кода. + for page in (0, 1): # Порядок повторяет обычное оформление примеров TI. + lines.append(f'PAGE {page}: /* Логическая страница линкера; физические интервалы не дублируются. */') # Не разрешает повторно использовать один адрес на другой странице. + for region in (r for r in regions if r.page == page): # Выводит каждый регион один раз. + lines.append(f' {region.name} : origin = 0x{region.origin:06X}, length = 0x{region.length:06X} /* {region.length} слов; аппаратные адреса профиля TI. */') # Значения переносимы между проектами выбранного MCU. + lines.extend(('} /* Конец MEMORY; внешняя память сюда не добавлена. */', 'SECTIONS /* Назначения стандартных COFF-секций. */', '{ /* Начало выходных секций. */', ' codestart : > BEGIN, PAGE = 0 /* Длинный branch из TI CodeStartBranch.asm в _c_int00. */')) # codestart остаётся отдельным от .text. + program = 'FLASH_APP' if boot == 'flash' else 'RAM_CODE' # Инициализированный код хранится в выбранном загрузочном носителе. + for section in ('.text', '.cinit', '.pinit', '.econst', '.switch'): # Имена соответствуют COFF, а не неподдерживаемому EABI. + lines.append(f' {section} : > {program}, PAGE = 0 /* Код, константы или таблицы инициализации COFF. */') # Не создаёт фиктивной адресуемой области EEPROM. + if boot == 'flash': # Исторические и современные RAM-функции входят в одну выходную секцию копирования. + lines.append(' ramfuncs : { *(ramfuncs) *(.TI.ramfunc) } LOAD = FLASH_APP, RUN = RAM_CODE, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), LOAD_SIZE(_RamfuncsLoadSize), RUN_START(_RamfuncsRunStart), PAGE = 0 /* До первого вызова скопируйте LoadSize слов из LoadStart в RunStart. */') # COFF linker-символам с подчёркиванием соответствуют C-имена без него. + else: # При RAM boot JTAG/boot-таблица загружает код сразу по исполняемому адресу. + lines.append(' ramfuncs : { *(ramfuncs) *(.TI.ramfunc) } > RAM_CODE, PAGE = 0 /* Отдельное копирование из внутренней Flash не требуется. */') # Не генерирует вымышленные Flash copy-symbols. + for section in ('.ebss', '.esysmem', '.cio'): # Изменяемые данные обязательно попадают в RAM. + lines.append(f' {section} : > RAM_DATA, PAGE = 1 /* Переменные, динамическая память или служебный буфер COFF. */') # Фактический объём проверяется линкером и MAP. + lines.extend((' .stack : > RAMM1, PAGE = 1 /* Размер --stack_size не должен превышать 1024 слова M1. */', ' .reset : > RESET, PAGE = 0, TYPE = DSECT /* Reset-vector находится в BootROM и не программируется. */', '} /* CSM/OTP намеренно не имеют загружаемых секций. */')) # Генерация никогда не создаёт пароль безопасности. + return '\n'.join(lines) + '\n' # Возвращает UTF-8 текст с конечным переводом строки. + + +def inspect_map(text, regions, sections, device, boot): # Сверяет поддерживаемый текстовый MAP TI с фактическими назначениями CMD. + issues, allocations = [], [] # MAP добавляет размеры секций, которых нет в исходном CMD. + if 'MEMORY CONFIGURATION' not in text or 'SECTION ALLOCATION MAP' not in text: # Не принимает XML/лог или усечённый файл за обычный MAP TI. + return [issue('incomplete', 'MAP_FORMAT', 'Нужен текстовый MAP TI C2000 с MEMORY CONFIGURATION и SECTION ALLOCATION MAP.')], [] # Частичный формат даёт статус 2. + memory = text.split('MEMORY CONFIGURATION', 1)[1].split('SECTION ALLOCATION MAP', 1)[0] # Исключает таблицы входных секций из разбора MEMORY. + map_regions, page = {}, 0 # PAGE участвует в идентификации названия региона. + for line in memory.splitlines(): # Таблица TI задаёт origin/length/used/unused шестнадцатерично. + mark = re.fullmatch(r'\s*PAGE\s+([01]):\s*', line) # Переключает только логическую страницу записи. + if mark: # Новая страница относится к последующим MEMORY-строкам. + page = int(mark[1]) # Физические интервалы будут проверены независимо от PAGE. + match = re.match(r'\s*(' + NAME + r')\s+([\da-fA-F]{8})\s+([\da-fA-F]{8})\s+([\da-fA-F]{8})\s+([\da-fA-F]{8})\b', line) # Не путает заголовки с числовыми строками. + if match: # Только полноценная строка даёт надёжное сравнение с CMD. + map_regions[match[1], page] = tuple(int(match[i], 16) for i in (2, 3, 4, 5)) # Размеры остаются словами C28x. + for region in regions: # Каждый понятный исходный регион должен присутствовать в MAP этой же сборки. + found = map_regions.get((region.name, region.page)) # Не ищет ближайшее совпадение по адресу другой страницы. + if not found or found[:2] != (region.origin, region.length): # Выявляет старый MAP и линковку с другим CMD. + issues.append(issue('error', 'MAP_MEMORY', region.name + ': origin/length/PAGE MAP не совпадают с CMD.')) # Объясняет необходимость передать карту текущей линковки. + table = text.split('SECTION ALLOCATION MAP', 1)[1].split('GLOBAL SYMBOLS', 1)[0] # Глобальные символы не являются отдельными выделениями секций. + table = re.sub(r'(?m)^(' + NAME + r')[ \t]*\n[ \t]*\*?[ \t]+([01])\s+([\da-fA-F]{8})', r'\1 \2 \3', table) # TI переносит длинное имя выходной секции на предыдущую строку. + heads = list(re.finditer(r'(?m)^(' + NAME + r')\s+\*?\s*([01])\s+([\da-fA-F]{8})\s+([\da-fA-F]{8})([^\n]*)', table)) # Строки input objects имеют отступ и не дублируются. + for index, match in enumerate(heads): # Фактические непустые секции проверяются обеими сторонами LOAD/RUN. + name, page, origin, length = match[1], int(match[2]), int(match[3], 16), int(match[4], 16) # Все числовые колонки TI представлены без префикса 0x. + rule = next((s for s in sections if s['name'] == name), None) # Связывает результат линковки с исходным назначением. + if not rule: # MAP может включать дополнительные headers.cmd, не переданные анализатору. + issues.append(issue('incomplete', 'MAP_SECTION', name + ': секция отсутствует в переданном CMD; полный объединённый CMD не проверен.')) # Отсутствие знания явно снижает полноту результата. + continue # Не угадывает назначение периферийных секций. + if not length or rule['type'] in ('DSECT', 'COPY'): # Пустые и фиктивные секции не занимают физические слова приложения. + continue # Не создаёт ложного пересечения ROM-reset с загрузкой. + attrs = match[5] + table[match.end():heads[index + 1].start() if index + 1 < len(heads) else len(table)] # RUN ADDR может быть напечатан на следующей строке атрибутов. + run = re.search(r'RUN\s+ADDR\s*=\s*([\da-fA-F]{8})', attrs) # Адрес исполнения нельзя подменять Flash-адресом хранения. + addresses = [('load', origin), ('run', int(run[1], 16))] if run else [('load', origin)] # Копируемая секция реально занимает два интервала. + if rule['load'] != rule['run'] and not run: # Неподдерживаемое оформление MAP нельзя объявлять полной проверкой RUN. + issues.append(issue('incomplete', 'MAP_RUN', name + ': не найден RUN ADDR для раздельного LOAD/RUN.')) # Показывает предел конкретного MAP-парсера. + for kind, address in addresses: # Каждый интервал должен помещаться в указанном MEMORY-регионе. + target = next((r for r in regions if r.name == rule[kind] and (rule['page'] is None or r.page == rule['page'])), None) # Повторяет однозначное разрешение назначения TI. + if not target or not target.origin <= address < address + length <= target.origin + target.length: # Проверяет конец всей секции, а не только её начало. + issues.append(issue('error', 'MAP_ALLOCATION', f'{name}/{kind}: 0x{address:X}+0x{length:X} вне назначенного MEMORY.')) # Конкретные адрес и размер помогают исправить карту. + current = Region(name + '/' + kind, page, address, length) # Фактическая запись пригодна для общей проверки физического пересечения. + start, end = physical(current, device) # Высокое зеркало F28335 нормализуется как в CMD. + for old in allocations: # PAGE не является исключением из физической проверки. + left, right = physical(old, device) # Оба сравниваемых интервала имеют одинаковую систему адресов. + if start < right and left < end: # Конец, равный началу следующей секции, разрешён. + issues.append(issue('error', 'MAP_OVERLAP', current.name + ' пересекается с ' + old.name)) # Выявляет также конфликт Flash LOAD с другой секцией. + allocations.append(current) # Следующая секция будет сравниваться с этим размещением. + if name == 'codestart' and (origin != (DEVICES[device]['begin'] if boot == 'flash' else DEVICES[device]['ram_entry']) or length != 2): # Реальная ветвь должна занимать два слова в аппаратной точке входа. + issues.append(issue('error', 'MAP_CODESTART', 'Размер/адрес codestart не соответствует выбранному boot mode.')) # Подтверждает то, что невозможно узнать из одного назначения >BEGIN. + if name in ('ramfuncs', '.TI.ramfunc') and boot == 'flash': # Проверяет наличие именно созданных copy-symbols текущей секции. + expected = {'LOAD_START': origin, 'LOAD_END': origin + length, 'LOAD_SIZE': length, 'RUN_START': int(run[1], 16) if run else None} # Символы должны соответствовать фактическим LOAD/RUN, а не старой сборке. + for op, value in expected.items(): # LOAD_END необязателен в пользовательском CMD; генератор всегда его создаёт. + symbol = re.search(r'\b' + op + r'\s*\(\s*(' + NAME + r')\s*\)', rule['body']) # Имя может отличаться от стандартного Ramfuncs. + if symbol: # Проверяет только явно заказанные символы, сохраняя минимальный контракт LOAD_SIZE. + values = re.findall(r'(?m)^\s*(?:(?:[01]|[A-Za-z_]\w*)\s+)?([\da-fA-F]{8})\s+' + re.escape(symbol[1]) + r'\b', text) # TI печатает символы также в нескольких отсортированных таблицах. + if not values or value is None or any(int(item, 16) != value for item in values): # Наличие слова имени само по себе не подтверждает правильный адрес или размер. + issues.append(issue('error', 'MAP_COPY_SYMBOL', symbol[1] + ': значение MAP не соответствует выделенной секции.')) # Не принимает ложные символы копирования. + if boot == 'flash' and not any(r.name == 'codestart/load' for r in allocations): # Flash boot нуждается в реально загружаемой ветви; одно пустое назначение CMD недостаточно. + issues.append(issue('error', 'MAP_NO_CODESTART', 'MAP не содержит непустой codestart для аппаратного Flash boot.')) # Не подтверждает Flash-образ, запускаемый только прямым переходом отладчика. + if not heads: # Пустой результат не подтверждает реальную укладку приложения. + issues.append(issue('incomplete', 'MAP_EMPTY', 'Не распознаны выходные секции текстового MAP TI.')) # Просит поддерживаемый MAP вместо ложного успеха. + return issues, allocations # Возвращает фактические слова также для JSON/inspect. + + +def main(argv=None): # Выполняет только явно выбранное офлайн-действие. + parser = argparse.ArgumentParser(description=__doc__) # Русская справка объясняет применение отдельной утилиты. + sub = parser.add_subparsers(dest='command', required=True) # По умолчанию пользовательские файлы не создаются. + sub.add_parser('profiles', aliases=['list'], help='Список MCU, boot modes и ABI.') # Не требует SDK или проекта. + exp = sub.add_parser('explain', help='Объяснить память и резервы MCU.') # Поясняет единицы и аппаратные границы. + exp.add_argument('--device', choices=DEVICES, required=True, help='MCU:28335 или 2812.') # Не угадывает похожую модель устройства. + gen = sub.add_parser('generate', help='Создать стартовый CMD COFF.') # Единственное действие записи входных файлов. + gen.add_argument('--output', type=Path, required=True, help='Создаваемый .cmd.') # Местоположение задаёт пользователь. + gen.add_argument('--force', action='store_true', help='Явно разрешить замену существующего файла.') # Без ключа файл защищён от перезаписи. + readers = [sub.add_parser(name, help='Показать и проверить понятную часть CMD/MAP.') for name in ('inspect', 'validate')] # Оба режима читают существующие карты без редактирования. + for command in [gen, *readers]: # Аппаратные параметры нужны всем действиям с картой. + command.add_argument('--device', choices=DEVICES, required=True, help='Ожидаемый MCU.') # Выбор устройства определяет карту, CSM и точку boot. + command.add_argument('--boot', choices=('ram', 'flash'), required=True, help='RAM boot/JTAG либо внутренняя Flash.') # EEPROM boot-таблица относится к ram. + for command in readers: # Только режимы проверки принимают исходные CMD/MAP. + command.add_argument('cmd', type=Path, help='Исходный или предварительно обработанный CMD TI.') # include не читаются и не вычисляются Python автоматически. + command.add_argument('--map', type=Path, help='Текстовый MAP той же линковки.') # Даёт фактические размеры и LOAD/RUN после TI linker. + command.add_argument('--json', action='store_true', help='Структурированный JSON UTF-8.') # Отчёт пригоден для непрерывной сборки. + args = parser.parse_args(argv) # Ошибочный CLI получает стандартный ненулевой статус argparse. + if args.command in ('profiles', 'list'): # Каталог не связан с текущим проектом. + print('TMS320F28335 иTMS320F2812: ram/flash, COFF. EABI не поддерживается.') # Не обещает непроверенный ABI. + return 0 # Простой вывод списка не является аппаратной проверкой. + if args.command == 'explain': # Сводка связывает числа с обязательными действиями при старте. + p = DEVICES[args.device] # Выбирает аппаратные диапазоны для понятной человеку таблицы hex-адресов. + print('TMS320F' + args.device + ' / COFF / адреса и размеры в 16-битных словах') # Единицы C28x явно отличаются от обычных октетов файла. + for title, start, end in [('RAM', a, b) for a, b in p['ram']] + [('Flash', *p['flash']), ('Flash BEGIN', p['begin'], p['begin'] + 2), ('CSM reserve', p['begin'] - 0x76, p['begin']), ('CSM password', p['begin'] + 2, p['begin'] + 10), ('OTP', *p['otp'])]: # Выводит только общие встроенные блоки выбранной модели. + print(f'{title:14} 0x{start:06X}..0x{end - 1:06X} {end - start:6} слов') # Включённый конец удобен для сопоставления с таблицей datasheet. + print('TI flags: --abi=coffabi -v28 --float_support=softlib; F2812 не имеет FPU32.') # Стартовый профиль переносится между обеими моделями без аппаратной FPU. + print('Внешняя EEPROM хранит boot-таблицу и не увеличивает RAM; объём RAM проверяйте по MAP.') # Большая M95M02 не устраняет переполнение .text/.ebss в RAM. + print('Адреса и длины — слова 16 бит. PAGE0/PAGE1 физически общие. BEGIN —2 слова. CSM/OTP/BootROM не программируются. Flash ramfuncs копируются до InitFlash. См.README.') # Объясняет назначение резервов и LOAD/RUN. + return 0 # Пользовательская карта в этой команде не проверяется. + try: # Обычные ошибки пути и синтаксиса не скрываются traceback. + if args.command == 'generate': # Выполняет только явно запрошенную запись. + text = generate(args.device, args.boot) # Получает готовый UTF-8 шаблон COFF. + regions, sections, issues = parse_cmd(text) # Проверяет встроенную карту тем же parser, что пользовательскую. + issues += validate_cmd(regions, sections, args.device, args.boot) # Ошибка генератора не должна попасть в проект. + if issues: # Собственный шаблон обязан поддерживаться целиком. + raise ValueError('; '.join(i['message'] for i in issues)) # Не сохраняет сомнительный или частично проверенный CMD. + with args.output.open('w' if args.force else 'x', encoding='utf-8', newline='\n') as stream: # Режим x атомарно защищает существующий файл от случайной замены. + stream.write(text) # Каждая строка CMD сопровождается русским комментарием. + print('Создан ' + str(args.output) + '; добавьте стартовый код и проверьте MAP/README.') # Шаблон не считается готовой прошивкой платы. + return 0 # Генератор не запускает программатор или сторонний процесс. + regions, sections, issues = parse_cmd(args.cmd.read_text(encoding='utf-8-sig')) # Поддерживает пользовательский UTF-8 с BOM без изменения файла. + allocations = [] # Без MAP реальный размер секций неизвестен. + if args.map: # Дополнительная проверка выполняется только по явно переданной карте. + extra, allocations = inspect_map(args.map.read_text(encoding='utf-8-sig'), regions, sections, args.device, args.boot) # Не читает COFF и бинарные прошивки. + issues += extra # Ограничения MAP также участвуют в итоговом статусе. + active = {r.name.rsplit('/', 1)[0] for r in allocations} if args.map else None # Без MAP все назначения потенциальны; с MAP пустые CSM-секции не выдаются за запись Flash. + issues += validate_cmd(regions, sections, args.device, args.boot, active) # Физические MEMORY-пересечения проверяются всегда; фактическая загрузка секций уточняется MAP. + status = 1 if any(i['level'] == 'error' for i in issues) else 2 if issues else 0 # Код 1 — найденное нарушение, код 2 — неполная проверка. + report = {'status': status, 'scope': 'Подмножество CMD; без MAP размеры секций неизвестны. TI linker и стартовый код проверяются отдельно.', 'device': args.device, 'boot': args.boot, 'regions': [r.__dict__ for r in regions], 'sections': sections, 'allocations': [r.__dict__ for r in allocations], 'issues': issues} # Машинный результат не теряет пределы применимости анализа. + if args.json: # JSON не смешивается с обычными строками stdout. + print(json.dumps(report, ensure_ascii=False, indent=2)) # Русские пояснения остаются читаемыми UTF-8. + else: # Человеческий режим показывает карту и все ограничения. + for region in regions: # Страница выводится рядом с физическим адресом для объяснения конфликта. + print(f'{region.name:14} PAGE{region.page} 0x{region.origin:06X}..0x{region.origin + region.length - 1:06X} ({region.length} слов)') # Правая граница включённая только при выводе человеку. + for item in issues: # Неподдерживаемая конструкция не скрывается за успешным частичным разбором. + print(f"{item['level'].upper()} {item['code']}: {item['message']}") # Стабильный код помогает автоматизировать диагностику. + print('Проверенная часть: нарушений не найдено; размеры требуют MAP/TI linker.' if not issues else 'Есть ошибки/непроверенные конструкции; вся карта не подтверждена.') # Не приравнивает статический успех к полной аппаратной проверке. + return status # Возвращает результат без изменения CMD/MAP. + except (OSError, ValueError) as error: # Отсутствующий путь, существующий файл и неверный формат имеют понятный отказ. + print('ОШИБКА: ' + str(error), file=sys.stderr) # stderr не портит структурированный успешный отчёт. + return 1 # Неудача чтения/генерации не может считаться проверкой. + +if __name__ == '__main__': # Импорт в unittest не выполняет CLI и не создаёт файлы. + raise SystemExit(main()) # Передаёт точный статус процессу сборки. diff --git a/tools/c2000-linker/tests/run_tests.py b/tools/c2000-linker/tests/run_tests.py new file mode 100644 index 0000000..3cc8f35 --- /dev/null +++ b/tools/c2000-linker/tests/run_tests.py @@ -0,0 +1,112 @@ +"""Регрессии карт памяти и необязательная реальная COFF-линковка четырёх профилей TI.""" # Проверяет полезные свойства карты, не повторяя реализацию parser. +import argparse # Принимает необязательный путь к установленному TI CGT для smoke. +import contextlib # Перехватывает stdout CLI при проверке отказа перезаписи. +import importlib.util # Импортирует helper относительно каталога теста без установки пакета. +import re # Разбирает контекст диагностической строки MAP при отказе smoke, не меняя рабочий parser. +import io # Сохраняет русскую диагностику CLI в памяти теста. +from pathlib import Path # Временные CMD/MAP не пишутся в пользовательский проект. +import subprocess # Вызывает настоящий TI compiler/linker только по явному параметру --ti. +import sys # Даёт возможность запускать тесты обычным Python3. +import tempfile # Удаляет только собственные временные сборки после тестов. +import unittest # Стандартная библиотека не требует pytest или скачивания зависимостей. +ROOT = Path(__file__).resolve().parents[1] # Находит установленную утилиту независимо от рабочего каталога. +SPEC = importlib.util.spec_from_file_location('c2000_linker', ROOT / 'c2000_linker.py') # Загружает именно проверяемый файл helper. +HELPER = importlib.util.module_from_spec(SPEC) # Создаёт модуль без запуска CLI. +sys.modules[SPEC.name] = HELPER # dataclass находит собственный модуль при аннотировании Region. +SPEC.loader.exec_module(HELPER) # Исполняет только определения функций и числовых профилей. +TI_ROOT = None # Путь compiler задаётся пользователем тестов, не ищется в глобальной системе молча. + + +def checked(text, device='28335', boot='flash'): # Проверяет сгенерированный или намеренно повреждённый CMD реальными функциями helper. + regions, sections, issues = HELPER.parse_cmd(text) # Использует рабочий parser, а не его тестовую копию. + return regions, sections, issues + HELPER.validate_cmd(regions, sections, device, boot) # Сохраняет и неполный синтаксис, и аппаратные нарушения. + + +class MapsTest(unittest.TestCase): # Проверяет границы ответственности и основные причины реальных ошибок linker. + def test_four_profiles(self): # Обе модели и оба boot mode должны генерироваться без неполной проверки. + for device in ('28335', '2812'): # F2812 не наследует адреса Flash или зеркала F28335. + for boot in ('ram', 'flash'): # RAM boot и внутренняя Flash имеют разные BEGIN. + with self.subTest(device=device, boot=boot): # Показывает конкретный аппаратный профиль при регрессии. + regions, sections, issues = checked(HELPER.generate(device, boot), device, boot) # Проверяет готовый текст, включая каждый русский комментарий CMD. + self.assertEqual(issues, []) # Собственные профили обязаны поддерживаться полностью. + self.assertEqual(next(r for r in regions if r.name == 'BEGIN').origin, HELPER.DEVICES[device]['begin' if boot == 'flash' else 'ram_entry']) # BEGIN соответствует первичным адресам TI. + def test_overlap_across_pages(self): # PAGE0/PAGE1 не дают две независимые копии L0. + text = HELPER.generate('28335', 'flash').replace('RAM_DATA : origin = 0x009000', 'RAM_DATA : origin = 0x008000') # Намеренно размещает данные поверх RAM-функций на другой странице. + self.assertIn('PHYSICAL_OVERLAP', [i['code'] for i in checked(text)[2]]) # Ошибка обнаруживается до запуска TI. + def test_high_alias(self): # Высокое зеркало L0–L3 также не добавляет физической RAM. + text = HELPER.generate('28335', 'ram').replace('RAM_DATA : origin = 0x00C000', 'RAM_DATA : origin = 0x3F8000') # Данные используют высокое зеркало того же L0–L3, где лежит код. + self.assertIn('PHYSICAL_OVERLAP', [i['code'] for i in checked(text, boot='ram')[2]]) # Проверка сравнивает физические адреса, а не строки чисел. + def test_flash_reserved(self): # Широкий FLASH_APP не может поглотить CSM_RSVD, BEGIN и пароль. + text = HELPER.generate('2812', 'flash').replace('length = 0x01FF80', 'length = 0x020000') # Расширяет код до физического конца Flash поверх служебных слов. + self.assertIn('RESERVED_REGION', [i['code'] for i in checked(text, '2812')[2]]) # Адреса 2812 сверяются по собственному профилю. + def test_otp_write(self): # Отдельное имя OTP не разрешает программировать его обычной секцией. + text = HELPER.generate('28335', 'flash').replace('PAGE 0:', 'PAGE 0:\n OTP : origin = 0x380400, length = 0x400', 1).replace(' .reset :', ' unsafe : > OTP, PAGE = 0\n .reset :') # Вводит потенциально необратимую загрузку данных в OTP. + self.assertIn('RESERVED_SECTION', [i['code'] for i in checked(text)[2]]) # Наличие резервного MEMORY не делает его записываемой RAM. + def test_flash_text_cannot_load_only_to_ram(self): # Рабочий после JTAG код не обязательно сохраняется при холодном Flash reset. + text = HELPER.generate('28335', 'flash').replace('.text : > FLASH_APP', '.text : > RAM_CODE') # Сохраняет корректные codestart и ramfuncs, но намеренно теряет постоянную копию основного кода. + self.assertIn('FLASH_LOAD', [i['code'] for i in checked(text)[2]]) # Flash-профиль не должен подтверждать такую карту полным успехом. + def test_copy_contract(self): # Flash RAM-функции требуют источника, назначения и количества слов. + text = HELPER.generate('28335', 'flash').replace('LOAD_SIZE(_RamfuncsLoadSize),', '').replace('LOAD_END(_RamfuncsLoadEnd),', '') # Удаляет только размер копирования, сохраняя остальные корректные назначения. + self.assertIn('RAMFUNCS_COPY', [i['code'] for i in checked(text)[2]]) # Отсутствие одного обязательного символа действительно обнаруживается. + def test_copy_end_alternative(self): # Исторический memcpy вправе вычислять размер как LoadEnd-LoadStart. + text = HELPER.generate('28335', 'flash').replace('LOAD_SIZE(_RamfuncsLoadSize),', '') # Оставляет действующие LOAD_END и оба начальных адреса. + self.assertEqual(checked(text)[2], []) # Не требует лишнего LOAD_SIZE у совместимых старых проектов TI. + def test_incomplete_preprocessor(self): # include и выражения не должны исчезать из итогового статуса. + text = '#include "board.cmd"\n' + HELPER.generate('28335', 'ram') # Неизвестный файл мог бы изменить физическую карту. + self.assertIn('PREPROCESSOR', [i['code'] for i in checked(text, boot='ram')[2]]) # Пользователь получает явно неполную проверку. + def test_unknown_syntax(self): # GROUP/UNION и split не интерпретируются ограниченным parser как обычный регион. + text = HELPER.generate('28335', 'ram').replace('.text : > RAM_CODE', '.text : >> RAM_CODE') # Требует поддерживаемого только TI разбиения секции. + self.assertIn('ADVANCED_SYNTAX', [i['code'] for i in checked(text, boot='ram')[2]]) # Поддерживаемая часть карты не даёт ложного полного успеха. + def test_unparsed_extra_blocks(self): # Грамматика не может молча проверить только начало сложного CMD. + text = HELPER.generate('28335', 'ram') # Использует заведомо корректную исходную карту. + extra = text + 'MEMORY { PAGE 1: OTHER : origin = 0x8000, length = 0x100 }' # Второй блок мог бы занять уже используемые физические слова. + self.assertIn('MULTIPLE_BLOCKS', [i['code'] for i in checked(extra, boot='ram')[2]]) # Даже численно понятный первый блок не даёт полного успеха. + prefix = text.replace('{ /* Начало выходных секций. */', '{ BROKEN_DIRECTIVE /* Начало выходных секций. */') # Вставляет неизвестный префикс, который не является телом предыдущей секции. + self.assertIn('SECTION_PREFIX', [i['code'] for i in checked(prefix, boot='ram')[2]]) # Произвольное начальное содержимое явно делает проверку неполной. + def test_no_overwrite(self): # Файл пользователя сохраняется без явно указанного --force. + with tempfile.TemporaryDirectory() as tmp: # Выделяет отдельный безопасный каталог для проверки записи. + target = Path(tmp) / 'board.cmd' # Существующий linker-файл не связан с рабочим проектом. + target.write_text('USER FILE', encoding='utf-8') # Контрольное содержимое должно остаться неизменным. + with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()): # Не засоряет успешный вывод ожидаемой ошибкой CLI. + result = HELPER.main(['generate', '--device', '2812', '--boot', 'ram', '--output', str(target)]) # Проверяет настоящий режим x, а не предварительный exists. + self.assertEqual(result, 1) # Отказ перезаписи имеет ненулевой код. + self.assertEqual(target.read_text(encoding='utf-8'), 'USER FILE') # Пользовательские данные не изменены. + def test_unknown_map(self): # Произвольный лог не считается успешно проверенным MAP. + regions, sections, unused = checked(HELPER.generate('28335', 'ram'), boot='ram') # Даёт анализатору корректный исходный CMD. + issues, allocations = HELPER.inspect_map('not a TI map', regions, sections, '28335', 'ram') # Пробует заведомо чужой текстовый формат. + self.assertEqual(issues[0]['code'], 'MAP_FORMAT') # Отказ объясняет нужный формат TI. + + +class TiSmokeTest(unittest.TestCase): # Тестирует реальную грамматику и MAP TI вместо тестовых выдуманных адресов. + def test_real_ti_four_profiles(self): # Четыре настоящие COFF-сборки выполняются только с указанным установленным CGT. + if TI_ROOT is None: # Обычные stdlib-тесты остаются переносимыми без проприетарного компилятора. + self.skipTest('Для четырёх настоящих TI линковок задайте --ti .') # Пропуск явно виден в отчёте. + compiler = TI_ROOT / 'bin/cl2000.exe' # На Windows smoke использует согласованный пользователем установленный TI CGT. + self.assertTrue(compiler.is_file(), str(compiler)) # Не подменяет отсутствие компилятора успешной проверкой Python. + with tempfile.TemporaryDirectory(prefix='c2000-linker-ti-') as tmp: # Все объектные файлы и MAP находятся только во временном каталоге. + folder = Path(tmp) # Минимальная сборка не зависит от SDK или пользовательского проекта. + source = folder / 'fixture.c' # Исходник содержит типичные секции COFF обоих устройств. + source.write_text('volatile int observed; /* Создаёт изменяемую .ebss для проверки RAM. */\nconst int setting = 17; /* Создаёт .econst с числовой константой без аппаратного адреса. */\n#pragma CODE_SECTION(ram_old, "ramfuncs") /* Проверяет историческое имя секции RAM-кода. */\nint ram_old(void) { return observed + setting; } /* Даёт непустой LOAD/RUN для проверки размера копирования. */\n#pragma CODE_SECTION(ram_new, ".TI.ramfunc") /* Проверяет современную входную секцию в том же копируемом блоке. */\nint ram_new(void) { return observed + 2; } /* Не требует FPU32, аппаратных заголовков или RTS-арифметики. */\nint main(void) { observed = ram_old() + ram_new(); return 0; } /* Только проверяет линковку; этот тест никогда не запускается на MCU. */\n', encoding='utf-8') # Каждая строка fixture имеет осмысленный русский комментарий. + start = folder / 'start.asm' # Собственный минимальный branch исключает зависимость теста от TI SDK. + start.write_text(' .sect "codestart" ; Помещает проверочную двухсловную ветвь в аппаратный BEGIN.\n .global _boot_start ; Задаёт явную точку входа COFF для теста линкера.\n .ref _main ; Объявляет цель из минимального C-файла.\n_boot_start: LB _main ; Длинная ветвь занимает два слова C28x без настройки периферии.\n', encoding='utf-8') # Не выдаёт smoke branch за полноценный CodeStartBranch промышленного приложения. + for device in ('28335', '2812'): # Оба устройства собираются как C28x без FPU32. + for boot in ('ram', 'flash'): # Проверяет отдельный BEGIN, RAM и Flash LOAD/RUN. + with self.subTest(device=device, boot=boot): # Ошибка указывает конкретный профиль. + prefix = folder / (device + '_' + boot) # Разные OUT/MAP исключают использование предыдущей сборки. + cmd = prefix.with_suffix('.cmd') # Выбирает самостоятельную карту для данной линковки. + cmd.write_text(HELPER.generate(device, boot), encoding='utf-8') # В тест идёт именно пользовательский генератор. + subprocess.run([str(compiler), '--abi=coffabi', '-v28', '--float_support=softlib', '--compile_only', str(source), str(start)], cwd=folder, check=True, capture_output=True, text=True) # Настоящий TI компилирует оба fixture без FPU/SDK. + result = subprocess.run([str(compiler), '-v28', '--abi=coffabi', '--run_linker', '--rom_model', '--entry_point=_boot_start', '--stack_size=0x100', '--heap_size=0x40', '--output_file=' + str(prefix.with_suffix('.out')), '--map_file=' + str(prefix.with_suffix('.map')), str(folder / 'fixture.obj'), str(folder / 'start.obj'), str(cmd)], cwd=folder, capture_output=True, text=True) # TI проверяет секции, длины и синтаксис сгенерированной карты. + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) # Любая ошибка linker блокирует подтверждение профиля. + regions, sections, issues = checked(cmd.read_text(encoding='utf-8'), device, boot) # Проверяет ту же карту, что фактически получил TI. + extra, allocations = HELPER.inspect_map(prefix.with_suffix('.map').read_text(encoding='utf-8'), regions, sections, device, boot) # Разбирает настоящий, а не нарисованный под parser MAP. + self.assertEqual(issues + extra, [], str(prefix) + ': ' + str(issues + extra) + '; allocations=' + str([r.name for r in allocations]) + '; codestart=' + str(re.findall(r'codestart[^\n]*\n[^\n]*\n[^\n]*', prefix.with_suffix('.map').read_text(encoding='utf-8')))) # Подтверждает совместимость исходного CMD, LOAD/RUN и реальных copy-symbols TI. + self.assertTrue(allocations) # Пустой MAP-парсер не может дать положительный smoke. + print('TI PASS TMS320F' + device + ' ' + boot + ': COFF, codestart, data, ramfuncs, MAP/copy symbols') # Сохраняет короткое подтверждение каждого реального профиля. + +if __name__ == '__main__': # Импорт теста не запускает компилятор автоматически. + parser = argparse.ArgumentParser(description=__doc__) # Справка описывает явное подключение TI smoke. + parser.add_argument('--ti', type=Path, help='Каталог установленного TI C2000 CGT; включает 4 реальные линковки.') # Не скачивает компилятор и не требует платы. + arguments, unittest_args = parser.parse_known_args() # Допускает обычные флаги unittest вроде-v. + TI_ROOT = arguments.ti.resolve() if arguments.ti else None # Фиксирует согласованный путь перед выполнением тестов. + unittest.main(argv=[sys.argv[0], *unittest_args]) # Возвращает ненулевой код при любой Python/TI регрессии. diff --git a/tools/firmware-build/README.md b/tools/firmware-build/README.md index 3ead431..e5531db 100644 --- a/tools/firmware-build/README.md +++ b/tools/firmware-build/README.md @@ -1,39 +1,199 @@ # Подключение precompile и postcompile из templates +Для проектов ПЛИС используйте [шаблон Xilinx ISE, Vivado и Altera/Intel Quartus](fpga/README.md): +общий сохраняемый итератор, паспорт на Verilog/VHDL, полная сборка `.bit`/`.sof`, +manifest, SHA-256 и архив выпуска. + +## Единая подготовка C2000 для 166/167 и Публикатора SETGUI + +Общая точка входа — `c/firmware-info/tools/c2000_build.py` с командами +`prepare` и `build`. CCS и совместимые `ccs/precompile.bat --identity` / +`ccs/postcompile.bat --identity` вызывают один процесс подготовки. + +`prepare` сохраняет JSON-счётчик старых проектов 166 либо читает ручную версию +из заголовка, заданного в `firmware_build_profile.json` проекта 167. Аппаратный +профиль содержит пути C-заголовков, имена макросов EEPROM и допустимые RAM-адреса +в 16-битных словах C28x. Ёмкость и размер SCI8 выражены в октетах. + +`build` проверяет встроенный паспорт, границу EEPROM, MAP, SHA-256, полноту +SCI8, Flash LOAD/RUN и точное соответствие Flash OUT ↔ Flash RS BIN до сохранения +постоянного выпуска. Проектный `build_flash.py` остаётся аппаратным сборщиком; +общих проверок или сетевых операций в нём нет. + +В текущей 167 каталог результата задан как `Debug/firmware/prepared` либо +`Release/firmware/prepared`; в остальных проектах он задаётся аргументом `--output`. +В этом каталоге создаётся папка +`HASH_дата_UTC+3` с RAM BIN, исходным RAM OUT, `*_flash.out` для JTAG, +`*_flash_rs.bin` для RS, картами, manifest и SHA-256. Flash-файлы создаются +только при наличии проектного `build_flash.py`. `latest_build.json` рядом +с папками указывает точную папку и основной manifest последнего успешного выпуска. + +Дальнейшая публикация выполняется в SETGUI: **Сервис → Прошивка → Публикатор → +Из папки postbuild / manifest → Импорт папки postbuild**. Выбирайте папку одной +сборки, указанную в `latest_build.json`. Для Flash по RS выбирайте manifest +`*_flash_rs.bin.manifest.json`; для JTAG можно выбрать основной RAM BIN manifest, +поскольку полный комплект содержит подписанный Flash OUT. Публикатор выбирает +Flash OUT по `execution=FLASH` и `image_format=COFF`, сохраняя соседний RAM OUT. +Проверьте назначение загрузчика и предпросмотр, затем публикуйте через штатное +хранилище Публикатора. Команды подготовки сами не создают сетевой выпуск. + +Ниже сохранены команды подключения старых проектов. Дополнительный аргумент +`export` остаётся совместимым локальным копированием; новые проекты могут +передавать готовый комплект прямо Публикатору без этого аргумента. + +## Пути на этом компьютере + +Самостоятельные постоянные CAN-загрузчики **F28335_CAN_AB** и **F2812_CAN_NOR** +имеют собственные prebuild/postbuild в Debug и Release. Они вызывают общий +`c/protocan-boot/projects/build.py`, проверяют Flash COFF через TI `ofd2000` и +автоматически копируют OUT/MAP, manifest, SHA-256 и метаданные в +`SETGUI/..periph_28335/firmware/periph28335/balzam167/canboot/28335/HASH_дата_UTC+3` +и `.../canboot/2812/HASH_дата_UTC+3` соответственно. +Команды, переопределение пути и структура результата описаны в +[инструкции CCS-проектов ProtoCAN Boot](../../c/protocan-boot/projects/README.md#prebuildpostbuild-и-копирование-в-setgui). + +| Назначение | Полный путь | +|---|---| +| Корень общей библиотеки templates | `K:\git_project\newProject\templates` | +| Сценарии CCS | `K:\git_project\newProject\templates\tools\firmware-build\ccs` | +| Сценарии Keil | `K:\git_project\newProject\templates\tools\firmware-build\keil` | +| Проект Бальзам-166 / TMS320F28335 | `K:\git_project\28335_periph\UKSSTMS320F28335` | +| Каталог сборок Бальзам-166 в SETGUI | `K:\git_project\newProject\SETGUI\..periph_28335\firmware\periph28335\balzam166` | + +Все команды ниже используют эту копию templates. При переносе библиотеки +замените её корень в командах и в include paths компилятора. +`${PROJECT_LOC}`, `${BuildDirectory}`, `${CG_TOOL_ROOT}` и +`${BuildArtifactFileBaseName}` раскрывает CCS; `$P` и `#H` раскрывает Keil. +Для ручного запуска замените макросы полными путями. + +В пути SETGUI `..periph_28335` — существующее имя папки с двумя точками +в начале. Переход к родителю записывается отдельным компонентом `..\`. + +## Текущий проект 28335_periph: вызов через firmware_build.bat + +Для проекта `K:\git_project\28335_periph\UKSSTMS320F28335` используйте +локальную обвязку. Она вызывает общие BAT из templates; общий генератор +увеличивает версию в проектном JSON. Перед публикацией обвязка дополнительно +проверяет встроенный паспорт SCI8 и предел EEPROM. + +В CCS → **Project Properties → Build → Steps** задайте для Debug и Release +следующие команды, каждую одной строкой. + +**Pre-build:** + +```bat +cmd /c call "${PROJECT_LOC}/firmware_build.bat" prepare --build-dir "${BuildDirectory}" +``` + +**Post-build:** + +```bat +cmd /c call "${PROJECT_LOC}/firmware_build.bat" build --compiler "${CG_TOOL_ROOT}" --build-dir "${BuildDirectory}" --artifact "${BuildArtifactFileBaseName}" +``` + +Настройки находятся в +`K:\git_project\28335_periph\UKSSTMS320F28335\firmware_identity.json`: + +| Поле | Рабочее значение и смысл | +|---|---| +| `templates` | `../../newProject/templates`; разрешается относительно папки JSON в `K:\git_project\newProject\templates`. Абсолютный эквивалент: `K:/git_project/newProject/templates`. | +| `copy_to` | `../Bin`; копирует проверенные BIN, manifest, SHA-256, HEX и карту в `K:\git_project\28335_periph\Bin`. | +| `increment_version` | `true`; каждый pre-build резервирует следующий номер в поле `version`. | +| `max_image_bytes` | `32508`; предельный размер SCI8 BIN в байтах для этой платы. | + +В JSON используйте `/` либо удваивайте обратные слеши. +`copy_to` принимает также абсолютный путь, например +`K:/git_project/newProject/SETGUI/..periph_28335/firmware/periph28335/balzam166`. +Эта настройка копирует отдельные файлы комплекта. Архивные папки остаются +в `${BuildDirectory}/firmware`. + +`firmware_build.bat build` принимает именованные параметры. Дописывание +каталога после `--artifact` вызывает `unrecognized arguments`; для этой +обвязки каталог копирования задаётся полем `copy_to`. + +Include paths компилятора для текущего проекта: + +| Запись в CCS | Реальный каталог для Debug | +|---|---| +| `${SRC_ROOT}/../newProject/templates/c/firmware-info/include` | `K:\git_project\newProject\templates\c\firmware-info\include` | +| `${SRC_ROOT}/../newProject/templates/c/set-protocol` | `K:\git_project\newProject\templates\c\set-protocol` | +| `${BuildDirectory}/generated` | `K:\git_project\28335_periph\UKSSTMS320F28335\Debug\generated` | + +`${SRC_ROOT}` в этом проекте равен `K:\git_project\28335_periph`. +При переносе templates обновите и JSON, и include paths в CCS. +Подробная инструкция проекта: +[README Бальзам-166](../../../../28335_periph/UKSSTMS320F28335/README.md). + +Готовый BIN ищите по строке `[firmware-build] Verified BIN: ...`. +Постоянный каталог Debug: +`K:\git_project\28335_periph\UKSSTMS320F28335\Debug\firmware`. +Папки `.identity-release-...` временные и удаляются после проверки. + +## Прямое подключение общих BAT к новому CCS-проекту + +Следующие разделы описывают прямые вызовы `ccs/precompile.bat` и +`ccs/postcompile.bat`. В этом варианте дополнительный последний аргумент +postcompile поддерживается и экспортирует целиком папку текущей сборки. +Общий генератор увеличивает версию прямо при вызове precompile, если в JSON задано `"increment_version": true`. Отсутствующий флаг или `false` сохраняет ручной режим. + +Итератор общий для CCS, Keil и CLI; проектная обёртка не должна увеличивать номер повторно. + +Каждый pre-build атомарно сохраняет следующий номер до генерации паспорта, включая попытки с последующей ошибкой. После patch 999 увеличивается minor, после minor 255 — major; младшие поля обнуляются. После 255.255.999 сборка останавливается. Clean не сбрасывает JSON; одновременные сборки с одним JSON не поддерживаются. +Выберите одну схему подключения: её pre-build и post-build должны +использовать один набор метаданных. + ## Новый CCS-проект C2000: локальные версия и SCI8 BIN Используйте обновлённую папку templates целиком. Режим `--identity` добавлен для нового проекта: Windows, Python 3.8+ в PATH и TI C2000 compiler с hex2000.exe. Git в PATH нужен для хеша коммита. Без Git либо без commit в проекте или templates используется `NOGIT000`; сборка и локальная конвертация разрешены. Это явно видно в manifest. SETGUI и доступ к серверу не требуются. ### 1. Создайте конфигурацию версии -При первом запуске pre-build автоматически копирует `ccs/firmware_identity.example.json` в путь конфигурации из команды (обычно `${PROJECT_LOC}/firmware_identity.json`, рядом с `.project`), если файла ещё нет. Существующий JSON никогда не перезаписывается. После первого запуска откройте его, задайте свои product, target и version и пересоберите проект. Первый запуск использует значения примера: +При первом запуске pre-build автоматически копирует `ccs/firmware_identity.example.json` в путь конфигурации из команды (обычно `${PROJECT_LOC}/firmware_identity.json`, рядом с `.project`), если файла ещё нет. Существующий JSON не заменяется примером; при включённом итераторе в нём обновляется версия. После первого запуска откройте его, задайте свои product, target и version и пересоберите проект. Исходные значения примера перед первым запуском: ```json { "product": "MY_CONTROLLER", "target": "TMS320F28335", - "version": [0, 1, 0] + "version": [0, 1, 0], + "increment_version": true } ``` -Задайте своё изделие, настоящий контроллер и нужную версию. Для TMS320F2812 замените target. Пример версии — 0.1.0; это не номер предыдущих прошивок. Этот JSON — единственное вручную редактируемое место версии в данной схеме. +Задайте своё изделие, настоящий контроллер и нужную версию. Для TMS320F2812 замените target. Начальный счётчик примера — 0.1.0; при включённом итераторе первый pre-build выдаёт 0.1.1. Этот JSON — единственное вручную редактируемое место версии в данной схеме. ### 2. Добавьте команды в CCS -Project Properties → Build → Steps, для нужной конфигурации. Пример предполагает templates в `C:\Projects\templates`. Замените только этот путь своим; макросы CCS оставьте как есть. +Project Properties → Build → Steps, для нужной конфигурации. Пример предполагает templates в `K:\git_project\newProject\templates`. Замените только этот путь своим; макросы CCS оставьте как есть. Pre-build steps → Command, одной строкой: ```bat -cmd /c call "C:\Projects\templates\tools\firmware-build\ccs\precompile.bat" --identity "${PROJECT_LOC}" "${PROJECT_LOC}\firmware_identity.json" "${BuildDirectory}\generated" +cmd /c call "K:\git_project\newProject\templates\tools\firmware-build\ccs\precompile.bat" --identity "${PROJECT_LOC}" "${PROJECT_LOC}\firmware_identity.json" "${BuildDirectory}\generated" ``` Post-build steps → Command, одной строкой: ```bat -cmd /c call "C:\Projects\templates\tools\firmware-build\ccs\postcompile.bat" --identity "${CG_TOOL_ROOT}" "${BuildDirectory}" "${BuildArtifactFileBaseName}" "${BuildDirectory}\generated\firmware_identity.json" "${BuildDirectory}\firmware" +cmd /c call "K:\git_project\newProject\templates\tools\firmware-build\ccs\postcompile.bat" --identity "${CG_TOOL_ROOT}" "${BuildDirectory}" "${BuildArtifactFileBaseName}" "${BuildDirectory}\generated\firmware_identity.json" "${BuildDirectory}\firmware" ``` +Позиционные аргументы общего `ccs/postcompile.bat` после `--identity`: + +| Позиция | Значение | Источник в CCS | +|---|---|---| +| 1 | Корень TI C2000 compiler, содержащий `bin/hex2000.exe` | `${CG_TOOL_ROOT}` | +| 2 | Каталог текущей конфигурации сборки | `${BuildDirectory}` | +| 3 | Имя или путь OUT без расширения `.out` | `${BuildArtifactFileBaseName}` | +| 4 | Метаданные, созданные pre-build | `${BuildDirectory}\generated\firmware_identity.json` | +| 5 | Постоянный каталог результатов | `${BuildDirectory}\firmware` | +| 6, необязательно | Каталог экспорта архивной папки текущей сборки | Полный путь назначения | + +Здесь templates определяется расположением вызываемого общего BAT. +Для прямой схемы поле `templates` в JSON не заменяет путь в команде CCS. +Добавьте `${BuildDirectory}/generated` в include paths; при подключении +общего порта firmware-info добавьте +`K:/git_project/newProject/templates/c/firmware-info/include`. + Нужны оба шага. Precompile создаёт версию, UTC-время и Git-метаданные до компиляции. Postcompile преобразует OUT в SCI8 HEX/BIN, создаёт manifest и SHA-256 для точного BIN. Он не повторяет запрос Git после компиляции. В этом режиме `firmware-release.cmd` не нужен. `BuildArtifactFileBaseName` передаётся без изменения и без расширения `.out`: допускается простое имя, абсолютный путь или путь относительно BuildDirectory. Postcompile находит OUT по этому пути, а для имён BIN/HEX использует только имя файла. Поэтому отдельная выходная папка проекта (например, `../bin`) не требует правки общей команды. Метаданные и результаты остаются в указанных каталогах generated и firmware. @@ -62,23 +222,23 @@ Debug/ firmware_identity.json ``` -Postcompile автоматически создаёт папку `HASH_YYYY-MM-DD_HH-MM-SS_UTC+3` для каждой сборки. HASH — первые 8 символов commit прошивки из pre-build JSON; при незакоммиченных изменениях добавляется `+`. Дата и время берутся из `built_at_utc` и переводятся в UTC+3 для имени папки. В JSON и заголовке сохраняется UTC. Если commit исходников неизвестен, используется build ID или NOGIT000. Например: `f5c3654e+_2026-10-08_15-30-00_UTC+3`. Сохраняются точные байты образа, manifest, SHA-256 и firmware_identity.json; в CCS также HEX и map. Повтор postcompile с теми же метаданными обновляет ту же папку. Файлы непосредственно в firmware сохраняются, поэтому существующие команды копирования продолжают работать. +Postcompile автоматически создаёт папку `HASH_YYYY-MM-DD_HH-MM-SS_UTC+3` для каждой сборки. HASH — первые 8 символов commit прошивки из pre-build JSON; при незакоммиченных изменениях добавляется `+`. Дата и время берутся из `built_at_utc` и переводятся в UTC+3 для имени папки. В JSON и заголовке сохраняется UTC. Если commit исходников неизвестен, используется build ID или NOGIT000. Например: `f5c3654e+_2026-10-08_15-30-00_UTC+3`. Сохраняются точные байты образа, manifest, SHA-256 и firmware_identity.json; в CCS также исходный OUT, HEX и map. Повтор postcompile с теми же метаданными обновляет ту же папку. Файлы непосредственно в firmware сохраняются, поэтому существующие команды копирования продолжают работать. Добавьте generated и firmware в игнорируемые Git-каталоги. Обычно вся папка Debug уже игнорируется. Полный Rebuild обязателен для выпуска. BAT сами по себе не подтверждают, что OUT собран именно с этим заголовком. -### 4. Копирование папки текущей сборки в SETGUI +### 4. Прямой postcompile: копирование папки текущей сборки в SETGUI -Передайте каталог назначения последним аргументом postcompile. Скрипт скопирует целиком только папку HASH_DATE, созданную текущим запуском: BIN, HEX, map, manifest, SHA-256 и метаданные. Он использует папку из pre-build JSON, не выбирает её по времени изменения файлов и не копирует остальные архивы или отдельные файлы из корня firmware. +При прямом вызове общего ccs/postcompile.bat передайте каталог назначения последним аргументом после output-dir. Это правило относится к общему BAT; проектный firmware_build.bat использует copy_to из JSON. Скрипт скопирует целиком только папку HASH_DATE, созданную текущим запуском: исходный OUT (для CCS), BIN, HEX, map, manifest, SHA-256 и метаданные. OUT сохраняется с исходным именем для выбора и загрузки через JTAG в GUI. Скрипт использует папку из pre-build JSON, не выбирает её по времени изменения файлов и не копирует остальные архивы или отдельные файлы из корня firmware. -Полная команда Post-build для templates в `K:\git_project\newProject\newTEMPL\templates`, одной строкой: +Полная команда Post-build для templates в `K:\git_project\newProject\templates`, одной строкой: ```bat -cmd /c call "K:\git_project\newProject\newTEMPL\templates\tools\firmware-build\ccs\postcompile.bat" --identity "${CG_TOOL_ROOT}" "${BuildDirectory}" "${BuildArtifactFileBaseName}" "${BuildDirectory}\generated\firmware_identity.json" "${BuildDirectory}\firmware" "K:\git_project\newProject\SETGUI\..periph_28335\firmware" +cmd /c call "K:\git_project\newProject\templates\tools\firmware-build\ccs\postcompile.bat" --identity "${CG_TOOL_ROOT}" "${BuildDirectory}" "${BuildArtifactFileBaseName}" "${BuildDirectory}\generated\firmware_identity.json" "${BuildDirectory}\firmware" "K:\git_project\newProject\SETGUI\..periph_28335\firmware\periph28335\balzam166" ``` Старые суффиксы `&& copy ...` и `&& xcopy ...` удалите. Папка назначения создаётся автоматически. В ней появится, например: ```text -K:\git_project\newProject\SETGUI\..periph_28335\firmware\ +K:\git_project\newProject\SETGUI\..periph_28335\firmware\periph28335\balzam166\ f5c3654e+_2026-10-08_15-30-00_UTC+3\ MyFirmware.hex MyFirmware_BUILDID.bin @@ -89,6 +249,33 @@ K:\git_project\newProject\SETGUI\..periph_28335\firmware\ Копирование выполняется после успешного архивирования; SHA-256 копии проверяется. Console покажет `[firmware-build] Exported folder: ...`. Повтор для той же папки обновляет её файлы; другие папки назначения сохраняются. Без последнего аргумента экспорт отключён. Это локальное копирование без сетевой публикации. +### Дополнительный Flash OUT из postbuild CCS + +Если рядом с CCS-проектом, на уровень выше BuildDirectory, есть `build_flash.py`, +общий postbuild автоматически вызывает его с `--postbuild`, `--compiler`, +`--build-dir` и `--output`. Команда postcompile в настройках CCS остаётся прежней. +Сценарий проекта должен использовать уже готовые объекты, не запускать Make +и создать непустые `<имя>_flash.out` и `<имя>_flash.map` по переданному пути. +Адреса секций, отдельный linker-файл и необходимые определения препроцессора +задаёт проектный сборщик, а не общий templates. + +Flash OUT и карта сохраняются рядом с обычным OUT. Копии, отдельный manifest +и SHA-256 попадают в firmware и ту же папку HASH_DATE, что и EEPROM BIN, +а затем копируются в GUI при настроенном export. Обычный BIN по-прежнему +создаётся из основного OUT; Flash OUT не преобразуется в EEPROM SCI8 BIN. +Ошибка сборщика или отсутствие любого результата завершает postcompile +с ненулевым кодом до архивирования и экспорта. Существующий Flash OUT +не считается результатом нового вызова: сборщик работает во временном каталоге. +Без `build_flash.py` дополнительные действия отключены. + +Дополнительно hex2000 преобразует Flash OUT в отдельный `<имя>_flash_rs.bin` +с адресной таблицей SCI8, картой `.bin.map`, manifest и SHA-256. +Эти файлы сохраняются рядом с OUT, в firmware и в экспортируемой папке +HASH_DATE. Flash RS BIN содержит адреса внутренней Flash и предназначен +для совместимого проектного CMD_TFLASH; его нельзя выбирать как обычный +EEPROM BIN. Проект сам должен реализовать проверку адресов и алгоритм +программирования из RAM. Общий postbuild только формирует транспортный файл. + ### Версия внутри устройства Это подготовка метаданных сборки и файла. Чтобы версия присутствовала в программе и ответах устройства, подключите заголовок `firmware_identity.h` к модулю версии и обработчику запроса. Include path: `${BuildDirectory}/generated`. Для C2000 с 16-битным char нужна адаптация байтового контракта; обычный 8-битный порт нельзя считать готовым. Смотрите [PORTING.md](../../c/firmware-info/PORTING.md). @@ -115,30 +302,31 @@ project/ { "product": "MY_CONTROLLER", "target": "STM32F407", - "version": [0, 1, 0] + "version": [0, 1, 0], + "increment_version": true } ``` ### 2. Настройте Before/After Build -В Options for Target → Output включите Create HEX File. Затем откройте User и включите выполнение команд Before Build/Rebuild и After Build/Rebuild. Для обеих команд задайте Stop on Exit Code `>=1`, чтобы ошибка скрипта останавливала сборку. Пример предполагает templates в `C:\Projects\templates`; замените этот путь своим. +В Options for Target → Output включите Create HEX File. Затем откройте User и включите выполнение команд Before Build/Rebuild и After Build/Rebuild. Для обеих команд задайте Stop on Exit Code `>=1`, чтобы ошибка скрипта останавливала сборку. Пример предполагает templates в `K:\git_project\newProject\templates`; замените этот путь своим. Before Build/Rebuild, одной строкой: ```bat -cmd /c call "C:\Projects\templates\tools\firmware-build\keil\precompile.bat" --identity "$P.." "$P..\firmware_identity.json" "$PGenerated" +cmd /c call "K:\git_project\newProject\templates\tools\firmware-build\keil\precompile.bat" --identity "$P.." "$P..\firmware_identity.json" "$PGenerated" ``` After Build/Rebuild, одной строкой: ```bat -cmd /c call "C:\Projects\templates\tools\firmware-build\keil\postcompile.bat" --identity "#H" "$PGenerated\firmware_identity.json" +cmd /c call "K:\git_project\newProject\templates\tools\firmware-build\keil\postcompile.bat" --identity "#H" "$PGenerated\firmware_identity.json" ``` Для копирования только папки текущей сборки добавьте каталог назначения последним аргументом: ```bat -cmd /c call "C:\Projects\templates\tools\firmware-build\keil\postcompile.bat" --identity "#H" "$PGenerated\firmware_identity.json" "K:\git_project\newProject\SETGUI\..periph_28335\firmware" +cmd /c call "K:\git_project\newProject\templates\tools\firmware-build\keil\postcompile.bat" --identity "#H" "$PGenerated\firmware_identity.json" "K:\git_project\newProject\SETGUI\..periph_28335\firmware\periph28335\balzam166" ``` Будет скопирована целиком новая папка HASH_DATE с HEX/BIN, manifest, SHA-256 и метаданными. Старые команды copy/xcopy в этой строке не нужны. В Console появится `[firmware-build] Exported folder`. @@ -169,3 +357,53 @@ firmware/ ## Совместимость со старыми проектами Вызовы BAT без `--identity` сохранены для уже настроенных проектов: прежний precompile генерирует только build ID, прежний postcompile запускает SETGUI preflight по release-конфигурации. Эта отдельная схема описана в [инструкции публикатора](../firmware-publish/README.md). Для новых CCS и Keil используйте приведённые выше команды с `--identity`. + +## Автоматический CAN BIN вместе с Flash + +Защищённый `c/firmware-info/tools/c2000_build.py build`, вызываемый из CCS +postbuild и `postcompile.bat --identity`, дополнительно создаёт CAN-вариант, +если проект явно задаёт `can_boot_profile` равным `f28335-m95m02-ab` +в `firmware_build_profile.json` и выбрана EEPROM M95M02. +Для AT25256B этот A/B-профиль отключён. Старые проекты без поля сохраняют +прежний состав выпуска. Изменение CAN-профиля требует нового prebuild и сборки. + +В одном выпуске сохраняются: + +| Файл | Назначение | +|---|---| +| `eeprom/_.bin` | Основной SCI8 RAM/EEPROM-образ | +| `can/__can.bin` | ProtoCAN Boot, M95M02 A/B, RAM-приложение | +| `flash/_flash.out` | Внутренняя Flash через JTAG, если проект имеет build_flash.py | +| `rs/_flash_rs.bin` | Обновление внутренней Flash по RS из того же Flash OUT | + +CAN BIN содержит точные байты проверенного RAM SCI8. Отдельно проверяются +предел 130560 октетов, максимум 64 секции, адреса RAM `[0x8000,0xE000)`, +entry, встроенный паспорт и экспортированные CAN hooks Init/Ready/Service/RxISR +в загружаемом payload. Flash-таблица не допускается как CAN BIN. +Каждый вариант получает собственные manifest и SHA-256. CAN-файл и оба +sidecar добавляются в тот же архив сборки и проходят штатный экспорт в GUI. +При отказе проверки CAN или обязательного Flash-варианта новая попытка +не копируется в постоянный output/export. Сетевая публикация и запись платы +этой командой не выполняются. + +Защищённый C2000 postbuild располагает образы, их manifest, SHA-256 и карты +в папках `eeprom`, `flash`, `can`, `rs` как непосредственно в `--output`, так +и внутри архива `HASH_дата_UTC+3`. При `--export` весь архив переносится +в SETGUI с той же структурой. Общий `firmware_identity.json` остаётся +в корне архива; `latest_build.json` указывает manifest с относительным +путём `eeprom/_.bin.manifest.json`. Папка +неподдержанного варианта не создаётся. Низкоуровневые конверторы и другие +семейства MCU сохраняют прежний контракт своих результатов. + +Для `target: "TMS320F2812"` основной SCI8-комплект сохраняется в `flash`, +поскольку проект 166 записывает его во внешнюю параллельную Flash. +Туда же попадают сопроводительные OUT, HEX, карты, manifest и SHA-256; +`latest_build.json` указывает `flash/_.bin.manifest.json`. +Это правило действует в локальном выпуске, архиве и `--export`. +Для остальных процессоров основной комплект остаётся в `eeprom`. + +В SETGUI можно импортировать корень одной сборки или выбрать её папку +`eeprom`, `can`, `rs`. Основной BIN определяется выбранным паспортом, +а ZIP сохраняет все назначения этой компиляции. Для JTAG выберите +совместимый загрузчик полного комплекта: он возьмёт подписанный OUT +из `flash`. Старые плоские комплекты также поддерживаются. diff --git a/tools/firmware-build/ccs/firmware_identity.example.json b/tools/firmware-build/ccs/firmware_identity.example.json index acef913..1faef6a 100644 --- a/tools/firmware-build/ccs/firmware_identity.example.json +++ b/tools/firmware-build/ccs/firmware_identity.example.json @@ -1,5 +1,6 @@ { "product": "MY_CONTROLLER", "target": "TMS320F28335", - "version": [0, 1, 0] + "version": [0, 1, 0], + "increment_version": true } diff --git a/tools/firmware-build/ccs/postcompile.bat b/tools/firmware-build/ccs/postcompile.bat index 04265f1..14c730c 100644 --- a/tools/firmware-build/ccs/postcompile.bat +++ b/tools/firmware-build/ccs/postcompile.bat @@ -18,10 +18,12 @@ if "%~5"=="" goto usage if "%~6"=="" goto usage if not "%~8"=="" goto usage if "%~7"=="" goto identity_local -python "%~dp0..\..\..\c\firmware-info\tools\c2000_postbuild.py" --compiler "%~f2" --build-dir "%~f3" --artifact "%~4" --metadata "%~f5" --output "%~f6" --export "%~f7" +rem Общая подготовка и проверка выполняются в templates; сетевую публикацию выполняет Публикатор SETGUI. +python "%~dp0..\..\..\c\firmware-info\tools\c2000_build.py" build --compiler "%~f2" --build-dir "%~f3" --artifact "%~4" --metadata "%~f5" --output "%~f6" --export "%~f7" exit /b %errorlevel% :identity_local -python "%~dp0..\..\..\c\firmware-info\tools\c2000_postbuild.py" --compiler "%~f2" --build-dir "%~f3" --artifact "%~4" --metadata "%~f5" --output "%~f6" +rem Общая подготовка и проверка выполняются в templates; сетевую публикацию выполняет Публикатор SETGUI. +python "%~dp0..\..\..\c\firmware-info\tools\c2000_build.py" build --compiler "%~f2" --build-dir "%~f3" --artifact "%~4" --metadata "%~f5" --output "%~f6" exit /b %errorlevel% :usage echo Usage: postcompile.bat --identity "compiler-root" "build-dir" "artifact-name" "generated-metadata.json" "output-dir" ["export-dir"] 1>&2 diff --git a/tools/firmware-build/ccs/precompile.bat b/tools/firmware-build/ccs/precompile.bat index 163f2b2..b45ea9a 100644 --- a/tools/firmware-build/ccs/precompile.bat +++ b/tools/firmware-build/ccs/precompile.bat @@ -23,7 +23,8 @@ if not exist "%~f3" ( echo [firmware-build] Created configuration: "%~f3" echo [firmware-build] Edit product, target and version in this file, then rebuild. ) -python "%~dp0..\..\..\c\firmware-info\tools\identity.py" prepare --repository "%~f2" --templates "%~dp0..\..\.." --config "%~f3" --output "%~f4" +rem Общая подготовка и проверка выполняются в templates; сетевую публикацию выполняет Публикатор SETGUI. +python "%~dp0..\..\..\c\firmware-info\tools\c2000_build.py" prepare --project "%~f2" --templates "%~dp0..\..\.." --config "%~f3" --output "%~f4" exit /b %errorlevel% :usage echo Usage: precompile.bat --identity "project-root" "firmware_identity.json" "generated-dir" 1>&2 diff --git a/tools/firmware-build/fpga/.gitattributes b/tools/firmware-build/fpga/.gitattributes new file mode 100644 index 0000000..22f70a5 --- /dev/null +++ b/tools/firmware-build/fpga/.gitattributes @@ -0,0 +1,2 @@ +# CMD требует CRLF для надёжного чтения BAT с русскими комментариями в UTF-8. +*.bat text eol=crlf diff --git a/tools/firmware-build/fpga/INSTALL_ISE.bat b/tools/firmware-build/fpga/INSTALL_ISE.bat new file mode 100644 index 0000000..0186b94 --- /dev/null +++ b/tools/firmware-build/fpga/INSTALL_ISE.bat @@ -0,0 +1,29 @@ +@chcp 65001 >nul +@rem Переключение на UTF-8 нужно для русских комментариев и путей; установщик создаёт локальные файлы ISE. +@echo off +rem Сохраняет окружение и не раскрывает восклицательные знаки в путях проекта. +setlocal EnableExtensions DisableDelayedExpansion +rem Предпочитает штатный Windows launcher Python 3, если он установлен. +where py >nul 2>nul +rem При отсутствии launcher использует Python из PATH. +if errorlevel 1 goto use_python +rem Передаёт путь проекта или дополнительные параметры без изменения их порядка. +py -3 "%~dp0ise_project.py" install %* +rem Запоминает код установки до вывода подсказок и ожидания клавиши. +set "FW_EXIT=%errorlevel%" +rem Не запускает установку повторно через другой интерпретатор. +goto done +rem Начинает вариант для компьютеров без Windows launcher. +:use_python +rem При двойном щелчке Python запросит путь к проекту интерактивно. +python "%~dp0ise_project.py" install %* +rem Сохраняет исходный результат установщика. +set "FW_EXIT=%errorlevel%" +rem Завершает оба варианта запуска одинаково. +:done +rem Автоматические вызовы могут отключить ожидание переменной окружения. +if defined FW_NO_PAUSE exit /b %FW_EXIT% +rem Оставляет результат видимым при запуске двойным щелчком или перетаскиванием .xise. +pause +rem Передаёт вызывающей программе результат установки, а не команды pause. +exit /b %FW_EXIT% diff --git a/tools/firmware-build/fpga/ISE_PORTING.md b/tools/firmware-build/fpga/ISE_PORTING.md new file mode 100644 index 0000000..b40604d --- /dev/null +++ b/tools/firmware-build/fpga/ISE_PORTING.md @@ -0,0 +1,42 @@ +# Простое подключение контроля прошивки к ISE + +1. Запустите **`INSTALL_ISE.bat` из этого каталога** и вставьте путь к вашему + `.xise`. Можно просто перетащить `.xise` на этот BAT. +2. Установщик сам прочитает кристалл, язык, имя `.bit` и рабочий каталог + из проекта, скопирует локальные команды и создаст настройки. +3. Один раз подключите паспорт к шине проекта по созданному файлу + `firmware_identity_instance.txt`: адрес слова — `word_addr[3:0]`, + данные — `word_data[15:0]`. Без использования выхода паспорт удалит синтезатор. +4. Для сборки запускайте **`build_firmware.bat` рядом с `.xise`**. + Для проверки настройки без сборки — `build_firmware.bat --check`. + +Автоматически создаются: + +| Файл | Назначение | +|---|---| +| `build_firmware.bat`, `firmware_build.py` | Локальная команда сборки | +| `firmware_build.json` | Найденные пути проекта, библиотеки templates, `.bit` и окружения ISE | +| `firmware_identity.json` | Изделие, кристалл и сохраняемый счётчик версии | +| `firmware_identity_instance.txt` | Заготовка подключения для Verilog или VHDL | +| `FIRMWARE_SETUP.md` | Памятка внутри проекта | +| `build/ise/generated/` | Предварительно созданный HDL-паспорт; обновляется перед каждой сборкой | + +Нужен Python 3.9+ через `py -3` или `python`. Окружение ISE ищется в PATH +и стандартных каталогах Xilinx. Для нестандартной установки один раз задайте +`ise_settings` в `firmware_build.json` — полный путь к `settings64.bat` +или `settings32.bat`. + +Общие инструменты используются из вашей библиотеки templates; вручную +копировать её внутрь проекта не требуется. Если библиотека переехала, +исправьте поле `templates` в `firmware_build.json`. + +Первая сборка получает **0.1.1**. Установка и `--check` номер не расходуют; +неудачная попытка синтеза расходует. Повторная установка сохраняет существующие +JSON и версию; чужие BAT с тем же именем не перезаписывает. + +Готовый `.bit`, manifest, SHA-256, HDL и метаданные сохраняются в +`build/ise/firmware/HASH_ДАТА_ВРЕМЯ_UTC+3/`. После загрузки на плату сравните +12 слов паспорта с `fpga.register_words` в manifest. + +Установщик предназначен для FPGA-проектов с результатом `.bit`; CPLD с `.jed` +требует отдельного шаблона. [Подробности паспорта и прямая Tcl-сборка](README.md). diff --git a/tools/firmware-build/fpga/README.md b/tools/firmware-build/fpga/README.md new file mode 100644 index 0000000..2a1a542 --- /dev/null +++ b/tools/firmware-build/fpga/README.md @@ -0,0 +1,241 @@ +# Контроль прошивок ПЛИС: Xilinx ISE, Vivado и Altera Quartus + +Для ISE: запустите `INSTALL_ISE.bat`, укажите `.xise`, затем используйте +созданный в проекте `build_firmware.bat`. [Краткая инструкция](ISE_PORTING.md). + +Шаблон подключает к существующему проекту ПЛИС общий механизм +[`firmware-info`](../../../c/firmware-info/README.md): сохраняемый итератор +SemVer, время сборки в UTC, Git build ID, manifest, SHA-256 и архив выпуска. +Параметры кристалла, выводы, частоты, ограничения и транспорт чтения регистров +задаёт проект платы. + +Цепочка: проект → Tcl своей САПР → `identity.py` из этого каталога → общий +`c/firmware-info/tools/identity.py`. Итератор, правила Git и архивирования +используются те же, что для CCS и Keil. + +## Файлы и зависимости + +| Файл | Назначение | Зависимости | +|---|---|---| +| `firmware_identity.example.json` | Начальная конфигурация изделия и счётчика | Копируется в проект | +| `INSTALL_ISE.bat`, `ise_project.py` | Автоматическая установка локальных BAT, JSON, HDL и памятки из `.xise` | Windows, Python 3.9+ | +| `ise-build.bat`, `ise_bootstrap.py`, `ise-project.md` | Шаблоны локальной команды сборки и памятки | Копируются установщиком в проект | +| `identity.py` | Генерация Verilog-2001/VHDL-93 и контроль готового файла | Python 3.9+, stdlib, общий `identity.py` из templates | +| `common.tcl` | Пути, язык, вызовы Python, обработка отказов | Tcl 8.5+ в САПР | +| `ise.tcl` | Полная сборка `.xise` до `.bit` | Xilinx ISE / `xtclsh` | +| `vivado.tcl` | Полная сборка `.xpr` до `.bit` | Vivado Project Mode | +| `quartus.tcl` | Полная сборка `.qpf` до `.sof` | Altera/Intel Quartus II или Prime / `quartus_sh` | + +Python 3 должен быть доступен как `python` из окружения САПР. Если ISE или +Quartus подставляет старый Python, передайте путь к `python.exe` шестым +аргументом. Git в PATH нужен для хешей; при недоступном Git получается +явный `NOGIT000`, локальная сборка продолжается. + +## 1. Конфигурация проекта + +Скопируйте `firmware_identity.example.json` рядом с `.xise`, `.xpr` или `.qpf` +под именем `firmware_identity.json`. Пример намеренно требует заменить имя +кристалла; задайте своё изделие и точный part number. + +| Поле | Смысл | +|---|---| +| `product` | Имя изделия, например `MY_FPGA_BOARD` | +| `target` | Точное обозначение кристалла; информационное поле, настройки part в проекте не меняет | +| `version` | Последний занятый номер `[major, minor, patch]`; в примере `[0, 1, 0]` | +| `increment_version` | `true` включает общий сохраняемый итератор; `false` оставляет ручную версию | + +Первая подготовка примера выдаёт **0.1.1**. Следующий pre-build выдаёт 0.1.2, +включая попытки после ошибки синтеза. Переносы: 0.1.999 → 0.2.0, +0.255.999 → 1.0.0. После 255.255.999 сборка останавливается. Post-build номер +не увеличивает. Clean не сбрасывает конфигурацию. + +Храните этот JSON в Git. Каталог `build/` добавьте в `.gitignore` проекта; +файлы результатов САПР также должны игнорироваться, иначе они пометят сборку +как dirty. Одна конфигурация JSON обслуживает только одну сборку одновременно. +Для независимых ревизий платы используйте отдельные JSON и выходные каталоги. + +## 2. Подключение паспорта к логике + +Генератор создаёт `generated/firmware_identity.v` и +`generated/firmware_identity.vhd`. Tcl добавляет в проект только выбранный +язык. Паспорт — комбинационный ROM из 12 слов по 16 бит: + +| Относительный адрес слова | Значение | +|---|---| +| 0 | Версия контракта: 1 | +| 1, 2, 3 | Major, minor, patch | +| 4 | Год, 2000..2199 | +| 5 | Месяц в битах 15..8, день в 7..0 | +| 6 | Час UTC в битах 15..8, минута в 7..0 | +| 7 | Секунда UTC | +| 8..11 | Восемь ASCII-символов build ID, первый символ пары в старшем октете | +| 12..15 | Ноль | + +Адреса относительные, без привязки к CPU, AXI, Avalon, SPI, Modbus или SETCAN. +Базовый адрес в системе назначает проект. Это тот же порядок слов, что в +`firmware_info_to_registers()`. Порядок байтов на конкретной шине задаёт +адаптер проекта. + +В верхний модуль Verilog добавьте экземпляр: + +```verilog +wire [15:0] identity_data; // 16-битное слово паспорта для мультиплексора чтения шины проекта. +firmware_identity u_identity ( // Экземпляр генерируемого до синтеза паспорта текущей сборки. + .word_addr(identity_word_offset), // Четыре младших бита относительного адреса слова в выделенном окне регистров. + .word_data(identity_data) // Выход должен участвовать в ответе шины, чтобы синтезатор сохранил паспорт. +); // Выбор окна и тактовое согласование выполняет логика проекта. +``` + +Для VHDL объявите component в declarative part архитектуры и подключите его +в теле архитектуры; component не требует заранее анализировать generated entity: + +```vhdl +component firmware_identity is -- Объявление размещается до begin архитектуры верхнего уровня. + port ( -- Интерфейс совпадает с генерируемой entity firmware_identity. + word_addr : in std_logic_vector(3 downto 0); -- Относительный адрес одного из 12 слов паспорта. + word_data : out std_logic_vector(15 downto 0) -- Данные для ответа шины проекта. + ); -- Закрывает список портов компонента. +end component; -- Привязка к entity из work выполняется при elaboration. +signal identity_data : std_logic_vector(15 downto 0); -- Объявляется до begin и подключается к чтению регистров. +-- Следующий экземпляр размещается после begin архитектуры верхнего уровня. +u_identity : firmware_identity -- Создаёт экземпляр паспорта без примитивов производителя. + port map ( -- Согласует имена сигналов проекта с интерфейсом компонента. + word_addr => identity_word_offset, -- Четырёхбитный сигнал относительного адреса слова задаёт проект. + word_data => identity_data -- Выход включается в мультиплексор ответа хосту. + ); -- Завершает подключение экземпляра. +``` + +`identity_word_offset`, декодер окна и ответ шины реализуйте в проекте. +Паспорт не имеет clock/reset, чтение комбинационное; при необходимости +зарегистрируйте ответ в тактовом домене шины. Без подключения выхода синтезатор +удалит паспорт. Смена языка существующего проекта требует удалить прежний +generated-файл из списка исходников, чтобы не получить два одноимённых модуля. + +## 3. Полная сборка + +Команды запускаются **из корня проекта** в командной строке с настроенным +окружением соответствующей САПР. В примерах templates подключён как +`lib/templates`. Проект должен уже содержать свой top, part и UCF/XDC/QSF. +Сценарии регистрируют generated-исходник в существующем проекте и выполняют +полную цепочку до файла программирования. + +Аргументы общие: `project config output image verilog|vhdl [python]`. +Пути разрешаются относительно начального рабочего каталога. `image` — точный +путь результата вашей САПР, а `output` — отдельный каталог паспорта и архивов; +передача `output` не меняет настройки выходного каталога САПР. + +**ISE:** + +```bat +rem Собирает существующий ISE-проект, в котором BitGen создаёт top.bit рядом с .xise. +xtclsh "lib/templates/tools/firmware-build/fpga/ise.tcl" "board.xise" "firmware_identity.json" "build/ise" "top.bit" verilog +``` + +Используется `Generate Programming File -force rerun_all`: XST, реализация +и BitGen выполняются заново. Логический `false` от процесса считается ошибкой. + +**Vivado:** + +```bat +rem Замените board.runs/impl_1/top.bit реальным путём .bit выбранного implementation run. +vivado -mode batch -source "lib/templates/tools/firmware-build/fpga/vivado.tcl" -tclargs "board.xpr" "firmware_identity.json" "build/vivado" "board.runs/impl_1/top.bit" verilog +``` + +Берётся активный implementation run и его родительский synthesis run; +нестандартные имена runs поддерживаются. Оба запуска сбрасываются, затем +выполняются синтез и реализация до `write_bitstream`. После `wait_on_run` +отдельно проверяется `PROGRESS`, поэтому завершение с ошибкой не вызывает упаковку. + +**Altera / Intel Quartus:** + +```bat +rem Собирает текущую revision из .qpf; image должен совпадать с результатом Assembler. +quartus_sh -t "lib/templates/tools/firmware-build/fpga/quartus.tcl" "board.qpf" "firmware_identity.json" "build/quartus" "output_files/board.sof" vhdl +``` + +`execute_flow -compile` запускает полную компиляцию с Assembler. +Для другой revision передайте седьмой аргумент после пути к Python: + +```bat +rem Укажите реальный Python 3 и отдельный JSON счётчика ревизии B. +quartus_sh -t "lib/templates/tools/firmware-build/fpga/quartus.tcl" "board.qpf" "identity_B.json" "build/quartus_B" "output_files/board_B.sof" vhdl "C:/Python313/python.exe" "board_B" +``` + +Не добавляйте второе увеличение версии в существующие pre-flow/pre-synthesis hooks. +Эти Tcl-файлы предназначены для запуска полной сборки из командной строки; +их нельзя подключать как вложенные hooks этапов синтеза. Для выпуска через +данную схему запускайте указанный сценарий, в том числе после работы в GUI. + +## 4. Результаты и проверка + +```text +build/vivado/ + generated/ + firmware_identity.h + firmware_identity.v + firmware_identity.vhd + firmware_identity.json + firmware/ + HASH_YYYY-MM-DD_HH-MM-SS_UTC+3/ + top.bit + top.bit.manifest.json + top.bit.sha256 + firmware_identity.v + firmware_identity.json +``` + +Для VHDL архив содержит выбранный `.vhd`, для Quartus — `.sof` вместо `.bit`. +Manifest и `.sha256` также создаются рядом с исходным файлом программирования. +Хеш и дата архивной папки берутся из pre-build, дата имени переводится в UTC+3; +в самом паспорте остаётся UTC. Знак `+` у build ID означает изменённые исходники +или templates. `firmware_identity.h` — сопутствующий результат общего генератора; +FPGA-сценарии используют HDL. + +Упаковка отклоняет отсутствующий, пустой или не обновившийся после prepare +файл. Проверяется содержимое и время записи: повторная запись тех же байтов +допускается. Это защита от старого результата; она не проверяет наличие паспорта +внутри vendor bitstream. Правильность подключения подтверждается чтением всех +12 регистров с работающей ПЛИС и сравнением с `fpga.register_words` в manifest. +SHA-256 относится к файлу программатора целиком и хранится снаружи образа. + +Проверить сохранённый файл можно общим инструментом: + +```bat +rem Проверяет размер и SHA-256 указанного файла по созданному рядом manifest. +python "lib/templates/c/firmware-info/tools/identity.py" verify --image "board.runs/impl_1/top.bit" --manifest "board.runs/impl_1/top.bit.manifest.json" +``` + +Для локального экспорта папки выпуска повторите только finish с `--export`; +номер версии при этом не меняется: + +```bat +rem Копирует текущую архивную папку и проверяет SHA-256 экспортной копии. +python "lib/templates/tools/firmware-build/fpga/identity.py" finish --metadata "build/vivado/generated/firmware_identity.json" --output "build/vivado/firmware" --export "D:/Firmware/FPGA" +``` + +Шаблон выпускает `.bit` и `.sof`. Преобразование в `.mcs`, `.bin`, `.pof` или +`.rbf`, загрузка на плату и публикация в сетевую базу требуют отдельного +проектного этапа. Контрольная сумма нативного образа не переносится на +преобразованный файл: для него создайте отдельные seal/verify общим инструментом. + +## Проверки и состояние + +Хостовые тесты проверяют эталон всех 12 слов, совпадение Verilog/VHDL, +итератор, свежесть результата, повреждение SHA-256, архив и экспорт. Реальные +Tcl-сценарии исполняются в Tcl из Python tkinter с заменой API производителей; +Python-генератор и упаковка выполняются полностью. Нужен Python с tkinter/Tcl, +графическое окно не открывается. + +```bat +rem Запускает проверки адаптера и управляющих сценариев без лицензии САПР. +python -m unittest discover -s tools/firmware-build/fpga/tests -v +``` + +Шаблон пока не подключён к конкретной плате. Полный синтез и чтение паспорта +на железе требуют установленной САПР, проекта и платы; хостовые тесты эти +проверки не заменяют. + +Команды сверены с руководствами производителей: +[ISE Command Line Tools UG628](https://docs.amd.com/v/u/en-US/devref), +[Vivado: запуск синтеза и реализации UG939](https://docs.amd.com/r/2023.1-English/ug939-vivado-designing-with-ip-tutorial/Step-8-Launch-Synthesis-and-Implementation), +[Quartus: полный Tcl flow](https://www.intel.com/content/www/us/en/docs/programmable/683432/22-1/the-tcl-shell-in-interactive-mode-example.html). diff --git a/tools/firmware-build/fpga/common.tcl b/tools/firmware-build/fpga/common.tcl new file mode 100644 index 0000000..d72e948 --- /dev/null +++ b/tools/firmware-build/fpga/common.tcl @@ -0,0 +1,76 @@ +# Общие процедуры совместимы с Tcl 8.5 старых ISE; пути передаются списками без eval. +namespace eval fw { + # Определяет Python-инструмент относительно поставки, а не текущего каталога САПР. + variable helper [file normalize [file join [file dirname [info script]] identity.py]] +# Закрывает пространство имён, не меняя глобальные команды САПР. +} +# Проверяет общие аргументы до открытия проекта и резервирования версии. +proc fw::init {arguments toolchain} { + # Объявляет настройки сценария в общем пространстве имён. + variable settings + # Пять обязательных аргументов и необязательный путь к python.exe. + if {[llength $arguments] < 5 || [llength $arguments] > 6} { + # Неверная команда не должна расходовать номер версии. + error "Usage: project config output image verilog|vhdl ?python?" + # Завершает проверку количества аргументов. + } + # Имена полей определяют одинаковый порядок аргументов всех трёх сценариев. + foreach name {project config output image} value [lrange $arguments 0 3] { + # Нормализует пути до перехода в каталог проекта. + set settings($name) [file normalize $value] + # Заканчивает обработку четырёх путей. + } + # Сохраняет выбранный HDL, чтобы в проект не попали две реализации одного модуля. + set settings(language) [lindex $arguments 4] + # Принимает только языки, поддержанные генератором паспорта. + if {[lsearch -exact {verilog vhdl} $settings(language)] < 0} { + # Останавливает сборку при опечатке в языке. + error "Expected verilog or vhdl" + # Заканчивает проверку выбранного языка. + } + # По умолчанию использует Python 3 из PATH, без аргументов командной оболочки. + set settings(python) python + # Полный путь позволяет обойти Python старой версии, встроенный в САПР. + if {[llength $arguments] == 6} { + # Делает путь python.exe абсолютным без раскрытия Windows junction до последующего cd. + set settings(python) [file join [pwd] [lindex $arguments 5]] + # Завершает выбор интерпретатора. + } + # Передаёт генератору имя формата нативного результата. + set settings(toolchain) $toolchain + # Разделяет генерируемые исходники и архивы внутри каталога конфигурации. + set settings(generated) [file join $settings(output) generated] + # Выбирает расширение только одного подключаемого HDL-файла. + set extension [expr {$settings(language) eq "verilog" ? "v" : "vhd"}] + # Имя модуля совпадает в Verilog и VHDL и известно верхнему уровню проекта. + set settings(hdl) [file join $settings(generated) firmware_identity.$extension] + # Проверяет наличие проектного файла до запуска САПР. + if {![file isfile $settings(project)] || ![file isfile $settings(config)]} { + # JSON создаётся пользователем из примера, чтобы не выпустить изделие с чужим именем. + error "Project or firmware identity config does not exist" + # Завершает проверку обязательных файлов. + } + # Зависимые исходники и ограничения проекта разрешаются относительно его каталога. + cd [file dirname $settings(project)] +# Заканчивает инициализацию путей и языка. +} +# Резервирует версию один раз до любых шагов синтеза. +proc fw::prepare {} { + # Получает проверенные аргументы текущего запуска. + variable settings + # Получает абсолютный путь общего генератора. + variable helper + # exec передаёт каждый путь отдельно; stderr остаётся в журнале САПР, ненулевой код вызывает Tcl error. + puts [exec $settings(python) $helper prepare --repository [file dirname $settings(project)] --config $settings(config) --output $settings(generated) --image $settings(image) --toolchain $settings(toolchain) --language $settings(language) 2>@stderr] +# Завершает подготовку паспорта. +} +# Упаковывает результат только после успешного возврата полного flow. +proc fw::finish {} { + # Использует те же пути, что и pre-build данного запуска. + variable settings + # Выбирает тот же Python-инструмент, который создавал паспорт. + variable helper + # Генератор проверяет обновление файла, SHA-256 и архивную копию; ошибка блокирует успешное завершение Tcl. + puts [exec $settings(python) $helper finish --metadata [file join $settings(generated) firmware_identity.json] --output [file join $settings(output) firmware] 2>@stderr] +# Завершает контроль готового образа. +} diff --git a/tools/firmware-build/fpga/firmware_identity.example.json b/tools/firmware-build/fpga/firmware_identity.example.json new file mode 100644 index 0000000..d483e0e --- /dev/null +++ b/tools/firmware-build/fpga/firmware_identity.example.json @@ -0,0 +1,6 @@ +{ + "product": "MY_FPGA_BOARD", + "target": "REPLACE_WITH_EXACT_FPGA_PART", + "version": [0, 1, 0], + "increment_version": true +} diff --git a/tools/firmware-build/fpga/identity.py b/tools/firmware-build/fpga/identity.py new file mode 100644 index 0000000..d1f7e8b --- /dev/null +++ b/tools/firmware-build/fpga/identity.py @@ -0,0 +1,92 @@ +"""Паспорт ПЛИС и контроль готового образа через общий итератор firmware-info.""" # CLI используется из Tcl трёх систем сборки. +from __future__ import annotations # Откладывает вычисление аннотаций для Python 3.9+. +import argparse # Разбирает явные пути, чтобы рабочий каталог IDE не менял назначение файлов. +from datetime import datetime # Разбирает UTC-время, зафиксированное общим pre-build. +import hashlib # Сравнивает исходный и новый образы при защите от устаревшего результата. +import importlib.util # Подключает существующий генератор без второй реализации итератора. +import json # Читает и сохраняет переносимые метаданные сборки в UTF-8. +from pathlib import Path # Нормализует пути проектов, результатов и общей библиотеки. +TEMPLATES = Path(__file__).resolve().parents[3] # От fpga/ поднимается к корню templates. +SPEC = importlib.util.spec_from_file_location("firmware_identity_shared", TEMPLATES / "c/firmware-info/tools/identity.py") # Выбирает общий модуль из этой же поставки. +shared = importlib.util.module_from_spec(SPEC) # Создаёт пространство имён общего генератора без изменения sys.path. +SPEC.loader.exec_module(shared) # Загружает prepare, seal, verify и archive_build без запуска общего CLI. +FORMATS = {"ise": {".bit"}, "vivado": {".bit"}, "quartus": {".sof"}} # Полные сценарии выпускают нативный файл конфигурации своей САПР. + + +def registers(metadata): # Переносит публичный 12-словный контракт firmware-info v1 в константную HDL-память. + stamp = datetime.fromisoformat(metadata["built_at_utc"]) # Общий prepare всегда сохраняет дату с часовым поясом UTC. + words = [1, *metadata["version"], stamp.year, (stamp.month << 8) | stamp.day, (stamp.hour << 8) | stamp.minute, stamp.second] # Слова 0..7: контракт, SemVer и календарные поля; сдвиг на 8 размещает старший октет. + build_id = metadata["build_id"].encode("ascii") # Контракт использует ровно восемь печатных ASCII-символов. + words.extend((build_id[index] << 8) | build_id[index + 1] for index in range(0, 8, 2)) # Слова 8..11 содержат пары символов, первый в старших восьми битах. + return words # Порядок совпадает с firmware_info_to_registers(), включая дату в UTC. + + +def verilog(words): # Генерирует Verilog-2001 без примитивов конкретного производителя. + lines = ["module firmware_identity ( // Комбинационный паспорт сборки с адресацией 16-битными словами.", " input wire [3:0] word_addr, // Четыре бита адресуют слова 0..11; остальные адреса возвращают ноль.", " output reg [15:0] word_data // Данные выбранного слова; синхронизацию с шиной выполняет проект.", "); // Интерфейс не требует тактового сигнала и сброса.", "always @* begin // Полная комбинационная чувствительность исключает устаревшее значение при смене адреса.", " case (word_addr) // Каждому адресу соответствует константа, вычисленная до синтеза."] # Использует синтаксис, доступный старым XST и Quartus II. + lines.extend(f" 4'd{index}: word_data = 16'h{word:04X}; // Слово {index} общего контракта firmware-info v1, значение без знака." for index, word in enumerate(words)) # Явные размеры исключают расширение констант и зависимость от порядка байтов. + lines.extend([" default: word_data = 16'h0000; // Неиспользуемые адреса не создают защёлок и возвращают ноль.", " endcase // Все входные комбинации определяют выход.", "end // Завершает комбинационное чтение паспорта.", "endmodule // Проект должен подключить выход к доступной хосту карте регистров."]) # Выход обязательно используется верхним уровнем, иначе синтезатор удалит паспорт. + return "\n".join(lines) + "\n" # Сохраняет единый формат строк UTF-8 с завершающим переводом строки. + + +def vhdl(words): # Генерирует VHDL-93 с тем же интерфейсом для проектов без Verilog. + lines = ["library ieee; -- Подключает стандартную библиотеку логических типов.", "use ieee.std_logic_1164.all; -- Определяет std_logic_vector для адреса и 16-битного слова.", "entity firmware_identity is -- Объявляет паспорт, подключаемый к карте регистров проекта.", " port ( -- Описывает комбинационный интерфейс без тактового домена.", " word_addr : in std_logic_vector(3 downto 0); -- Адрес слова 0..11; четыре бита покрывают весь контракт.", " word_data : out std_logic_vector(15 downto 0) -- 16-битное значение общего регистра версии.", " ); -- Завершает описание портов.", "end firmware_identity; -- Закрывает внешний интерфейс паспорта.", "architecture rtl of firmware_identity is -- Реализует паспорт только константами без памяти производителя.", "begin -- Начинает комбинационную архитектуру.", " with word_addr select word_data <= -- При изменении адреса немедленно выбирает соответствующее слово."] # Выбор с others определяет выход для всех состояний входа. + lines.extend(f' x"{word:04X}" when "{index:04b}", -- Слово {index} контракта firmware-info v1, шестнадцатеричная константа 16 бит.' for index, word in enumerate(words)) # Двоичные селекторы не требуют numeric_std и преобразования адреса. + lines.extend([' x"0000" when others; -- Неиспользуемые и неопределённые адреса возвращают нулевое слово.', "end rtl; -- Завершает синтезируемый паспорт сборки."]) # Полный выбор исключает защёлки. + return "\n".join(lines) + "\n" # Возвращает текст для атомарной записи в UTF-8. + + +def fingerprint(image): # Фиксирует состояние результата перед сборкой для отказа при повторной упаковке старого файла. + if not image.exists(): # При первой сборке ожидаемого образа ещё нет. + return None # Любой непустой файл после успешной сборки будет новым результатом. + return {"mtime_ns": image.stat().st_mtime_ns, "sha256": hashlib.sha256(image.read_bytes()).hexdigest()} # Изменение времени допускает побайтно воспроизводимую пересборку. + + +def prepare(repository, config, output, image, toolchain, language): # Резервирует единственный номер до синтеза и создаёт оба варианта HDL. + repository, config, output, image = (path.resolve() for path in (repository, config, output, image)) # Все пути в метаданных независимы от последующих cd в САПР. + if image.suffix.lower() not in FORMATS[toolchain]: # Не выдаёт произвольный или служебный файл за нативный результат данного flow. + raise ValueError(f"{toolchain}: expected {sorted(FORMATS[toolchain])}") # Неверный путь останавливает подготовку до увеличения версии. + before = fingerprint(image) # Читает старый результат до резервирования номера, чтобы отказ чтения не занимал версию. + metadata = shared.prepare(repository, TEMPLATES, config, output) # Использует общий атомарный итератор, Git, SOURCE_DATE_EPOCH и UTC. + words = registers(metadata) # Упаковывает уже зарезервированную версию в общий контракт регистров. + metadata["fpga"] = {"toolchain": toolchain, "language": language, "image_path": str(image), "image_before": before, "register_words": words} # Связывает post-build с конкретным файлом и снимком pre-build. + shared.write_atomic(output / "firmware_identity.v", verilog(words)) # Даёт старым XST/Quartus синтезируемый Verilog-2001. + shared.write_atomic(output / "firmware_identity.vhd", vhdl(words)) # Даёт VHDL-проекту тот же паспорт без смешения языков. + shared.write_atomic(output / "firmware_identity.json", json.dumps(metadata, ensure_ascii=False, indent=2) + "\n") # Сохраняет FPGA-привязку в тех же метаданных, которые попадут в manifest. + return metadata # Вызывающий сценарий добавляет в проект только один выбранный язык. + + +def finish(metadata_path, output, export=None): # Вызывается только после успешной полной сборки нативного образа. + metadata_path = metadata_path.resolve() # Исключает зависимость пути от рабочего каталога post-build. + metadata = json.loads(metadata_path.read_text(encoding="utf-8")) # Использует сохранённый pre-build, не запрашивая Git и время повторно. + image = Path(metadata["fpga"]["image_path"]) # Упаковывает исключительно тот файл, который был указан перед синтезом. + if not image.is_file() or not image.stat().st_size: # Отсутствующий или пустой результат не может стать выпуском. + raise ValueError(f"Missing or empty FPGA image: {image}") # Ошибка блокирует создание manifest и архива. + if fingerprint(image) == metadata["fpga"]["image_before"]: # Старый файл с прежним временем и содержимым означает отсутствие нового результата. + raise ValueError("FPGA image was not updated after prepare") # Не связывает новый номер версии с прежней прошивкой после неудачного запуска. + shared.seal(image, metadata_path) # Считает SHA-256 точных байтов .bit/.sof, передаваемых программатору. + shared.verify(image, image.with_suffix(image.suffix + ".manifest.json")) # Проверяет размер и контрольную сумму до архивирования. + extension = "v" if metadata["fpga"]["language"] == "verilog" else "vhd" # Выбирает точный HDL-паспорт, зарегистрированный в проекте перед синтезом. + hdl = metadata_path.parent / ("firmware_identity." + extension) # Хранит исходник констант рядом с pre-build JSON. + return shared.archive_build(image, metadata_path, output, extra_files=(hdl,), export=export) # Сохраняет HDL с образом; общий архиватор проверяет локальную и экспортную копии. + + +def main(): # Разделяет подготовку и упаковку, чтобы Tcl мог остановиться между ними при ошибке САПР. + parser = argparse.ArgumentParser(description=__doc__) # Печатает назначение общего FPGA-инструмента в --help. + commands = parser.add_subparsers(dest="command", required=True) # Требует явный этап сборки. + before = commands.add_parser("prepare") # Создаёт интерфейс pre-build без запуска САПР из Python. + for name in ("repository", "config", "output", "image"): # Все входные и выходные пути передаются отдельными аргументами. + before.add_argument("--" + name, type=Path, required=True) # Path сохраняет пробелы и кириллицу без shell-подстановки. + before.add_argument("--toolchain", choices=FORMATS, required=True) # Ограничивает форматы результата выбранной САПР. + before.add_argument("--language", choices=("verilog", "vhdl"), default="verilog") # Позволяет выбрать один HDL для регистрации в проекте. + after = commands.add_parser("finish") # Создаёт интерфейс post-build только для готового результата. + after.add_argument("--metadata", dest="metadata_path", type=Path, required=True) # Требует тот же паспорт, что был создан перед синтезом. + after.add_argument("--output", type=Path, required=True) # Размещает архивы отдельно от файлов синтеза. + after.add_argument("--export", type=Path) # По явному запросу копирует проверенную архивную папку в локальный каталог. + arguments = vars(parser.parse_args()) # Преобразует именованные аргументы в параметры выбранной функции. + command = arguments.pop("command") # Удаляет служебное имя команды из аргументов функции. + result = {"prepare": prepare, "finish": finish}[command](**arguments) # Ошибки прерывают процесс с ненулевым кодом для Tcl catch. + print(json.dumps(result, ensure_ascii=False)) # Даёт журналу САПР путь архива и использованные метаданные. + + +if __name__ == "__main__": # Импорт в тестах не должен изменять проектную версию. + main() # Запускает CLI только при прямом вызове Python. diff --git a/tools/firmware-build/fpga/ise-build.bat b/tools/firmware-build/fpga/ise-build.bat new file mode 100644 index 0000000..3c15bc3 --- /dev/null +++ b/tools/firmware-build/fpga/ise-build.bat @@ -0,0 +1,19 @@ +@chcp 65001 >nul +@rem Переключение на UTF-8 сохраняет русские пути и комментарии локальной команды сборки ISE. +@echo off +rem Не допускает изменения окружения родительской консоли и раскрытия символа ! в путях. +setlocal EnableExtensions DisableDelayedExpansion +rem Находит штатный launcher Python 3 без привязки к каталогу его установки. +where py >nul 2>nul +rem При отсутствии launcher переключается на Python из PATH. +if errorlevel 1 goto use_python +rem Запускает локальную обвязку независимо от текущего рабочего каталога. +py -3 "%~dp0firmware_build.py" %* +rem Возвращает точный код сборки или проверки параметров. +exit /b %errorlevel% +rem Обслуживает компьютеры, где установлен только python.exe. +:use_python +rem Передаёт необязательный --check для проверки настройки без увеличения версии. +python "%~dp0firmware_build.py" %* +rem Не скрывает ошибку отсутствующего Python, окружения ISE или самой сборки. +exit /b %errorlevel% diff --git a/tools/firmware-build/fpga/ise-env.bat b/tools/firmware-build/fpga/ise-env.bat new file mode 100644 index 0000000..b1fa478 --- /dev/null +++ b/tools/firmware-build/fpga/ise-env.bat @@ -0,0 +1,8 @@ +@rem Получает окружение ISE в дочернем CMD; вывод SET захватывается Python и не попадает в журнал. +@echo off +rem Активирует штатную установку, путь передан через окружение без вставки в shell-код. +call "%FW_ISE_SETTINGS%" >nul +rem Не возвращает частично настроенное окружение после отказа settings.bat. +if errorlevel 1 exit /b %errorlevel% +rem CMD /u выдаёт переменные в UTF-16LE независимо от текущей кодовой страницы. +set diff --git a/tools/firmware-build/fpga/ise-project.md b/tools/firmware-build/fpga/ise-project.md new file mode 100644 index 0000000..a07c3fa --- /dev/null +++ b/tools/firmware-build/fpga/ise-project.md @@ -0,0 +1,27 @@ +# Сборка прошивки ISE + +Для сборки запускайте `build_firmware.bat`. Версия увеличивается перед +синтезом; результат и архив сохраняются в `build/ise/firmware/`. +`build_firmware.bat --check` проверяет настройки и наличие ISE без сборки +и увеличения версии. + +Один раз подключите экземпляр `firmware_identity` к верхнему модулю: +адрес слова — `word_addr[3:0]`, выход — `word_data[15:0]`. +Заготовка подключения находится в `firmware_identity_instance.txt`. +Выход включите в чтение вашей шины, иначе синтезатор удалит паспорт. +Сценарий сам добавит generated HDL к проекту при сборке. + +В `firmware_identity.json` меняются изделие и номер версии. +В `firmware_build.json` находятся пути проекта, `.bit`, templates, +каталог результатов, язык и необязательный путь `ise_settings` к +`settings64.bat` или `settings32.bat` вашей установки ISE. +Если окружение ISE не найдено автоматически, задайте этот путь один раз. + +Общие инструменты используются из каталога templates, указанного в настройках. +Храните локальные BAT, Python, JSON и заготовку подключения в Git. +Каталог сборки добавлен установщиком в `.gitignore`; остальные результаты +ISE также добавьте в игнорируемые файлы проекта. + +После загрузки `.bit` сравните 12 слов паспорта с `fpga.register_words` +в manifest из архива. Повторная установка сохраняет существующие JSON +и занятый номер версии. Одновременные сборки с одним JSON не поддерживаются. diff --git a/tools/firmware-build/fpga/ise.tcl b/tools/firmware-build/fpga/ise.tcl new file mode 100644 index 0000000..2336371 --- /dev/null +++ b/tools/firmware-build/fpga/ise.tcl @@ -0,0 +1,32 @@ +# Подключает общие процедуры из того же каталога поставки templates. +source [file join [file dirname [info script]] common.tcl] +# Любая ошибка подготовки, XST, реализации или упаковки возвращает ненулевой код xtclsh. +if {[catch { + # Принимает project.xise, config.json, output, top.bit, язык и необязательный python.exe. + fw::init $argv ise + # Открывает существующий проект с выбранной платой, top и ограничениями UCF. + project open $fw::settings(project) + # Создаёт HDL-паспорт до синтеза XST и увеличивает только общий счётчик. + fw::prepare + # Добавляет выбранный HDL-паспорт; повторное добавление существующего источника поддерживает ISE. + xfile add $fw::settings(hdl) + # Принудительно повторяет всю цепочку до BitGen, чтобы паспорт вошёл в новый bitstream. + set result [process run "Generate Programming File" -force rerun_all] + # ISE может вернуть false без Tcl-исключения при отказе дочернего процесса. + if {![string is true -strict $result]} { + # Не позволяет упаковать оставшийся от предыдущей сборки файл .bit. + error "ISE Generate Programming File failed: $result" + # Заканчивает проверку результата процесса. + } + # Записывает manifest, SHA-256 и архив только после успешного BitGen. + fw::finish + # Сохраняет регистрацию HDL-паспорта и закрывает проект. + project close +# catch сохраняет текст ошибки, не продолжая цепочку сборки. +} message]} { + # Выводит причину отказа в поток ошибок командной строки. + puts stderr $message + # Ненулевой код позволяет внешнему BAT или CI остановить выпуск. + exit 1 +# Закрывает обработчик ошибок. +} diff --git a/tools/firmware-build/fpga/ise_bootstrap.py b/tools/firmware-build/fpga/ise_bootstrap.py new file mode 100644 index 0000000..148cea7 --- /dev/null +++ b/tools/firmware-build/fpga/ise_bootstrap.py @@ -0,0 +1,23 @@ +"""Локальная обвязка ISE: настройки проекта и запуск общего инструмента templates.""" # Установщик копирует файл как firmware_build.py. +import json # Читает только настройки путей, оставляя номер версии отдельному JSON. +from pathlib import Path # Разрешает пути относительно установленной обвязки. +import subprocess # Передаёт аргументы отдельным списком без сборки shell-команды. +import sys # Сохраняет выбранный Python 3 и код возврата общей сборки. + + +def main(): # Одна локальная команда обращается к алгоритмам общей библиотеки. + config = Path(__file__).resolve().with_name("firmware_build.json") # Не зависит от того, из какой папки запущен BAT. + settings = json.loads(config.read_text(encoding="utf-8-sig")) # Принимает UTF-8, включая JSON, сохранённый редактором с BOM. + templates = (config.parent / settings["templates"]).resolve() # Поддерживает относительное подключение или абсолютный путь библиотеки. + helper = templates / "tools/firmware-build/fpga/ise_project.py" # Хранит реализацию сборки в одном месте для всех проектов. + if not helper.is_file(): # Перемещение библиотеки должно дать понятную причину отказа. + raise ValueError(f"templates not found; edit templates in {config}") # Не запускает сборку с неподходящим инструментом из PATH. + return subprocess.call([sys.executable, str(helper), "build", "--settings", str(config), *sys.argv[1:]]) # Сохраняет пробелы и кириллицу в каждом аргументе. + + +if __name__ == "__main__": # Импорт для проверки не должен запускать сборку проекта. + try: # Превращает ошибку настройки в короткое сообщение для консоли. + sys.exit(main()) # Сохраняет точный код завершения общего Tcl-flow. + except (OSError, ValueError, KeyError) as error: # Обрабатывает отсутствующие файлы и неверный JSON до запуска САПР. + print(f"[firmware-build] {error}", file=sys.stderr) # Не скрывает путь настройки, которую требуется исправить. + sys.exit(2) # Отличает ошибку настройки от успешной сборки. diff --git a/tools/firmware-build/fpga/ise_project.py b/tools/firmware-build/fpga/ise_project.py new file mode 100644 index 0000000..bf250e6 --- /dev/null +++ b/tools/firmware-build/fpga/ise_project.py @@ -0,0 +1,185 @@ +"""Установка локальных BAT и автоматический запуск контроля прошивки проекта ISE.""" # Общие алгоритмы версии остаются в identity.py. +import argparse # Поддерживает интерактивную установку и явные параметры для автоматизации. +import importlib.util # Подключает существующий FPGA-генератор без повторения его алгоритмов. +import json # Сохраняет отдельно параметры сборки и сохраняемый номер версии. +import os # Разрешает относительные пути библиотеки и окружение Windows. +from pathlib import Path # Работает с путями проекта независимо от текущего каталога. +import shutil # Находит xtclsh в PATH настроенного окружения ISE. +import subprocess # Запускает окружение ISE и готовый Tcl-flow с контролем кодов возврата. +import sys # Передаёт Tcl тот же Python 3, которым запущена обвязка. +import tempfile # Подготавливает предварительный HDL без увеличения рабочего счётчика. +import xml.etree.ElementTree as ET # Читает стандартный XML .xise, не меняя исходный проект. +HERE = Path(__file__).resolve().parent # Находит шаблоны рядом с установщиком. +TEMPLATES = HERE.parents[2] # Поднимается от tools/firmware-build/fpga к корню библиотеки. + + +def relative(path, root): # Сохраняет переносимые пути при расположении проекта и templates на одном диске. + try: # Windows не позволяет вычислить относительный путь между разными дисками. + return Path(os.path.relpath(path, root)).as_posix() # JSON использует прямые слеши без двойного экранирования. + except ValueError: # Разные диски требуют абсолютной привязки. + return path.as_posix() # Абсолютный путь можно заменить в firmware_build.json после переноса. + + +def project_info(project, language=None, image=None): # Извлекает параметры из существующего .xise без пользовательского копирования команд. + project = project.resolve() # Нормализует путь до чтения XML и выбора корня проекта. + if project.is_dir(): # Разрешает перетащить папку проекта вместо отдельного .xise. + choices = list(project.glob("*.xise")) # Не выбирает вложенные архивы и другие платы рекурсивным поиском. + if len(choices) != 1: # Несколько проектов требуют явного выбора .xise пользователем. + raise ValueError("Select one .xise file; the directory must contain exactly one project") # Не угадывает плату по времени изменения. + project = choices[0] # Единственный проект определён однозначно. + if project.suffix.lower() != ".xise" or not project.is_file(): # Не принимает произвольный каталог как проект ISE. + raise ValueError(f"ISE project not found: {project}") # Останавливает установку до записи локальных файлов. + tree = ET.parse(project) # Использует XML-парсер stdlib с поддержкой пространства имён Xilinx. + properties = {} # Собирает только свойства проекта, необходимые для запуска сборки. + for element in tree.iter(): # Поддерживает как namespaced .xise, так и минимальные тестовые проекты. + if element.tag.rsplit("}", 1)[-1] == "property": # Игнорирует список исходников и настройки других XML-элементов. + attributes = {key.rsplit("}", 1)[-1]: value for key, value in element.attrib.items()} # Снимает namespace с атрибутов name и value. + properties[attributes.get("name", "")] = attributes.get("value", "") # Читает сохранённое значение свойства без изменения .xise. + device = properties.get("Device", "") # Точное устройство берётся из настроек исходного проекта. + if not device or "cpld" in properties.get("Device Family", "").lower() or device.lower().startswith(("xc95", "xc2c")): # Данный flow выпускает FPGA .bit, а CPLD требует отдельной цепочки .jed. + raise ValueError("A configured FPGA project producing .bit is required") # Не устанавливает неподходящий шаблон на CPLD. + top = properties.get("Implementation Top", "").split("|") # ISE хранит тип и имя top через вертикальный разделитель. + name = properties.get("Output File Name") or (top[1] if len(top) > 1 else "") # Явное имя BitGen имеет приоритет над именем верхнего модуля. + if not name and image is None: # Отсутствующие настройки не должны приводить к выбору случайного .bit. + raise ValueError("Set Implementation Top in ISE or pass --image path/to/top.bit") # Позволяет явно указать нестандартный результат BitGen. + working = project.parent / properties.get("Working Directory", ".") # Учитывает отдельный рабочий каталог реализации ISE. + image = (project.parent / image if image is not None else working / (name if name.lower().endswith(".bit") else name + ".bit")).resolve() # Путь CLI разрешается от проекта, штатный результат — от Working Directory. + if image.suffix.lower() != ".bit": # Только .bit поддерживается исходным ise.tcl. + raise ValueError("ISE image must have .bit extension") # Ошибка пути обнаруживается до создания настройки. + top_file = properties.get("Implementation Top File", "").lower() # Расширение реального верхнего исходника точнее общего предпочтения языка. + detected = "vhdl" if top_file.endswith((".vhd", ".vhdl")) else "verilog" if top_file.endswith((".v", ".sv")) else properties.get("Preferred Language", "Verilog").lower() # Поддерживает оба языка генерируемого паспорта. + target = device + properties.get("Speed Grade", "") + properties.get("Package", "") # Сохраняет устройство, скоростную группу и корпус из .xise в информационном поле target. + return project, image, language or detected, target # Возвращает только параметры, требуемые общему Tcl-flow. + + +def find_settings(): # Ищет стандартную установку ISE без рекурсивного сканирования дисков. + candidates = [] # Порядок поиска предпочитает уже активное окружение. + xilinx = os.environ.get("XILINX") # Штатная переменная ISE обычно указывает на ISE_DS/ISE. + if xilinx: # Активное окружение даёт наиболее точную подсказку расположения. + candidates.extend(Path(xilinx).parent / name for name in ("settings64.bat", "settings32.bat")) # Проверяет оба варианта разрядности установки. + for drive in "CDEFGHIJKLMNOPQRSTUVWXYZ": # Проверяет стандартный корень Xilinx только на обычных дисках Windows. + base = Path(drive + ":/Xilinx") # Не просматривает содержимое пользовательских проектов. + if base.is_dir(): # Отсутствующий диск или каталог пропускается без ошибки установки. + candidates.extend(sorted(base.glob("*/ISE_DS/settings64.bat"), reverse=True)) # Сначала предлагает 64-битную установку из стандартной структуры. + candidates.extend(sorted(base.glob("*/ISE_DS/settings32.bat"), reverse=True)) # Поддерживает старые 32-битные установки при отсутствии 64-битной. + return next((str(path.resolve()) for path in candidates if path.is_file()), "") # Пустое значение разрешает настроить путь позже. + + +def install(project, language=None, image=None, ise_settings=None): # Создаёт локальные команды и настройки без увеличения версии. + project, image, language, target = project_info(project, language, image) # Проверяет все входные параметры до записи файлов. + if language not in ("verilog", "vhdl"): # Не переносит неизвестные предпочтения языка в общий flow. + raise ValueError("Expected verilog or vhdl") # Ошибка языка требует явного --language при установке. + root = project.parent # Все локальные файлы лежат рядом с .xise для простого запуска. + build_path = root / "firmware_build.json" # Настройки путей отделены от сохраняемого итератора версии. + identity_path = root / "firmware_identity.json" # Существующая рабочая версия никогда не заменяется примером. + settings = {"schema": 1, "project": project.name, "templates": relative(TEMPLATES, root), "image": relative(image, root), "language": language, "output": "build/ise", "ise_settings": str(ise_settings.resolve()) if ise_settings else find_settings()} # По умолчанию пользователь не редактирует пути вручную. + if build_path.exists(): # Повторная установка должна сохранить индивидуальные настройки сборки. + settings = json.loads(build_path.read_text(encoding="utf-8-sig")) # Использует прежний output и язык при создании предварительного HDL. + if (root / settings["project"]).resolve() != project: # Один набор локальных BAT не должен незаметно переключиться на другую плату. + raise ValueError("firmware_build.json belongs to another .xise project") # Требует отдельную папку настройки для другого проекта. + identity = json.loads(identity_path.read_text(encoding="utf-8-sig")) if identity_path.exists() else {"product": project.stem, "target": target, "version": [0, 1, 0], "increment_version": True} # Сохраняет прежний счётчик побайтно, а новый заполняет из .xise. + if type(identity.get("increment_version", False)) is not bool: # Предварительная генерация не должна скрыть неверный тип рабочего флага итератора. + raise ValueError("increment_version must be true or false") # Останавливает установку до создания предварительного HDL. + files = {root / "build_firmware.bat": (HERE / "ise-build.bat").read_bytes(), root / "firmware_build.py": (HERE / "ise_bootstrap.py").read_bytes(), root / "FIRMWARE_SETUP.md": (HERE / "ise-project.md").read_bytes()} # Копирует только локальные обвязки; алгоритмы остаются в указанной библиотеке templates. + for path, data in files.items(): # Проверяет коллизии всех управляемых файлов до первой записи. + if path.exists() and path.read_bytes() != data: # Не перезаписывает чужой BAT или правки пользователя при повторном запуске. + raise ValueError(f"Existing file differs; preserve or rename it before installation: {path}") # Существующие пользовательские файлы требуют явного разрешения конфликта. + spec = importlib.util.spec_from_file_location("ise_install_identity", HERE / "identity.py") # Использует тот же генератор, что последующая сборка. + fpga = importlib.util.module_from_spec(spec) # Создаёт изолированный модуль подготовки предварительного HDL. + spec.loader.exec_module(fpga) # Загружает общий итератор и FPGA-адаптер без запуска CLI. + output = (root / settings["output"]).resolve() # Учитывает выходной каталог, сохранённый предыдущей установкой. + output.mkdir(parents=True, exist_ok=True) # Создаёт место предварительного паспорта и временной конфигурации. + with tempfile.TemporaryDirectory(prefix=".ise-setup-", dir=output) as temporary: # Не редактирует рабочую версию ради предварительной генерации исходников. + preview = Path(temporary) / "identity.json" # Временный JSON существует только во время установки. + preview.write_text(json.dumps({**identity, "increment_version": False}, ensure_ascii=False), encoding="utf-8") # Явно отключает итератор только в копии для предварительного HDL. + fpga.prepare(root, preview, output / "generated", (root / settings["image"]).resolve(), "ise", settings["language"]) # Создаёт HDL до первого запуска ISE, не занимая номер. + for path, data in files.items(): # Записывает заранее проверенные локальные обвязки. + if not path.exists(): # Повторная установка не меняет время и содержимое прежних файлов. + path.write_bytes(data) # Сохраняет исходные UTF-8 файлы из templates без изменения комментариев. + for path, data in ((build_path, settings), (identity_path, identity)): # Устанавливает две настройки с разными назначениями. + if not path.exists(): # Существующие настройки и рабочая версия остаются побайтно прежними. + path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") # Новые JSON доступны для обычного ручного редактирования. + snippet = root / "firmware_identity_instance.txt" # Отдельная заготовка показывает единственную проектную часть подключения. + if not snippet.exists(): # Не меняет уже адаптированный пользователем экземпляр паспорта. + snippet.write_text(instance(settings["language"]), encoding="utf-8") # Генерирует пример именно для языка проекта. + ignore = root / ".gitignore" # Исключение результатов предотвращает ложный dirty от generated-файлов. + existing = ignore.read_text(encoding="utf-8-sig") if ignore.exists() else "" # Сохраняет все существующие правила игнорирования проекта. + ignored = relative(output, root) + "/" # Привязывает исключение к установленному выходному каталогу. + if output.is_relative_to(root) and ignored not in existing.splitlines(): # Внешние каталоги не добавляет в .gitignore данного репозитория. + with ignore.open("a", encoding="utf-8", newline="\n") as stream: # Дописывает одно правило, не заменяя пользовательский файл. + stream.write(("\n" if existing and not existing.endswith("\n") else "") + "# Результаты контроля прошивки ISE.\n" + ignored + "\n") # Отделяет новое правило и объясняет его назначение. + print(f"[firmware-build] Installed: {root / 'build_firmware.bat'}") # Показывает готовую команду для обычной сборки. + print(f"[firmware-build] Connect identity ports using: {snippet}") # Оставляет пользователю только подключение к шине конкретного проекта. + return settings # Позволяет тестам проверить автоматически извлечённые параметры. + + +def instance(language): # Возвращает короткую заготовку подключения без изменения верхней схемы пользователя. + if language == "verilog": # Verilog допускает прямое создание экземпляра с именованными портами. + return "wire [15:0] identity_data; // Слово паспорта подключается к мультиплексору чтения вашей шины.\nfirmware_identity u_identity ( // Генерируемый модуль добавляется сценарием сборки.\n .word_addr(identity_word_offset), // Четырёхбитный относительный адрес слова задаёт декодер проекта.\n .word_data(identity_data) // Выход должен использоваться схемой, иначе синтезатор удалит паспорт.\n); // Тактовое согласование чтения выполняет проект.\n" # Каждый элемент интерфейса снабжён пояснением для адаптации. + return "component firmware_identity is -- Объявляется до begin архитектуры верхнего уровня.\n port ( -- Описывает интерфейс генерируемого паспорта.\n word_addr : in std_logic_vector(3 downto 0); -- Относительный адрес слова 0..11 задаёт декодер проекта.\n word_data : out std_logic_vector(15 downto 0) -- 16-битное слово для ответа шины.\n ); -- Закрывает список портов.\nend component; -- Завершает декларацию компонента.\nsignal identity_data : std_logic_vector(15 downto 0); -- Объявляется до begin и используется при чтении шины.\n-- Следующий экземпляр размещается после begin архитектуры.\nu_identity : firmware_identity -- Создаёт паспорт текущей сборки.\n port map ( -- Сопоставляет интерфейс паспорта с сигналами проекта.\n word_addr => identity_word_offset, -- Четырёхбитный относительный адрес слова формирует проект.\n word_data => identity_data -- Выход включается в ответ шины, чтобы сохранить паспорт при синтезе.\n ); -- Завершает подключение компонента.\n" # Декларация component позволяет создать entity только перед фактической сборкой. + + +def ise_environment(settings): # Подготавливает окружение автоматически, если xtclsh ещё отсутствует в PATH. + environment = {name.upper(): value for name, value in os.environ.items()} # В Windows имена переменных нечувствительны к регистру; единый регистр исключает два разных PATH. + if shutil.which("xtclsh", path=environment.get("PATH")): # Запуск из уже настроенной консоли не требует повторной настройки. + return environment # Сохраняет окружение выбранной пользователем установки. + startup = settings.get("ise_settings") or find_settings() # Использует явный путь либо стандартную найденную установку. + if not startup or not Path(startup).is_file(): # Не запускает pre-build, пока САПР не найдена. + raise ValueError("ISE not found; set ise_settings in firmware_build.json to settings64.bat") # Даёт одно место для исправления нестандартной установки. + if any(character in startup for character in '%!"\r\n'): # CALL повторно раскрывает переменные, поэтому специальные подстановки в пути запрещены. + raise ValueError("ISE settings path contains unsupported command expansion characters") # Не допускает интерпретацию пути как дополнительной команды. + environment["FW_ISE_SETTINGS"] = startup # Путь передаётся через окружение, без вставки в shell-код. + capture = HERE / "ise-env.bat" # Статический BAT исключает вложенное экранирование команды CALL с пробелами. + result = subprocess.run([environment.get("COMSPEC", "cmd.exe"), "/d", "/u", "/v:off", "/c", "call", str(capture)], env=environment, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True) # Ключ /u выдаёт SET в UTF-16LE независимо от кодовой страницы; окружение не выводится в журнал. + for line in result.stdout.decode("utf-16-le").splitlines(): # Декодирование Unicode сохраняет русские пути после запуска UTF-8 BAT. + name, separator, value = line.partition("=") # Значения переменных могут сами содержать знак равенства. + if separator and name: # Служебные записи текущих дисков вида =C: не передаются в subprocess. + environment[name.upper()] = value # Получает PATH, XILINX и библиотечные пути без дублирования переменных Windows. + return environment # Настройка применяется к последующему запуску Tcl. + + +def build(settings_path, check=False): # Читает локальную настройку и запускает существующий полный Tcl-flow. + settings_path = settings_path.resolve() # Разрешает пути относительно каталога локальной обвязки. + root = settings_path.parent # Рабочий каталог .xise задаётся настройкой данного проекта. + settings = json.loads(settings_path.read_text(encoding="utf-8-sig")) # Не читает номер версии: он изменяется только внутри общего pre-build. + paths = {name: (root / settings[name]).resolve() for name in ("project", "templates", "image", "output")} # Преобразует все сохранённые пути до запуска САПР. + script = paths["templates"] / "tools/firmware-build/fpga/ise.tcl" # Общий Tcl выполняет генерацию паспорта, синтез и контроль результата. + if not script.is_file() or not paths["project"].is_file() or not (root / "firmware_identity.json").is_file(): # Проверяет обязательные файлы до запуска итератора. + raise ValueError("Project, templates or firmware_identity.json not found; check firmware_build.json") # Не создаёт пустую конфигурацию вместо потерянной пользовательской. + environment = ise_environment(settings) # Находит и активирует штатную установку ISE перед pre-build. + executable = shutil.which("xtclsh", path=environment.get("PATH", environment.get("Path"))) # Использует исполняемый файл именно подготовленного окружения. + if not executable: # Неподходящий settings.bat не должен запускать случайную программу. + raise ValueError("xtclsh was not found after loading ISE settings") # Останавливает сборку до увеличения версии. + print(f"[firmware-build] Project: {paths['project']}", flush=True) # Показывает выбранный проект при запуске BAT двойным щелчком. + if check: # Проверка установки не должна создавать новый паспорт или занимать номер. + print(f"[firmware-build] Ready: {executable}") # Подтверждает наличие зависимостей для обычного запуска. + return 0 # Завершает проверку без Tcl-flow. + return subprocess.call([executable, str(script), str(paths["project"]), str(root / "firmware_identity.json"), str(paths["output"]), str(paths["image"]), settings["language"], sys.executable], cwd=root, env=environment) # Передаёт параметры отдельными аргументами и сохраняет исходный код ошибки САПР. + + +def main(): # Разделяет установку проекта и последующие сборки одной локальной командой. + parser = argparse.ArgumentParser(description=__doc__) # Предоставляет справку для нестандартных путей проекта. + commands = parser.add_subparsers(dest="command", required=True) # Явно выбирает действие без скрытого запуска сборки. + setup = commands.add_parser("install") # Установка создаёт обвязки и предварительный паспорт. + setup.add_argument("project", type=Path, nargs="?") # Двойной щелчок без аргументов включает запрос пути. + setup.add_argument("--language", choices=("verilog", "vhdl")) # Позволяет переопределить язык для смешанного проекта. + setup.add_argument("--image", type=Path) # Поддерживает нестандартное имя результата BitGen. + setup.add_argument("--ise-settings", type=Path) # Указывает settings.bat при нестандартной установке ISE. + run = commands.add_parser("build") # Этот режим вызывает установленная локальная Python-обвязка. + run.add_argument("--settings", dest="settings_path", type=Path, required=True) # Требует явный путь параметров проекта. + run.add_argument("--check", action="store_true") # Проверяет настройку без увеличения версии. + arguments = vars(parser.parse_args()) # Передаёт выбранной функции только её именованные параметры. + command = arguments.pop("command") # Удаляет служебное имя режима из параметров функции. + if command == "install": # Интерактивный запрос нужен только при запуске установщика без пути. + arguments["project"] = arguments["project"] or Path(input("ISE project (.xise or directory): ").strip().strip('"')) # Принимает вставленный путь из Проводника с внешними кавычками. + install(**arguments) # Заполняет локальную настройку и показывает готовую команду сборки. + return 0 # Успешная установка не запускает синтез автоматически. + return build(**arguments) # Обычная команда возвращает результат полного Tcl-flow. + + +if __name__ == "__main__": # Импорт для тестов не должен устанавливать файлы в рабочий проект. + try: # Сохраняет понятную причину отказа без длинной трассировки в BAT-окне. + sys.exit(main()) # Передаёт точный код сборки внешнему BAT или CI. + except (OSError, ValueError, KeyError, ET.ParseError, subprocess.CalledProcessError) as error: # Обрабатывает неверную настройку и отказ штатного settings.bat. + print(f"[firmware-build] {error}", file=sys.stderr) # Печатает исправимую причину остановки. + sys.exit(2) # Возвращает ошибку конфигурации, не скрывая её успешным завершением. diff --git a/tools/firmware-build/fpga/quartus.tcl b/tools/firmware-build/fpga/quartus.tcl new file mode 100644 index 0000000..daadf87 --- /dev/null +++ b/tools/firmware-build/fpga/quartus.tcl @@ -0,0 +1,60 @@ +# Подключает общие пути и Python-этапы, совместимые с Quartus II и Prime. +source [file join [file dirname [info script]] common.tcl] +# Ошибка execute_flow или упаковки не должна выглядеть успешным выпуском. +if {[catch { + # Берёт аргументы quartus_sh из штатного массива Quartus, включая необязательную revision. + set arguments $quartus(args) + # По умолчанию project_open выбирает текущую revision из .qpf. + set revision "" + # Седьмой аргумент разрешён только после явного пути python.exe. + if {[llength $arguments] == 7} { + # Позволяет явно собрать ревизию платы вместо текущей из .qpf. + set revision [lindex $arguments 6] + # Передаёт общему разбору только его шесть аргументов. + set arguments [lrange $arguments 0 5] + # Завершает извлечение необязательной revision. + } + # Принимает project.qpf, config.json, output, revision.sof, язык и необязательный python.exe. + fw::init $arguments quartus + # Подключает штатные команды открытия проекта. + package require ::quartus::project + # Загружает полную цепочку Analysis/Synthesis, Fitter, Assembler и Timing Analyzer. + load_package flow + # Quartus принимает имя проекта без расширения .qpf. + set project_name [file rootname $fw::settings(project)] + # Явная revision нужна для нескольких аппаратных конфигураций одного проекта. + if {$revision eq ""} { + # Использует текущую ревизию проекта, сохранённую в .qpf. + project_open $project_name + # При наличии имени выбирает заданную ревизию. + } else { + # Раздельный аргумент сохраняет пробелы в имени ревизии. + project_open -revision $revision $project_name + # Завершает открытие проекта. + } + # Генерирует новый паспорт перед Analysis/Synthesis, используя общий итератор. + fw::prepare + # По умолчанию регистрирует Verilog-2001 для старых Quartus II. + set assignment VERILOG_FILE + # VHDL-проект получает только альтернативный .vhd файл. + if {$fw::settings(language) eq "vhdl"} { + # Штатное назначение Quartus определяет язык нового исходника. + set assignment VHDL_FILE + # Завершает выбор языка. + } + # Добавляет паспорт к исходникам выбранной ревизии проекта. + set_global_assignment -name $assignment $fw::settings(hdl) + # Полная компиляция экспортирует назначения перед запуском модулей и создаёт новый .sof. + execute_flow -compile + # Контролирует свежесть .sof, формирует SHA-256, manifest и архив. + fw::finish + # Закрывает проект после успешной упаковки результата. + project_close +# Перехватывает отказ САПР и сохраняет причину для внешней сборки. +} message]} { + # Пишет сообщение в стандартный поток ошибок. + puts stderr $message + # Не допускает успешный exit при ошибке компиляции или проверки образа. + exit 1 +# Завершает общий обработчик ошибок. +} diff --git a/tools/firmware-build/fpga/tests/test_flows.py b/tools/firmware-build/fpga/tests/test_flows.py new file mode 100644 index 0000000..58367e1 --- /dev/null +++ b/tools/firmware-build/fpga/tests/test_flows.py @@ -0,0 +1,96 @@ +"""Исполняет реальные Tcl-сценарии с заменой только команд производителей САПР.""" # Проверяет порядок, пути с пробелами и блокирование post-build. +import json # Проверяет, сколько номеров занял каждый запуск сценария. +import os # Временно задаёт путь минимальной инициализации Tcl без GUI. +from pathlib import Path # Находит сценарии относительно тестов. +import sys # Передаёт Tcl путь к тому же Python 3, которым выполняется тест. +import tempfile # Изолирует проекты и готовые образы каждого запуска. +import unittest # Организует успешные и ошибочные сценарии трёх САПР. +import tkinter # Предоставляет настоящий Tcl-интерпретатор без открытия окна Tk. +SCRIPTS = Path(__file__).resolve().parents[1] # Находит поставку FPGA-сценариев. + + +class FlowTests(unittest.TestCase): # Проверяет Tcl-управление без подмены генерации паспорта и архивирования. + def run_flow(self, toolchain, language="verilog", failure="", revision=""): # Исполняет один полный flow во временном проекте. + scratch = SCRIPTS.parents[2] / ".codex-build" # Каталог внутри репозитория исключает внешние junction AppData при проверке Tcl на Windows. + scratch.mkdir(exist_ok=True) # Хранит временные проекты в уже игнорируемой области сборки. + with tempfile.TemporaryDirectory(prefix="FPGA flow пробел ", dir=scratch) as temporary: # Кириллица и пробелы должны пережить Tcl exec и Python CLI. + root = Path(temporary) # Не использует настоящие проекты или настройки САПР. + project = root / {"ise": "board.xise", "vivado": "board.xpr", "quartus": "board.qpf"}[toolchain] # Создаёт только входной маркер нужного типа проекта. + project.touch() # Открытие моделируется командами производителя, наличие проверяет реальный common.tcl. + config = root / "identity.json" # Хранит реальный сохраняемый счётчик. + config.write_text(json.dumps({"product": "Плата", "target": "test", "version": [0, 1, 0], "increment_version": "true" if failure == "prepare" else True}), encoding="utf-8") # Ошибка типа флага должна остановить prepare до резервирования; штатный flow занимает 0.1.1. + image = root / ("board.sof" if toolchain == "quartus" else "board.bit") # Совпадает с нативным форматом сценария. + image.write_bytes(b"old image") # Позволяет проверить отказ упаковки старого файла после сбоя сборки. + previous = Path.cwd() # Настоящий Tcl cd меняет текущий каталог процесса Python. + script = os.path.relpath(SCRIPTS / (toolchain + ".tcl"), previous) # Относительный путь проверяет нахождение Python-helper после перехода в другой каталог проекта. + interpreter = tkinter.Tcl() # Выполняет установленный Tcl без окна и без запуска xtclsh/Vivado/Quartus. + calls = [] # Собирает последовательность только вендорных команд. + def vendor(name, *arguments): # Моделирует интерфейс САПР, сохраняя настоящий exec Python-инструмента. + calls.append((name, *arguments)) # Позволяет проверить порядок подготовки и запуска дочерних шагов. + if name == "current_run": # В Vivado выбирается активная реализация с нестандартным именем. + return "impl_board" # Проверяет отсутствие жёсткой привязки к impl_1. + if name == "get_runs": # Возвращает имя объекта run без лишних преобразований. + return arguments[-1] # Достаточно для чтения PARENT, SRCSET и PROGRESS. + if name == "get_property": # Моделирует свойства выбранного синтеза и реализации. + field, target = arguments # Сохраняет различие родительского синтеза и активного в GUI. + if field == "PARENT": # Реализация может зависеть от другого синтеза. + return "synth_board" # Сценарий должен выбрать этого родителя. + if field == "SRCSET": # Новый модуль должен попасть именно в исходники родителя реализации. + return "sources_board" # Проверяет выбор набора вместо предположения sources_1. + return "0%" if failure == target else "100%" # Ожидание завершения при ошибке не считается успехом. + finished = name == "execute_flow" or name == "process" or (name == "wait_on_run" and arguments[0] == "impl_board") # Определяет место записи результата компиляции. + if finished and not failure: # Только успешный flow создаёт новый файл. + image.write_bytes(b"new image from " + toolchain.encode("ascii")) # Имитирует точные байты нового .bit/.sof. + if name == "process": # ISE сообщает отказ логическим результатом без Tcl error. + return "false" if failure else "true" # Проверяет особую обработку boolean в ise.tcl. + if name == "execute_flow" and failure: # Quartus сообщает ошибку компиляции Tcl-исключением. + raise RuntimeError("test compiler failure") # Вызывает catch в настоящем quartus.tcl. + return "" # Остальные команды производителя успешно завершаются без значения. + for name in ("project", "xfile", "process", "open_project", "current_run", "get_property", "get_runs", "add_files", "update_compile_order", "reset_run", "launch_runs", "wait_on_run", "close_project", "load_package", "project_open", "set_global_assignment", "execute_flow", "project_close"): # Подменяет только API производителя, не команды ядра Tcl. + interpreter.createcommand(name, lambda *arguments, name=name: vendor(name, *arguments)) # Привязывает имя при создании каждой callback-функции. + interpreter.eval('proc exit {code} {error "flow-exit:$code"}') # Не позволяет Tcl exit завершить процесс тестов. + interpreter.call("package", "provide", "::quartus::project", "1.0") # Удовлетворяет require пакета, чьи команды заменены заглушками. + arguments = [str(project), str(config), str(root / "build"), str(image), language, sys.executable] # Передаёт пути списком, без shell-экранирования. + if revision: # Quartus допускает дополнительное имя аппаратной ревизии. + arguments.append(revision) # Проверяет передачу значения с пробелами одним аргументом. + interpreter.call("set", "quartus(args)" if toolchain == "quartus" else "argv", tuple(arguments)) # Создаёт штатный источник аргументов соответствующей САПР. + try: # Гарантирует восстановление cwd даже при ожидаемом exit 1. + if failure: # Неудачная компиляция должна прервать сценарий до упаковки. + with self.assertRaisesRegex(tkinter.TclError, "flow-exit:1"): # Проверяет внешнее состояние отказа. + interpreter.call("source", script) # Исполняет настоящий сценарий со всеми проверками. + else: # Успешный сценарий обязан дойти до архива. + interpreter.call("source", script) # Реальный exec создаёт HDL, manifest и архив. + self.assertEqual(json.loads(config.read_text(encoding="utf-8"))["version"], [0, 1, 0] if failure == "prepare" else [0, 1, 1]) # Ошибка конфигурации не занимает номер; после начала сборки номер резервируется ровно один раз. + manifests = list((root / "build/firmware").glob("*/*.manifest.json")) # Ищет только выпущенные архивы текущего запуска. + self.assertEqual(len(manifests), 0 if failure else 1) # Ошибка синтеза/реализации не должна выпустить старый образ. + if failure == "prepare": # Ошибка общего Python pre-build должна блокировать запуск САПР. + self.assertFalse(any(call[0] in ("process", "launch_runs", "execute_flow") for call in calls)) # Не допускает синтез с прежним паспортом после ошибки настроек. + if not failure: # Дополнительно проверяет выбранный HDL после реального prepare. + suffix = "v" if language == "verilog" else "vhd" # В проект регистрируется только выбранный вариант. + self.assertTrue(any(str(root / "build/generated" / ("firmware_identity." + suffix)).replace("\\", "/") in str(call).replace("\\\\", "/") for call in calls)) # Учитывает Windows-разделители в строковом представлении кортежей. + finally: # Tcl cd не должен влиять на следующий тест или временную очистку. + os.chdir(previous) # Возвращает исходный каталог процесса до удаления проекта. + return calls # Отдаёт последовательность команд для специфических проверок САПР. + + def test_all_toolchains_and_languages(self): # Каждый сценарий должен выпустить файл для обеих HDL-реализаций. + for toolchain in ("ise", "vivado", "quartus"): # Покрывает три независимых набора Tcl-команд. + for language in ("verilog", "vhdl"): # Проверяет правильное расширение и тип назначения исходника. + with self.subTest(toolchain=toolchain, language=language): # Показывает точную конфигурацию возможного отказа. + self.run_flow(toolchain, language) # Создаёт реальный паспорт и архив без лицензии производителя. + + def test_failures_do_not_archive_old_images(self): # Проверяет false ISE, ошибку Quartus и неуспешные runs Vivado. + for toolchain, failure in (("ise", "compile"), ("quartus", "compile"), ("vivado", "synth_board"), ("vivado", "impl_board"), ("ise", "prepare"), ("vivado", "prepare"), ("quartus", "prepare")): # Отдельно покрывает обе стадии Vivado и отказ Python pre-build во всех САПР. + with self.subTest(toolchain=toolchain, failure=failure): # Сохраняет контекст ожидаемой ошибки. + self.run_flow(toolchain, failure=failure) # Старый файл существует, но архив не должен появиться. + + def test_revision_and_parent_synthesis(self): # Проверяет нестандартные имена конфигураций проектов. + quartus = self.run_flow("quartus", revision="board revision B") # Явная ревизия содержит пробелы и передаётся единым аргументом. + self.assertTrue(any(call[:3] == ("project_open", "-revision", "board revision B") for call in quartus)) # Не допускает случайной сборки default revision. + vivado = self.run_flow("vivado") # Активная реализация зависит от синтеза с нестандартным именем. + self.assertIn(("launch_runs", "synth_board"), vivado) # Собирается именно родитель выбранной реализации. + self.assertIn(("update_compile_order", "-fileset", "sources_board"), vivado) # Паспорт относится к набору исходников этого синтеза. + self.assertLess(vivado.index(("wait_on_run", "synth_board")), vivado.index(("launch_runs", "impl_board", "-to_step", "write_bitstream"))) # Реализация начинается только после ожидания синтеза. + + +if __name__ == "__main__": # Поддерживает прямой запуск файла проверки. + unittest.main() # Возвращает ненулевой код при нарушении порядка сборки. diff --git a/tools/firmware-build/fpga/tests/test_identity.py b/tools/firmware-build/fpga/tests/test_identity.py new file mode 100644 index 0000000..9faaad7 --- /dev/null +++ b/tools/firmware-build/fpga/tests/test_identity.py @@ -0,0 +1,94 @@ +"""Проверяет FPGA-паспорт, общий итератор и точные байты архивов без лицензии САПР.""" # Запуск через unittest discover из корня репозитория. +import importlib.util # Импортирует реальный FPGA-адаптер без установки пакета. +import json # Сравнивает конфигурацию, метаданные и manifest готового образа. +import os # Управляет меткой времени файла в тесте воспроизводимой пересборки. +from pathlib import Path # Ограничивает изменения собственными временными каталогами. +import re # Извлекает значения из HDL для проверки общего регистрационного контракта. +import tempfile # Изолирует результаты от рабочих проектов пользователя. +import unittest # Проверяет успешные сборки и отказы при устаревших файлах. +from unittest.mock import patch # Делает Git и время независимыми от машины запуска. +TOOL = Path(__file__).resolve().parents[1] / "identity.py" # Находит инструмент рядом с тестами. +SPEC = importlib.util.spec_from_file_location("fpga_identity", TOOL) # Создаёт отдельное имя для адаптера. +fpga = importlib.util.module_from_spec(SPEC) # Подготавливает импорт без вызова CLI. +SPEC.loader.exec_module(fpga) # Загружает код, используемый всеми тремя сценариями САПР. + + +class IdentityTests(unittest.TestCase): # Проверяет границу между общим генератором и HDL. + def setUp(self): # Создаёт проект с кириллицей и пробелами в пути. + temporary = tempfile.TemporaryDirectory(prefix="ПЛИС project ") # Проверяет UTF-8 и корректную передачу путей. + self.addCleanup(temporary.cleanup) # Очищает только файлы данного теста. + self.root = Path(temporary.name) # Хранит все входы и выходы внутри временного проекта. + self.config = self.root / "firmware_identity.json" # Служит единственным источником ручного номера версии. + self.generated = self.root / "build/generated" # Имитирует каталог текущей конфигурации сборки. + self.image = self.root / "board.bit" # Нативный результат ISE или Vivado. + self.config.write_text(json.dumps({"product": "Плата", "target": "test-part", "version": [1, 2, 3], "increment_version": True}), encoding="utf-8") # Не изменяет пример или настройки реальных проектов. + self.git = patch.object(fpga.shared, "git_state", return_value={"commit": None, "dirty": None}) # Без Git должен получаться явный NOGIT000. + self.git.start() # Фиксирует отсутствие Git для всех вызовов данного теста. + self.addCleanup(self.git.stop) # Восстанавливает функцию после проверки. + self.epoch = patch.dict(os.environ, {"SOURCE_DATE_EPOCH": "1792413296"}) # UTC 2026-10-19 12:34:56 позволяет проверить точные календарные слова. + self.epoch.start() # Делает дату HDL детерминированной. + self.addCleanup(self.epoch.stop) # Не меняет окружение остальных тестов. + + def prepare(self, toolchain="vivado", language="verilog"): # Вызывает публичную функцию адаптера теми же аргументами, что Tcl. + return fpga.prepare(self.root, self.config, self.generated, self.image, toolchain, language) # Делегирует резервирование версии общему prepare. + + def test_hdl_matches_contract_and_iterator(self): # Одним вектором сравнивает обе HDL-реализации с контрактом C. + metadata = self.prepare() # Первый запуск должен увеличить patch ровно один раз. + expected = [1, 1, 2, 4, 2026, 0x0A13, 0x0C22, 56, 0x4E4F, 0x4749, 0x5430, 0x3030] # 12 слов: контракт, 1.2.4, UTC и ASCII NOGIT000. + self.assertEqual(metadata["fpga"]["register_words"], expected) # Фиксирует независимый эталон адресов и старшинства октетов. + verilog = (self.generated / "firmware_identity.v").read_text(encoding="utf-8") # Читает фактически записанный файл для синтеза XST. + vhdl = (self.generated / "firmware_identity.vhd").read_text(encoding="utf-8") # Читает альтернативный VHDL-93 паспорт. + self.assertEqual([int(value, 16) for value in re.findall(r"word_data = 16'h([0-9A-F]{4})", verilog)][:12], expected) # Проверяет константы без зависимости от пробелов и комментариев. + self.assertEqual([int(value, 16) for value in re.findall(r'x"([0-9A-F]{4})" when "[01]{4}"', vhdl)], expected) # Проверяет то же расположение слов в VHDL. + self.assertEqual(json.loads(self.config.read_text(encoding="utf-8"))["version"], [1, 2, 4]) # HDL и сохраняемый счётчик обязаны совпадать. + self.assertEqual(self.prepare()["version"], [1, 2, 5]) # Следующая попытка использует следующий номер общего итератора. + + def test_seal_archive_export_and_tampering(self): # Проверяет реальную упаковку точных байтов и отказ при повреждении. + self.prepare() # Фиксирует паспорт до появления готового .bit. + data = b"test-only FPGA bitstream\x00\xff" # Произвольные байты моделируют файл программатора без разбора вендорного контейнера. + self.image.write_bytes(data) # Имитирует успешный выход полной сборки САПР. + result = fpga.finish(self.generated / "firmware_identity.json", self.root / "firmware", self.root / "export") # Запускает общий seal, verify, archive и проверку экспорта. + for folder in (Path(result["directory"]), Path(result["exported_directory"])): # Проверяет обе сохраняемые копии текущего выпуска. + self.assertEqual((folder / self.image.name).read_bytes(), data) # Архивы должны содержать точные исходные байты. + self.assertEqual((folder / "firmware_identity.v").read_bytes(), (self.generated / "firmware_identity.v").read_bytes()) # Вместе с образом сохраняется точный исходник паспорта, переданный синтезатору. + manifest = fpga.shared.verify(folder / self.image.name, folder / (self.image.name + ".manifest.json")) # Повторно считает размер и SHA-256 независимо от результата finish. + self.assertEqual(manifest["version"], [1, 2, 4]) # Post-build не увеличивает версию второй раз. + self.image.write_bytes(b"damaged") # Имитирует изменение файла после выпуска manifest. + with self.assertRaises(ValueError): # Проверка обязана обнаружить повреждение до программирования. + fpga.shared.verify(self.image, self.image.with_suffix(".bit.manifest.json")) # Использует публичную общую проверку образа. + + def test_stale_missing_and_empty_images_are_rejected(self): # Отказы сборки не должны связывать новый паспорт со старым результатом. + self.image.write_bytes(b"old image") # Оставляет нативный файл от предыдущего выпуска. + self.prepare() # Запоминает его содержимое и время до синтеза. + with self.assertRaisesRegex(ValueError, "not updated"): # Неизменившийся старый файл не считается новым выпуском. + fpga.finish(self.generated / "firmware_identity.json", self.root / "firmware") # Отказывается до создания manifest. + self.image.unlink() # Моделирует отсутствие результата после сбоя САПР. + with self.assertRaisesRegex(ValueError, "Missing or empty"): # Нет образа — нет архива. + fpga.finish(self.generated / "firmware_identity.json", self.root / "firmware") # Проверяет отсутствие файла. + self.image.write_bytes(b"") # Моделирует оборванную запись выходного файла. + with self.assertRaisesRegex(ValueError, "Missing or empty"): # Пустой файл также блокирует выпуск. + fpga.finish(self.generated / "firmware_identity.json", self.root / "firmware") # Не допускает SHA-256 пустого файла как прошивки. + self.assertFalse((self.root / "firmware").exists()) # Ни один из отказов не должен создать архив. + + def test_reproducible_image_with_new_mtime_is_accepted(self): # Ручная версия и воспроизводимый BitGen могут дать прежние байты. + self.image.write_bytes(b"same image") # Готовит существующий результат предыдущей сборки. + metadata = self.prepare() # Запоминает прежнее время записи. + stamp = metadata["fpga"]["image_before"]["mtime_ns"] + 2_000_000_000 # Две секунды покрывают даже грубую точность времени старых файловых систем. + os.utime(self.image, ns=(stamp, stamp)) # Имитирует реальную повторную запись тех же байтов. + fpga.finish(self.generated / "firmware_identity.json", self.root / "firmware") # Обновлённый файл допускается без требования отличающегося хеша. + + def test_quartus_and_wrong_extension(self): # Проверяет нативный .sof и отказы до резервирования номера. + original = self.config.read_bytes() # Неверная команда не должна увеличивать счётчик. + with self.assertRaises(ValueError): # .bit не является нативным результатом Quartus. + self.prepare(toolchain="quartus") # Проверяет соответствие расширения выбранной САПР. + self.assertEqual(self.config.read_bytes(), original) # Конфигурация остаётся прежней после отказа. + self.image = self.root / "revision.sof" # Выбирает штатный выход Assembler. + metadata = self.prepare(toolchain="quartus", language="vhdl") # Использует тот же итератор для Altera и VHDL. + self.image.write_bytes(b"test SOF") # Моделирует успешную компиляцию Quartus. + result = fpga.finish(self.generated / "firmware_identity.json", self.root / "firmware") # Архивирует .sof через общий механизм. + self.assertEqual(result["file"], "revision.sof") # Сохраняет имя ревизии программатора. + self.assertEqual(metadata["fpga"]["language"], "vhdl") # Фиксирует язык для последующего аудита. + + +if __name__ == "__main__": # Позволяет запускать проверку отдельным файлом. + unittest.main() # Возвращает ненулевой код при нарушении контракта. diff --git a/tools/firmware-build/fpga/tests/test_ise_project.py b/tools/firmware-build/fpga/tests/test_ise_project.py new file mode 100644 index 0000000..ebd7f75 --- /dev/null +++ b/tools/firmware-build/fpga/tests/test_ise_project.py @@ -0,0 +1,138 @@ +"""Проверяет автоматическую установку ISE, сохранение версии и локальные BAT.""" # Тесты не изменяют реальные .xise пользователя. +import importlib.util # Загружает установщик без вызова его интерактивного CLI. +import json # Проверяет автоматически извлечённые и сохраняемые настройки проекта. +import os # Подготавливает окружение Windows для реального запуска BAT. +from pathlib import Path # Изолирует проекты в игнорируемом каталоге репозитория. +import subprocess # Проверяет установочный BAT и установленную команду --check. +import tempfile # Создаёт независимый проект для каждой проверки. +import unittest # Проверяет успешную установку, повторные вызовы и отказы до сборки. +from unittest.mock import patch # Заменяет только внешние команды ISE в тестах запуска. +HERE = Path(__file__).resolve().parents[1] # Находит общий установщик рядом с остальными FPGA-инструментами. +SPEC = importlib.util.spec_from_file_location("ise_project_setup", HERE / "ise_project.py") # Выделяет установщику отдельное пространство имён. +ise = importlib.util.module_from_spec(SPEC) # Создаёт модуль для проверки публичных функций. +SPEC.loader.exec_module(ise) # Загружает код без запросов к пользователю и без установки в чужие каталоги. +PROJECT = ''' + + + + + + + + + + + + + +''' # Фикстура воспроизводит namespace и свойства настоящего ISE 14.7 без исходников платы. + + +class SetupTests(unittest.TestCase): # Проверяет автоматическое подключение одного проекта без ручного копирования. + def setUp(self): # Каждый сценарий получает свой рабочий каталог с пробелами и кириллицей. + scratch = HERE.parents[2] / ".codex-build" # Держит тестовые проекты внутри разрешённой области и вне индекса Git. + scratch.mkdir(exist_ok=True) # Поддерживает запуск тестов из свежей копии библиотеки. + temporary = tempfile.TemporaryDirectory(prefix="ISE setup плата & ", dir=scratch) # Амперсанд проверяет передачу путей без вставки shell-команд. + self.addCleanup(temporary.cleanup) # Удаляет только собственный тестовый проект. + self.root = Path(temporary.name) # Хранит весь созданный комплект рядом с тестовым .xise. + self.project = self.root / "board.xise" # Отличается от имени top и результата BitGen для проверки автоподбора. + self.project.write_text(PROJECT, encoding="utf-8") # Не изменяет существующие проекты на диске. + + def install(self, **arguments): # Вызывает установщик без поиска реальной САПР на каждом тесте. + with patch.object(ise, "find_settings", return_value=""): # Автоматическая установка допускается и до установки ISE. + return ise.install(self.project, **arguments) # Проверяет настоящую запись обвязок и предварительного HDL. + + def test_install_detects_project_and_does_not_consume_version(self): # Установка должна завершиться готовым локальным BAT и исходниками паспорта. + before = self.project.read_bytes() # Автоматическое подключение не должно менять XML проекта без ISE. + settings = self.install() # Извлекает параметры и создаёт локальные файлы. + self.assertEqual(settings["image"], "impl/programmer_top.bit") # Output File Name и Working Directory важнее имени .xise. + self.assertEqual(settings["language"], "verilog") # Определяет язык по реальному верхнему исходнику. + identity = json.loads((self.root / "firmware_identity.json").read_text(encoding="utf-8")) # Читает рабочий, а не временный счётчик. + self.assertEqual(identity["target"], "xc6slx16-3ftg256") # Паспорт получает реальный кристалл с корпусом и скоростной группой. + self.assertEqual(identity["version"], [0, 1, 0]) # Установка не является попыткой синтеза и не расходует номер. + self.assertEqual(self.project.read_bytes(), before) # Исходный .xise сохранён побайтно. + for name in ("build_firmware.bat", "firmware_build.py", "firmware_build.json", "FIRMWARE_SETUP.md", "firmware_identity_instance.txt", "build/ise/generated/firmware_identity.v"): # Все ранее ручные файлы создаются автоматически. + self.assertTrue((self.root / name).is_file(), name) # Проверяет полноту установленного комплекта. + self.assertIn("build/ise/", (self.root / ".gitignore").read_text(encoding="utf-8")) # Сгенерированные исходники исключаются из статуса Git проекта. + + def test_reinstall_preserves_configs_version_and_ignore(self): # Повторное подключение не должно сбросить уже выпущенный номер. + self.install() # Сначала создаёт штатный набор локальных файлов. + identity = self.root / "firmware_identity.json" # Рабочий счётчик изменяется только как часть тестового сценария. + identity.write_text('{"product":"Моя плата","target":"xc6slx16","version":[3,4,5],"increment_version":true}', encoding="utf-8") # Имитирует существующую версию и пользовательское форматирование. + config = self.root / "firmware_build.json" # Параметры установки также сохраняются при повторном запуске. + settings = json.loads(config.read_text(encoding="utf-8")) # Сохраняет автоматически определённые значения остальных полей. + settings["output"] = "build/custom" # Проект может поменять каталог архивов после установки. + config.write_text(json.dumps(settings), encoding="utf-8") # Создаёт пользовательский формат настройки. + originals = {path: path.read_bytes() for path in (identity, config)} # Проверяет побайтную сохранность обоих JSON. + self.install() # Повторный вызов должен использовать выбранный пользователем output. + for path, data in originals.items(): # Ни версия, ни пути не должны замениться значениями из .xise. + self.assertEqual(path.read_bytes(), data) # Не допускает переформатирования сохранённых настроек. + ignore = (self.root / ".gitignore").read_bytes() # Запоминает результат после добавления custom output. + self.install() # Третий вызов проверяет отсутствие повторяющихся правил. + self.assertEqual((self.root / ".gitignore").read_bytes(), ignore) # .gitignore не растёт при каждом запуске. + self.assertTrue((self.root / "build/custom/generated/firmware_identity.v").is_file()) # Предварительный HDL соответствует сохранённой настройке. + + def test_existing_user_bat_is_preserved_without_partial_installation(self): # Установщик не должен заменять существующие проектные команды. + custom = self.root / "build_firmware.bat" # Создаёт пользовательскую команду с занятым именем. + custom.write_bytes(b"@echo custom build\n") # Содержимое отличается от управляемого шаблона. + with self.assertRaisesRegex(ValueError, "Existing file differs"): # Коллизия должна быть обнаружена до записи JSON и generated. + self.install() # Выполняет настоящую предварительную проверку устанавливаемых файлов. + self.assertEqual(custom.read_bytes(), b"@echo custom build\n") # Пользовательский файл остаётся прежним. + self.assertFalse((self.root / "firmware_identity.json").exists()) # Частичная установка не создаёт рабочий счётчик. + self.assertFalse((self.root / "build").exists()) # Отказ коллизии не оставляет предварительный паспорт. + + def test_vhdl_override_and_ambiguous_or_cpld_project(self): # Поддерживает VHDL и останавливает неподходящие проекты до записи файлов. + self.project.write_text(PROJECT.replace("logic_top.v", "logic_top.vhd"), encoding="utf-8") # Расширение top имеет приоритет над Preferred Language. + project, image, language, target = ise.project_info(self.root) # Единственный .xise выбирается из переданной папки. + self.assertEqual(language, "vhdl") # Выбирает VHDL автоматически без ручного параметра. + settings = self.install(image=Path("custom/result.bit")) # Разрешает явно переопределить нестандартный путь BitGen. + self.assertEqual(settings["image"], "custom/result.bit") # Не теряет ручное уточнение при автоматическом заполнении. + self.assertIn("component firmware_identity", (self.root / "firmware_identity_instance.txt").read_text(encoding="utf-8")) # Выдаёт VHDL-заготовку для подключения до первого синтеза. + (self.root / "other.xise").write_text(PROJECT, encoding="utf-8") # Моделирует две платы в одной папке. + with self.assertRaisesRegex(ValueError, "exactly one"): # Установщик не должен угадывать нужную плату. + ise.project_info(self.root) # Требует явный файл .xise. + self.project.write_text(PROJECT.replace("xc6slx16", "xc9572xl"), encoding="utf-8") # CPLD требует .jed вместо .bit. + with self.assertRaisesRegex(ValueError, "FPGA project"): # Неподходящий FPGA-шаблон не устанавливается на CPLD. + ise.project_info(self.project) # Проверяет устройство до любых изменений проекта. + + def test_build_preserves_arguments_exit_code_and_check_version(self): # Локальная настройка должна доходить до общего Tcl отдельными аргументами. + self.install() # Готовит настоящий набор настроек и исходную версию. + config = self.root / "firmware_build.json" # Выбирает установленную локальную настройку. + version = (self.root / "firmware_identity.json").read_bytes() # --check не имеет права занимать следующий номер. + with patch.object(ise, "ise_environment", return_value={"PATH": "test"}), patch.object(ise.shutil, "which", return_value="C:/ISE path/xtclsh.exe"), patch.object(ise.subprocess, "call", return_value=7) as invoke: # Не запускает лицензируемую САПР в тесте аргументов. + self.assertEqual(ise.build(config, check=True), 0) # Проверка должна завершиться до запуска Tcl-flow. + invoke.assert_not_called() # Подтверждает отсутствие скрытой сборки в --check. + self.assertEqual(ise.build(config), 7) # Код ошибки САПР передаётся пользователю без подмены. + arguments = invoke.call_args.args[0] # Каждый элемент списка соответствует одному аргументу процесса. + self.assertEqual(arguments[2], str(self.project)) # Пробелы, кириллица и амперсанд сохраняются в пути .xise. + self.assertEqual(arguments[-2], "verilog") # Общий Tcl получает выбранный при установке язык. + self.assertEqual(invoke.call_args.kwargs["cwd"], self.root) # Относительные исходники .xise разрешаются из папки проекта. + self.assertEqual((self.root / "firmware_identity.json").read_bytes(), version) # До настоящего pre-build номер не изменяется. + + @unittest.skipUnless(os.name == "nt", "Windows BAT execution") # Реальные BAT проверяются только на Windows, остальные тесты переносимы. + def test_native_settings_environment_preserves_unicode(self): # Автоматическое окружение должно сохранить пути при любой кодовой странице консоли. + settings = self.root / "settings64.bat" # Путь содержит пробелы, кириллицу и амперсанд. + settings.write_bytes('@echo off\r\n@rem Передаёт переменную с русским путём из исходного окружения.\r\n@set "ISE_TEST_RESULT=%FW_TEST_UNICODE%"\r\n'.encode("utf-8")) # Моделирует штатный settings.bat без настоящей установки ISE. + expected = str(self.root / "русская папка") # Результат не должен зависеть от OEM-кодировки Windows. + with patch.dict(os.environ, {"FW_TEST_UNICODE": expected}), patch.object(ise.shutil, "which", return_value=None): # Принуждает настройку окружения через settings.bat. + environment = ise.ise_environment({"ise_settings": str(settings)}) # Исполняет настоящий CMD /u с захватом SET. + self.assertEqual(environment["ISE_TEST_RESULT"], expected) # Декодирование UTF-16LE должно сохранить каждый символ пути. + + @unittest.skipUnless(os.name == "nt", "Windows BAT execution") # Реальный запуск обвязок требует командного процессора Windows. + def test_real_installer_and_local_bat_check(self): # Проверяет запуск пользователем без ручного копирования файлов или длинной Tcl-команды. + environment = os.environ.copy() # Наследует Python launcher и стандартные системные программы. + environment["FW_NO_PAUSE"] = "1" # Автотест не должен ожидать клавиши установщика. + setup = subprocess.run([environment.get("COMSPEC", "cmd.exe"), "/d", "/c", "call", str(HERE / "INSTALL_ISE.bat"), str(self.project)], env=environment, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # CALL сохраняет кавычки имени BAT; аргумент проекта содержит пробелы и амперсанд. + self.assertEqual(setup.returncode, 0, setup.stderr.decode(errors="replace")) # Файлы должен создать сам установщик. + stub = self.root / "stub bin" # Создаёт отдельный PATH для проверки наличия xtclsh. + stub.mkdir() # Не подменяет системную установку ISE. + (stub / "xtclsh.bat").write_text("@rem Только маркер наличия ISE для --check.\n@exit /b 99\n", encoding="utf-8") # Проверка не должна выполнять эту заглушку. + environment["PATH"] = str(stub) + os.pathsep + environment.get("PATH", "") # Добавляет тестовую САПР перед остальными программами. + before = (self.root / "firmware_identity.json").read_bytes() # Сохраняет номер перед запуском установленного BAT. + run = subprocess.run([environment.get("COMSPEC", "cmd.exe"), "/d", "/c", "call", str(self.root / "build_firmware.bat"), "--check"], cwd=HERE, env=environment, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Рабочий каталог специально отличается от каталога проекта; CALL сохраняет кавычки пути BAT. + self.assertEqual(run.returncode, 0, run.stderr.decode(errors="replace")) # Локальная Python-обвязка должна найти настройку и библиотеку самостоятельно. + self.assertEqual((self.root / "firmware_identity.json").read_bytes(), before) # Проверка установленного комплекта не увеличивает версию. + + +if __name__ == "__main__": # Поддерживает прямой запуск тестов установщика. + unittest.main() # Возвращает ненулевой код при ошибке установки или потере настроек. diff --git a/tools/firmware-build/fpga/vivado.tcl b/tools/firmware-build/fpga/vivado.tcl new file mode 100644 index 0000000..91d403f --- /dev/null +++ b/tools/firmware-build/fpga/vivado.tcl @@ -0,0 +1,56 @@ +# Находит общий код независимо от рабочего каталога Vivado. +source [file join [file dirname [info script]] common.tcl] +# Объединяет запуск и контроль результата в одну прерываемую при ошибке операцию. +if {[catch { + # Принимает project.xpr, config.json, output, top.bit, язык и необязательный python.exe. + fw::init $argv vivado + # Открывает проект с его part, top, XDC и настройками реализации. + open_project $fw::settings(project) + # Берёт активную реализацию, а не предполагает стандартное имя impl_1. + set implementation [current_run -implementation] + # Синтез выбирается по родителю реализации, даже если в GUI активен другой synth run. + set synthesis [get_property PARENT $implementation] + # Файловый набор принадлежит именно синтезу выбранной реализации. + set sources [get_property SRCSET [get_runs $synthesis]] + # Генерирует паспорт до запуска синтеза; повторное увеличение в hooks проекта не требуется. + fw::prepare + # Регистрирует только один вариант HDL в правильном наборе исходников. + add_files -fileset $sources -norecurse $fw::settings(hdl) + # Обновляет порядок компиляции для нового модуля или VHDL entity. + update_compile_order -fileset $sources + # Сбрасывает реализацию перед синтезом, чтобы не использовать прежнюю размещённую схему. + reset_run $implementation + # Полный синтез обязателен при новом паспорте даже в ручном режиме номера версии. + reset_run $synthesis + # Запускает синтез с настройками проекта. + launch_runs $synthesis + # Ожидает завершения дочернего процесса до проверки результата. + wait_on_run $synthesis + # Ожидание само по себе не означает успех; 100% проверяется отдельно. + if {[get_property PROGRESS [get_runs $synthesis]] ne "100%"} { + # Не запускает реализацию при отказе синтеза. + error "Vivado synthesis failed" + # Заканчивает проверку синтеза. + } + # Включает write_bitstream, который обычная реализация по умолчанию не выполняет. + launch_runs $implementation -to_step write_bitstream + # Ждёт записи .bit перед вызовом общего post-build. + wait_on_run $implementation + # Проверяет завершение полной цепочки генерации файла программирования. + if {[get_property PROGRESS $implementation] ne "100%"} { + # Отказ маршрутизации, DRC или BitGen блокирует архивирование. + error "Vivado implementation/bitstream failed" + # Завершает проверку реализации. + } + # Упаковывает именно ожидаемый .bit после успешной сборки. + fw::finish + # Завершает работу с сохранёнными настройками проекта. + close_project +# Ошибка любого шага передаётся внешнему вызывающему процессу. +} message]} { + # Сохраняет исходное сообщение САПР или общего генератора в журнале. + puts stderr $message + # Возвращает отказ внешней сборке или CI. + exit 1 +# Заканчивает обработку ошибок. +} diff --git a/tools/firmware-build/keil/firmware_identity.example.json b/tools/firmware-build/keil/firmware_identity.example.json index 7767f6d..cf7b225 100644 --- a/tools/firmware-build/keil/firmware_identity.example.json +++ b/tools/firmware-build/keil/firmware_identity.example.json @@ -1,5 +1,6 @@ { "product": "MY_CONTROLLER", "target": "STM32F407", - "version": [0, 1, 0] + "version": [0, 1, 0], + "increment_version": true }