15 Commits

Author SHA1 Message Date
dce9dd41a4 Использовать общий итератор версии прошивки
Убрать повторное увеличение версии из проектной обёртки.
Проверять прямое подключение templates и вызов через обёртку в CCS.
Сохранить текущий номер прошивки 1.0.5 и уточнить документацию.
2026-10-19 12:02:08 +03:00
31f92e89d9 Обновить сборку прошивки 166, TESTLAMP и кодировку исходников
Перенести настройки выпуска в JSON, добавить переносимый сценарий сборки и проверки BIN. Обновить конфигурации CCS, исходники в UTF-8, обработку TESTLAMP, образы прошивки и регрессионные проверки.
2026-10-17 14:36:59 +03:00
13f1a2c5fd Добавить heartbeat и передачу CAN по изменению и таймеру
Для всех Mode передавать пакеты при обновлении данных и повторять каждый через 1300 мс от последнего CAN ACK. Отдельно отправлять heartbeat раз в секунду. Сохранить маски рассылки, отключение потоков нулевым периодом и неблокирующее восстановление после ошибок TX.

Проверены границы периодов, все Mode, занятый mailbox, отмена без CANAA, отсутствие ACK, переполнение Timer1, первый снимок и справедливость потоков. Изменённые модули ecan.c и main.c скомпилированы компилятором TI C2000.
2026-10-16 23:17:00 +03:00
345c81166e Добавить блочное чтение EEPROM в прошивку 166
Перенести контракт FC03 из 167: до 120 слов за запрос, проверка границ окна и точная длина ответа с CRC. Использовать существующий буфер UART и разрешённые прерывания SPI. Проверить полный дамп из 137 блоков и сохранение прежних маршрутов Modbus и CAN.
2026-10-16 22:50:25 +03:00
7713ff7573 Сохранить образы 166 с проверяемым паспортом прошивки
Образы собраны из fe95dbf: версия 1.0.0, идентификатор fe95dbf+, размер BIN 30248 байт. Паспорт, манифест и SHA256 проверены штатным декодером SetGUI. Проверка на физической плате не выполнялась.
2026-10-16 14:53:02 +03:00
fe95dbff3d Перенести паспорт и проверку прошивки из 167 в 166
Добавить неизменяемое окно firmware-info v1 0x1200 из 12 слов для FC03 и служебного CAN, запретить запись. Сохранить текущую технологическую карту и логгер v4 с записью 12 слов.

Подключить общий генератор версии 1.0.0 для Balsam-166-PM35, prebuild CCS и локальный выпуск BIN с manifest и SHA-256. Проверять соответствие встроенных слов манифесту до публикации; старый OUT без паспорта отклонять.

Проверка: реальные обработчики RS/CAN и CRC под GCC O3, прежний тест логгера, анализатор установленного SetGUI, полная сборка TI C2000 22.6.0.LTS. BIN 30248 байт при границе параметров 32508 байт. Аппаратная проверка требует установки нового образа и перезапуска платы.
2026-10-16 12:05:44 +03:00
001ade4b20 Исключить временные сборки и генерируемую документацию из Git
Добавить исключения для локальных проверок, Doxygen, HTML-документации, Release CCS, кэшей Python и pytest, новых карт памяти, паспортов BIN и экспериментальных Flash-образов.

Проверка: 571 временный файл больше не попадает в список изменений; файлы сохранены на диске.
2026-10-16 11:42:22 +03:00
8427827247 Сохранить подготовленные образы прошивки 166 и карту памяти
Зафиксировать имеющиеся в рабочем каталоге HEX, OUT и карту памяти отдельным коммитом от исходников и настроек CCS. Повторная сборка и аппаратные испытания в рамках этой фиксации не выполнялись.
2026-10-16 11:42:21 +03:00
3e69aab967 Настроить подключение отладчика в CCS
Выбрать SAU510USBIsoPlusV2 и автоматическую настройку цели. Сохранить обновлённые CCS подписи опций без изменения их значений.

Проверка: оба XML-файла успешно разобраны, текст сохранён в UTF-8.
2026-10-16 11:42:21 +03:00
b0c1667523 Установить секундный период медленной рассылки CAN по умолчанию
Уменьшить делитель Cancount[m_SLOW] со 101 до 50. При базовом интервале CANPOWSE 20 мс это соответствует примерно одной секунде; загруженные параметры EEPROM сохраняют приоритет.
2026-10-16 11:42:21 +03:00
29a191be56 Сохранить проверенные образы прошивки 166 с компактным логгером 2026-10-16 11:27:02 +03:00
22eb4ce243 Увеличить период передачи кнопок пульта по CAN до 200 мс 2026-10-16 11:26:45 +03:00
4635f00a20 Выбрать исполнение 166 и исправить обратный порядок индикаторов 2026-10-16 11:26:29 +03:00
1955f2c98f Сократить запись логгера УМП до 12 слов формата v4 2026-10-16 11:26:14 +03:00
ba9a54959e Исправить фильтрацию TESTLAMP и показать заголовки в CCS 2026-10-16 10:15:09 +03:00
68 changed files with 2408 additions and 994 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
# Windows cmd.exe должен получать BAT с CRLF: русские комментарии в UTF-8 при одних LF могут нарушать разбор строк команд.
*.bat text eol=crlf

20
.gitignore vendored
View File

@@ -6,3 +6,23 @@
/UKSSTMS320F28335.paf2 /UKSSTMS320F28335.paf2
/UKSSTMS320F28335.sbl /UKSSTMS320F28335.sbl
/Bin/UKSSTMS320F28335_*.bin /Bin/UKSSTMS320F28335_*.bin
# Локальные разовые проверки, резервные копии и экспериментальные результаты сохраняются вне истории исходников.
/.ui_patch/
# Кэш pytest создаётся повторно при запуске тестов и не является частью прошивки.
/.pytest_cache/
# Загруженные исполняемые файлы и зависимости Doxygen остаются локальными инструментами.
/Doc/.tools/
# HTML, JavaScript и журналы генерации документации восстанавливаются из исходников.
/Doc/build/
# Каталог Release этого CCS-проекта содержит генерируемые make-файлы и объектные файлы.
/UKSSTMS320F28335/Release/
# Скомпилированный кэш Python восстанавливается автоматически и не содержит самостоятельных исходников.
__pycache__/
# Новые карты памяти формируются линкером; уже отслеживаемые карты остаются в истории.
/Bin/*.map
# Паспорт сопровождает генерируемый BIN и сохраняется рядом с ним в локальном выпуске.
/Bin/*.bin.manifest.json
# Контрольная сумма относится к конкретному генерируемому BIN и не является исходным файлом.
/Bin/*.bin.sha256
# Именованные экспериментальные Flash-варианты сохраняются локально; основные отслеживаемые OUT остаются в истории.
/Bin/UKSSTMS320F28335_flash_*.out

Binary file not shown.

View File

@@ -1,9 +1,9 @@
******************************************************************************** ********************************************************************************
TMS320C2000 Hex Converter v5.2.7 TMS320C2000 Hex Converter v22.6.0
******************************************************************************** ********************************************************************************
INPUT FILE NAME: <c:\Temp\166-sifu-build-vq3o6iha\UKSSTMS320F28335.out> INPUT FILE NAME: <K:\git_project\28335_periph\Bin\UKSSTMS320F28335.out>
OUTPUT FORMAT: Binary OUTPUT FORMAT: Intel
PHYSICAL MEMORY PARAMETERS PHYSICAL MEMORY PARAMETERS
Default data width : 16 Default data width : 16
@@ -12,22 +12,22 @@ PHYSICAL MEMORY PARAMETERS
BOOT LOADER PARAMETERS BOOT LOADER PARAMETERS
Table Type: SERIAL PORT (SCI 8 bit Mode) Table Type: SERIAL PORT (SCI 8 bit Mode)
Entry Point: 0x0000b56a Entry Point: 0x0000b7bc
OUTPUT TRANSLATION MAP OUTPUT TRANSLATION MAP
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
00000000..003fffff Page=0 Memory Width=8 ROM Width=8 00000000..ffffffff Page=0 Memory Width=8 ROM Width=8
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
OUTPUT FILES: c:\Temp\166-sifu-build-vq3o6iha\UKSSTMS320F28335.bin [b0..b7] OUTPUT FILES: K:\git_project\28335_periph\UKSSTMS320F28335\Debug\.identity-release-018w5cqu\.firmware-7iwzourf\UKSSTMS320F28335.hex [b0..b7]
CONTENTS: 00000000..000075d5 BOOT TABLE CONTENTS: 00000000..00007aa3 BOOT TABLE
.cinit : dest=0000b717 size=00000262 width=00000002 .cinit : dest=0000b969 size=0x26b width=00000002
.text : dest=00008000 size=00003717 width=00000002 .text : dest=00008000 size=0x3969 width=00000002
.econst : dest=0000c000 size=00000112 width=00000002 .econst : dest=0000c000 size=0x11e width=00000002
.switch : dest=0000c112 size=00000048 width=00000002 .switch : dest=0000c11e size=0x48 width=00000002
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
00000000..003fffff Page=1 Memory Width=8 ROM Width=8 "*DEFAULT PAGE 1*" 00000000..ffffffff Page=1 Memory Width=8 ROM Width=8 "*DEFAULT PAGE 1*"
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
NO CONTENTS NO CONTENTS

Binary file not shown.

View File

@@ -2,7 +2,7 @@
Текущая логика дискретов описана в [SIFU_START_STOP.md](SIFU_START_STOP.md): Текущая логика дискретов описана в [SIFU_START_STOP.md](SIFU_START_STOP.md):
CAN-фронты обрабатываются при приёме, импульсы снимаются таймером, STOP CAN-фронты обрабатываются при приёме, импульсы снимаются таймером, STOP
имеет приоритет. Формат записи v2 и интерфейс SetGUI сохранены. имеет приоритет. Компактный формат записи v4 совпадает с исполнением 167.
## Назначение и работа оператора ## Назначение и работа оператора
@@ -13,8 +13,9 @@ CAN-фронты обрабатываются при приёме, импуль
Общий RS-адрес 16 здесь не рекомендуется: ответ содержит собственный адрес, Общий RS-адрес 16 здесь не рекомендуется: ответ содержит собственный адрес,
и SetGUI проверяет совпадение адресов. CAN-настройки: [PERIPH28335_CAN.md](PERIPH28335_CAN.md). и SetGUI проверяет совпадение адресов. CAN-настройки: [PERIPH28335_CAN.md](PERIPH28335_CAN.md).
Перенесён протокол v2 из 167: 40 слов на запись, два банка по 800 записей. Используется формат v4 из 167: 12 слов на запись вместо прежних 40;
Существующий SetGUI понимает эту прошивку без изменений программы. ёмкость исполнения 166 сохранена — два банка по 800 записей.
Для чтения нужен SetGUI с поддержкой компактного формата v4, как для 167.
Кнопки записи управляют регистратором; команду запуска УМП подаёт контроллер. Кнопки записи управляют регистратором; команду запуска УМП подаёт контроллер.
1. **Начать запись** включает только регистратор, не пуск УМП. 1. **Начать запись** включает только регистратор, не пуск УМП.
@@ -45,7 +46,8 @@ EEPROM не используется: под отключением в этой
## Память и точность ## Память и точность
Использована существующая секция `.logg` по адресу 0x200000: 64000 Использована существующая секция `.logg` по адресу 0x200000: 64000
16-битных слов. Два банка по 800 записей × 40 слов занимают её целиком. 16-битных слов. Два банка по 800 записей × 12 слов используют 19200 слов;
размер выделенной секции сохранён. Одна запись занимает 24 байта вместо 80.
Текущий банк кольцевой. При триггере сохраняются последние до 399 записей, Текущий банк кольцевой. При триггере сохраняются последние до 399 записей,
добавляется событие отключения, оставшаяся половина банка отведена добавляется событие отключения, оставшаяся половина банка отведена
постинтервалу. При 20 мс это до примерно 8 секунд до отключения и 1 секунды постинтервалу. При 20 мс это до примерно 8 секунд до отключения и 1 секунды
@@ -61,7 +63,7 @@ EEPROM не используется: под отключением в этой
одинаковую отметку; порядок сохраняется порядком записей. На перезапуске одинаковую отметку; порядок сохраняется порядком записей. На перезапуске
регистратора счётчик продолжает прежнюю шкалу, при перезагрузке платы — 0. регистратора счётчик продолжает прежнюю шкалу, при перезагрузке платы — 0.
Онлайн-опрос возвращает три последних записи каждые 40 мс. Он не гарантирует Онлайн-опрос возвращает до десяти последних записей каждые 40 мс. Он не гарантирует
передачу каждого события при высоком CAN-трафике, медленном UART или паузах передачу каждого события при высоком CAN-трафике, медленном UART или паузах
GUI. Номера записей позволяют убрать дубликаты и явно показать пропуски. GUI. Номера записей позволяют убрать дубликаты и явно показать пропуски.
Полный сохранившийся фрагмент следует читать кнопкой архива. Частота 20 мс Полный сохранившийся фрагмент следует читать кнопкой архива. Частота 20 мс
@@ -73,7 +75,12 @@ GUI. Номера записей позволяют убрать дублика
EEPROM, выделения памяти или копирования целого банка. Реальную задержку EEPROM, выделения памяти или копирования целого банка. Реальную задержку
прерываний и длительность критических секций нужно измерить на F28335. прерываний и длительность критических секций нужно измерить на F28335.
## Состав записи: 40 слов ## Состав записи v4: 12 слов
Состав и позиции полей совпадают с компактным логгером 167. Убраны сырые
данные АЦП и CAN, ошибки, счётчики, код и калибровки ЦАП, состояние разгона
и прочие дополнительные диагностические поля. Управление нагрузкой 166,
ёмкость банка и секундный постинтервал отключения сохранены.
| Слова | Данные | Единицы/смысл | | Слова | Данные | Единицы/смысл |
|---|---|---| |---|---|---|
@@ -81,33 +88,21 @@ EEPROM, выделения памяти или копирования целог
| 2 | Событие | 1 период, 2 CAN RX, 3 изменение I/O, 4 RS-команда, 5 конец постинтервала | | 2 | Событие | 1 период, 2 CAN RX, 3 изменение I/O, 4 RS-команда, 5 конец постинтервала |
| 2, бит 8 | Триггер отключения | флаг поверх причины события | | 2, бит 8 | Триггер отключения | флаг поверх причины события |
| 2, бит 9 | Усечён постинтервал | установлен в конечном снимке | | 2, бит 9 | Усечён постинтервал | установлен в конечном снимке |
| 3 | Commands / modbus[0x7F] | все 16 бит, в том числе пуск, сброс, инициализация и калибровка ЦАП | | 3 | Commands & 0xC0 | только пуск УМП (бит 7) и сброс УМП (бит 6) |
| 4 | Входы OMEGA, Start_1, Res_in | биты 0,1,2, активный уровень приведён к 1 | | 4 | Входы OMEGA, Start_1, Res_in | биты 0,1,2, активный уровень приведён к 1 |
| 5 | START_DPTB, STOP_DPTB, RES_OUT_2 | биты 0,1,2, активный уровень приведён к 1 | | 5 | START_DPTB, STOP_DPTB, RES_OUT_2 | биты 0,1,2, активный уровень приведён к 1 |
| 6 | IMPowse | остаток импульса, мс | | 6 | modbus[0x1C] | расчётное задание в 0.1 мА; GUI/CSV переводит в мА |
| 7 | WAKEpowse | остаток инициализации, тики DAC_FREQ | | 7–8 | Фиксированные начальная и конечная уставки 166 | 6 и 16 мА; это не регистры настройки |
| 8 | modbus[0x7B] | 12-битный код, переданный функцией dSEND в ЦАП | | 9 | ЗПТ1: U1 + U2 | ПМ67, регистр 306 / нулевой CAN-индекс 305, В |
| 9 | modbus[0x1C] | расчётное задание в 0.1 мА; GUI/CSV переводит в мА | | 10 | ЗПТ2: U3 + U4 | ПМ67, регистр 9 / нулевой CAN-индекс 8, В |
| 10–13 | sens_data[0..3] | измеренные сигналы, знаковое 16-битное значение в исходном масштабе | | 11 | Резерв | всегда ноль; чётная длина нужна для парной передачи CAN |
| 14–17 | modbus[0..3] | маски ошибок измерений |
| 18 | CAN заголовок | адрес регистра в младших 13 битах и маска трёх слов в старших |
| 19–21 | Три слова последнего принятого CAN-кадра | без преобразования |
| 22 | Счётчик записанных CAN RX | младшие 16 бит |
| 23 | CanTimeOutErrorTR | младшие 16 бит счётчика тайм-аутов CAN TX |
| 24–25 | Фиксированные границы разгона 166 | 6 и 16 мА; это не регистры настройки |
| 26–28 | DAC_min(), DAC_max(), DAC_cal() | коды калибровки и ручного задания ЦАП |
| 29–30 | DAC_04, DAC_20 | значения соответствующих регистров |
| 31–32 | count_load, time_dac | положение и длительность разгона в тиках |
| 33–34 | Эффективные границы разгона 166 | 60 и 160 в 0.1 мА; GUI показывает 6 и 16 мА |
| 35 | kod | целочисленное положение, используемое Anal_output |
| 36–39 | adc_table_lem[0..3] | ADCRESULT2..5 после сдвига на 4, диапазон 0..4095 |
**Отправленный код ЦАП не является измеренным током выхода.** В этом проекте **Расчётное задание тока не является измеренным током выхода.** При включённом
не установлено, какой вход аппаратно измеряет ток ЦАП. При включённом
`cCalibrDac` отправляется `DAC_cal()`, а расчётное задание 0x1C остаётся `cCalibrDac` отправляется `DAC_cal()`, а расчётное задание 0x1C остаётся
результатом алгоритма разгона. Для диагностики это различие сохранено. результатом алгоритма разгона. Сырой код ЦАП и каналы АЦП в запись v4 не входят.
В 166 каналы «АЦП 0..3» берутся из `adc_table_lem`, обновляемой в режиме Напряжения обновляются по подтверждённым маской словам CAN даже при остановленной
нагрузки. Таблица `adc_table_tpl` в этом режиме не обновляется и не используется. записи: первый снимок содержит последние принятые значения. До первого приёма
они равны нулю; отдельного флага свежести в формате v4 нет.
Управляющая формула 166 сохранена: `sinus = 10/16 * count_load + 2/16 * time_dac`. Управляющая формула 166 сохранена: `sinus = 10/16 * count_load + 2/16 * time_dac`.
Регулируемый разгон и ограничители 167 не переносились. Поля границ показывают Регулируемый разгон и ограничители 167 не переносились. Поля границ показывают
@@ -128,9 +123,9 @@ FC03, 0x1000, 16 слов:
| Смещение | Значение | | Смещение | Значение |
|---|---| |---|---|
| 0,1 | 0x554D, версия 2 | | 0,1 | 0x554D, версия 4 |
| 2,3 | состояние и число записей выбранного источника | | 2,3 | состояние и число записей выбранного источника |
| 4,5 | 40 слов в записи, 800 записей в банке | | 4,5 | 12 слов в записи, 800 записей в банке |
| 6 | период периодических снимков, мс | | 6 | период периодических снимков, мс |
| 7,8 | счётчик времени, младшее/старшее слово | | 7,8 | счётчик времени, младшее/старшее слово |
| 9,10 | Desk (требуется 6 / dsk_LOAD), Mode | | 9,10 | Desk (требуется 6 / dsk_LOAD), Mode |
@@ -148,15 +143,17 @@ FC06:
- 0x1002: хронологический индекс первой записи окна 0..799; - 0x1002: хронологический индекс первой записи окна 0..799;
- 0x1003: источник окна, 0 — текущий остановленный банк, 1 — архив отключения. - 0x1003: источник окна, 0 — текущий остановленный банк, 1 — архив отключения.
FC03, 0x1010, до 120 слов: окно до трёх записей от установленного индекса. FC03, 0x1010, до 120 слов: окно до десяти записей от установленного индекса.
Для CAN длина должна быть кратна 12 словам: 12, 24, ..., 120; прежние
блоки v2 по 40 или 80 слов отклоняются как обрывающие компактную запись.
Чтение текущего банка этим окном во время записи не выдаёт изменяющиеся Чтение текущего банка этим окном во время записи не выдаёт изменяющиеся
данные. GUI сначала останавливает его; архив можно читать при работающем данные. GUI сначала останавливает его; архив можно читать при работающем
текущем банке. После всех блоков GUI повторно проверяет поколение архива; текущем банке. После всех блоков GUI повторно проверяет поколение архива;
при замене во время чтения результат не подменяет предыдущий график. при замене во время чтения результат не подменяет предыдущий график.
FC03, 0x1100, ровно 124 слова: онлайн-блок. Слова 0,1 — 32-битный номер FC03, 0x1100, ровно 124 слова: онлайн-блок. Слова 0,1 — 32-битный номер
первой записи, 2 — число записей 0..3, 3 — поколение архива, далее до трёх первой записи, 2 — число записей 0..10, 3 — поколение архива, далее до десяти
записей по 40 слов. Неиспользованные слова равны нулю. Окно онлайн не записей по 12 слов. Неиспользованные слова равны нулю. Окно онлайн не
зависит от курсора/выбора архива. Разделение 0x1010 и 0x1100 предотвращает зависит от курсора/выбора архива. Разделение 0x1010 и 0x1100 предотвращает
пересечение двух окон. пересечение двух окон.
@@ -167,7 +164,19 @@ CRC и разбор стандартного ответа GUI использую
## Проверка и запуск ## Проверка и запуск
Перенесены регистратор и RS/CAN-доступ из коммитов 167 `df71922` и `a3633d8`. Для компактного формата v4 пройден host-тест настоящего `log_to_mem.c`
с MSVC 14.30.30705. Модули `log_to_mem.c`, `ecan.c` и `message.c`
скомпилированы TI C2000 22.6.0.LTS с COFF, FPU32 и O1 без ошибок.
После выбора исполнения 166 и периода CAN пульта 200 мс выполнена независимая
компиляция всех 27 C/ASM-модулей и линковка TI C2000 22.6.0.LTS с COFF,
FPU32 и O1. Загрузочный SCI8-образ занимает 30036 байт и побайтно совпадает
с образом, полученным из сохранённого `Bin/UKSSTMS320F28335.out`.
Проверено соответствие сохранённого HEX этому OUT. Сохранились пять
предупреждений в существующих `measure.c` и `peripher.c`; на плате не проверено.
Первоначально регистратор и RS/CAN-доступ перенесены из коммитов 167
`df71922` и `a3633d8`. Приведённые ниже результаты полной сборки относятся
к исходному формату v2 до сокращения полей.
Сборка всех 27 C/ASM-файлов и линковка TI C2000 22.6.1.LTS (Debug, COFF, Сборка всех 27 C/ASM-файлов и линковка TI C2000 22.6.1.LTS (Debug, COFF,
FPU32, O1) прошли. Остались шесть прежних предупреждений в measure.c/peripher.c. FPU32, O1) прошли. Остались шесть прежних предупреждений в measure.c/peripher.c.
В MAP: RAML0 занято 0x38D1 из 0x4000 слов, .ebss — 0xFA9 из 0x3000, В MAP: RAML0 занято 0x38D1 из 0x4000 слов, .ebss — 0xFA9 из 0x3000,
@@ -176,8 +185,10 @@ FPU32, O1) прошли. Остались шесть прежних предуп
Сборка проверки лежит вне репозитория, штатные файлы Bin не заменены. Сборка проверки лежит вне репозитория, штатные файлы Bin не заменены.
Host-тест компилирует настоящий log_to_mem.c с подменой GPIO/IRQ. Host-тест компилирует настоящий log_to_mem.c с подменой GPIO/IRQ.
Проверяет кольцо, архив, переполнение постинтервала, онлайн-окно, CAN-протокол, Проверяет кольцо, архив, переполнение постинтервала, онлайн-окно из десяти
готовность именно 166, фиксированные границы и четыре канала АЦП. 12-словных записей, CAN-протокол v4, готовность именно 166, фиксированные
уставки 6/16 мА, маску команд и получение ЗПТ из трёх позиций CAN-кадра.
Сторожевые значения контролируют границу записи и разделение банков.
Запуск из корня 166: `py -3 tests/ump_logger/run_test.py` (Clang/lld или MSVC Запуск из корня 166: `py -3 tests/ump_logger/run_test.py` (Clang/lld или MSVC
в PATH); при необходимости передать `--compiler "полный путь к cl.exe"`. в PATH); при необходимости передать `--compiler "полный путь к cl.exe"`.
Тест не проверяет физические GPIO, тайминги прерываний и 16-битную ABI TI. Тест не проверяет физические GPIO, тайминги прерываний и 16-битную ABI TI.
@@ -186,7 +197,7 @@ Host-тест компилирует настоящий log_to_mem.c с подм
начать запись → подать CAN-пуск → подать отключение → через секунду прочитать начать запись → подать CAN-пуск → подать отключение → через секунду прочитать
архив. Сверить START/STOP с физическими выходами и измерениями, повторить с архив. Сверить START/STOP с физическими выходами и измерениями, повторить с
разрывом RS/CAN. Проверить период 1 мс и задержки IRQ под нагрузкой. разрывом RS/CAN. Проверить период 1 мс и задержки IRQ под нагрузкой.
Тесты существующего SetGUI (`test_ump_logger.py`, `test_ump_logger_can.py`, Для первоначального формата v2 тесты SetGUI (`test_ump_logger.py`, `test_ump_logger_can.py`,
`test_periph28335_tab.py`) в окружении Qt 5: **47 passed**. Проверены протокол, `test_periph28335_tab.py`) в окружении Qt 5: **47 passed**. Проверены протокол,
онлайн/архив, CAN-фрагменты, графики, курсоры и CSV. онлайн/архив, CAN-фрагменты, графики, курсоры и CSV.
Проверка на устройстве не выполнялась. Проверка на устройстве не выполнялась.

View File

@@ -1,8 +1,8 @@
/* Íàñòðîéêà ÀÖÏ è îáðàáîòêà àíàëîãîâûõ âûáîðîê. adc_isr îáíîâëÿåò /* Настройка АЦП и обработка аналоговых выборок. adc_isr обновляет
* adc_table_lem[0..3] èç ADCRESULT2..5 >> 4 è âûçûâàåò ðàñ÷¸ò èçìåðåíèé. * adc_table_lem[0..3] из ADCRESULT2..5 >> 4 и вызывает расчёт измерений.
* READY â 166 ÿâëÿåòñÿ ñ÷¸ò÷èêîì äî íóëÿ, íå ôëàãîì ãîòîâíîñòè. * READY в 166 является счётчиком до нуля, не флагом готовности.
* WAKE çàäà¸ò îòäåëüíîå âðåìÿ óñòàíîâëåíèÿ èçìåðèòåëüíûõ öåïåé. * WAKE задаёт отдельное время установления измерительных цепей.
* Íå äîáàâëÿòü îæèäàíèÿ EEPROM/UART â îáðàáîò÷èê âûáîðîê. * Не добавлять ожидания EEPROM/UART в обработчик выборок.
*/ */
#include "DSP2833x_Device.h" // DSP281x Headerfile Include File #include "DSP2833x_Device.h" // DSP281x Headerfile Include File
#include "DSP2833x_Examples.h" // DSP281x Examples Include File #include "DSP2833x_Examples.h" // DSP281x Examples Include File
@@ -21,7 +21,7 @@
#include "peripher.h" #include "peripher.h"
Uint16 adc_table_lem[4]; Uint16 adc_table_lem[4];
Uint16 adc_table_tpl[28]; // Ïîòîìó ÷òî +4 êàëèáð Uint16 adc_table_tpl[28]; // Потому что +4 калибр
unsigned long COUNT_WAIT_ONE_CANAL; unsigned long COUNT_WAIT_ONE_CANAL;
@@ -63,12 +63,12 @@ void setup_adc()
{ {
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x0005; // Setup 2 conv's on SEQ1 AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x0005; // Setup 2 conv's on SEQ1
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x3; // òåìïåðàòóðà (êîòîðîé íåò) AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x3; // температура (которой нет)
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // îìåãà AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // омега
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x5; // íàïðóãà 1 AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x5; // напруга 1
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x4; // íàïðóãà 2 AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x4; // напруга 2
AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x7; // òîê 1 AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x7; // ток 1
AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x2; // òîê 2 AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x2; // ток 2
} }
if(Desk==dsk_BKST) if(Desk==dsk_BKST)
@@ -82,7 +82,7 @@ void setup_adc()
if(Desk==dsk_COMM) if(Desk==dsk_COMM)
{ {
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x0006; // Setup 2 conv's on SEQ1 AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x0006; // Setup 2 conv's on SEQ1
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x5; // ñíà÷àëà òîæå áóäóò òåìïåðàòóðû AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x5; // сначала тоже будут температуры
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x4; // Setup ADCINA2 as 2nd SEQ1 conv. AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x4; // Setup ADCINA2 as 2nd SEQ1 conv.
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x7; // Setup ADCINA2 as 2nd SEQ1 conv. AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x7; // Setup ADCINA2 as 2nd SEQ1 conv.
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x2; // Setup ADCINA2 as 2nd SEQ1 conv. AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x2; // Setup ADCINA2 as 2nd SEQ1 conv.
@@ -100,23 +100,23 @@ void setup_adc()
if(Desk==dsk_SHKF) if(Desk==dsk_SHKF)
{ {
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x000F; // Setup 2 conv's on SEQ1 AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x000F; // Setup 2 conv's on SEQ1
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x2; // 380Â Ô1 AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x2; // 380В Ф1
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x3; // 380Â Ô2 AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x3; // 380В Ф2
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x6; // 31Â Ô1 AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x6; // 31В Ф1
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0xC; // 31Â Ô2 ? AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0xC; // 31В Ф2 ?
AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0xA; // 31Â UC1 AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0xA; // 31В UC1
AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0xB; // 31Â UC2 AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0xB; // 31В UC2
AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x7; // 24Â ÏÓ AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x7; // 24В ПУ
AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x4; // 24Â ÏÓ AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x4; // 24В ПУ
AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x5; // 24Â ÏÊ áûëî 5 AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x5; // 24В ПК было 5
AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x1; // 15Â Äð AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x1; // 15В Др
AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0xE; // +24Â Äò AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0xE; // +24В Дт
AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0x0; // +24Â Äò AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0x0; // +24В Дт
AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0x8; // -24Â Äò áûëî 8 AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0x8; // -24В Дт было 8
AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0xF;//0xF; // ÄÒ° 1 AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0xF;//0xF; // ДТ° 1
AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 0xD;//0xD; // ÄÒ° 2 AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 0xD;//0xD; // ДТ° 2
AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 0x9;//0x9; AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 0x9;//0x9;
} }
@@ -206,7 +206,7 @@ interrupt void adc_isr(void)
{ {
if (++cownt_cans>=tpl_cans) cownt_cans=0; if (++cownt_cans>=tpl_cans) cownt_cans=0;
// Èìåííî çäåñü íåò äûð // Именно здесь нет дыр
// if(sens_type[cownt_cans]) // if(sens_type[cownt_cans])
{ {
i++; i++;
@@ -244,7 +244,7 @@ interrupt void adc_isr(void)
if(TermoAD) if(TermoAD)
{ {
if(cownt_cans == TPL_CANS ) code_tpl_canal = TERMOPAIR-1; if(cownt_cans == TPL_CANS ) code_tpl_canal = TERMOPAIR-1;
if(cownt_cans == TPL_CANS+1) code_tpl_canal = TERMOPAIR-2; // ïîòîìó ÷òî 300 è 400 íàîáîðîò if(cownt_cans == TPL_CANS+1) code_tpl_canal = TERMOPAIR-2; // потому что 300 и 400 наоборот
} }
select_tpl_canal(code_tpl_canal); select_tpl_canal(code_tpl_canal);

View File

@@ -1,9 +1,9 @@
/* ЦАП нагрузки и аппаратная обёртка импульсов СИФУ. Load_runner /* ЦАП нагрузки и аппаратная обёртка импульсов СИФУ. Load_runner
* вызывается таймером 1 кГц, расчёт ЦАП делится до DAC_FREQ. * вызывается таймером 1 кГц, расчёт ЦАП делится до DAC_FREQ.
* Формула 166 задаёт фиксированный разгон 6..16 мА. DAC_min/max * Формула 166 задаёт фиксированный разгон 6..16 мА. DAC_min/max
* переводят положение в код, cCalibrDac выбирает ручной код. * переводят положение в код, cCalibrDac выбирает ручной код.
* WAKEpowse относится к ЦАП, не является разрешением дискрета запуска. * WAKEpowse относится к ЦАП, не является разрешением дискрета запуска.
* Автомат СИФУ подключён в конце файла через ump_control_impl.h. * Автомат СИФУ подключён в конце файла через ump_control_impl.h.
*/ */
#include "DSP2833x_Device.h" // DSP281x Headerfile Include File #include "DSP2833x_Device.h" // DSP281x Headerfile Include File
#include "DSP2833x_SWPrioritizedIsrLevels.h" #include "DSP2833x_SWPrioritizedIsrLevels.h"
@@ -29,8 +29,8 @@ unsigned long WAKEpowse;
volatile unsigned long IMPowse; volatile unsigned long IMPowse;
unsigned int period_dac, time_dac; unsigned int period_dac, time_dac;
/* Инициализация, не обработка каждого START. 601 отсчёт при 200 Гц /* Инициализация, не обработка каждого START. 601 отсчёт при 200 Гц
* дают около 3 секунд до рабочего расчёта ЦАП после включения. * дают около 3 секунд до рабочего расчёта ЦАП после включения.
*/ */
void Setup_DAC_time(void) void Setup_DAC_time(void)
{ {
@@ -76,9 +76,9 @@ void Init_DAC(void)
dSEND(0x9002|0x0000); toggle_RES_OUT_1(); dSEND(0x9002|0x0000); toggle_RES_OUT_1();
} }
/* vrot/maxx — доля диапазона между кодами 4 и 20 мА. Маска 0xFFF /* vrot/maxx — доля диапазона между кодами 4 и 20 мА. Маска 0xFFF
* сохраняет 12 бит, но не является насыщением. modbus[0x1C] содержит * сохраняет 12 бит, но не является насыщением. modbus[0x1C] содержит
* расчётное задание, не измеренный ток на выходных клеммах. * расчётное задание, не измеренный ток на выходных клеммах.
*/ */
void Anal_output(long vrot, long maxx) void Anal_output(long vrot, long maxx)
{ {
@@ -87,7 +87,7 @@ void Anal_output(long vrot, long maxx)
out = DAC_min() + vrot * DAC_max() / maxx - vrot * DAC_min() / maxx ; out = DAC_min() + vrot * DAC_max() / maxx - vrot * DAC_min() / maxx ;
x=0;// !x; тщетно бытие x=0;// !x; тщетно бытие
if(cCalibrDac) out=DAC_cal(); if(cCalibrDac) out=DAC_cal();
@@ -116,9 +116,9 @@ Log_to_mem(modbus[0x1D]);
} }
/* После половины time_dac счётчик растёт дважды за вызов. Поэтому /* После половины time_dac счётчик растёт дважды за вызов. Поэтому
* LOAD_TIME=30 даёт примерно 22.5 с до конца разгона при 200 Гц. * LOAD_TIME=30 даёт примерно 22.5 с до конца разгона при 200 Гц.
* Существующий профиль 166 исправление импульса СИФУ не меняет. * Существующий профиль 166 исправление импульса СИФУ не меняет.
*/ */
void Load_runner() void Load_runner()
{ {
@@ -126,7 +126,7 @@ void Load_runner()
float sinus=0; float sinus=0;
int kod; int kod;
/* IMPowse обновляется UMP_pulse_tick(), а не алгоритмом ЦАП. */ /* IMPowse обновляется UMP_pulse_tick(), а не алгоритмом ЦАП. */
if(++count_dac >= period_dac) if(++count_dac >= period_dac)
{ {
count_dac=0; count_dac=0;

View File

@@ -1,5 +1,5 @@
/* Таблицы выборок обновляет ADC ISR. Согласованный снимок нескольких /* Таблицы выборок обновляет ADC ISR. Согласованный снимок нескольких
* каналов требует защиты копирования, одного указателя недостаточно. * каналов требует защиты копирования, одного указателя недостаточно.
*/ */

View File

@@ -1,17 +1,17 @@
/* Интерфейс ЦАП и СИФУ. Входящие команды — UMP_commands_write, /* Интерфейс ЦАП и СИФУ. Входящие команды — UMP_commands_write,
* окончание импульса — UMP_pulse_tick. IMPowse только для диагностики. * окончание импульса — UMP_pulse_tick. IMPowse только для диагностики.
*/ */
void Load_runner(void); void Load_runner(void);
void Anal_output(long vrot, long maxx); void Anal_output(long vrot, long maxx);
void Init_DAC(void); void Init_DAC(void);
void Setup_DAC_time(void); void Setup_DAC_time(void);
/* Счётчик пускового импульса и выдержки инициализации доступны логгеру. */ /* Счётчик пускового импульса и выдержки инициализации доступны логгеру. */
extern volatile unsigned long IMPowse; extern volatile unsigned long IMPowse;
extern unsigned long WAKEpowse; extern unsigned long WAKEpowse;
extern unsigned int period_dac, time_dac; extern unsigned int period_dac, time_dac;
/* Все операции безопасны для вызова из main и обработчиков IRQ. */ /* Все операции безопасны для вызова из main и обработчиков IRQ. */
void UMP_pulse_init(void); void UMP_pulse_init(void);
void UMP_commands_write(unsigned int commands); void UMP_commands_write(unsigned int commands);
void UMP_pulse_tick(void); void UMP_pulse_tick(void);

View File

@@ -1,5 +1,5 @@
/* Íàïðàâëåíèÿ GPIO äëÿ àïïàðàòíûõ èñïîëíåíèé. Åäèíèöà îçíà÷àåò /* Направления GPIO для аппаратных исполнений. Единица означает
* âûõîä; àêòèâíóþ ïîëÿðíîñòü çàäàþò peripher.h è ñõåìà ïëàòû. * выход; активную полярность задают peripher.h и схема платы.
*/ */
#define COMM_gpio00_dir 0L #define COMM_gpio00_dir 0L
#define COMM_gpio01_dir 0L #define COMM_gpio01_dir 0L
@@ -14,7 +14,7 @@
#define COMM_gpio10_dir 0L #define COMM_gpio10_dir 0L
#define COMM_gpio11_dir 0L #define COMM_gpio11_dir 0L
#define COMM_gpio19_dir 1L // 63 — SPI #define COMM_gpio19_dir 1L // 63 — SPI
#define COMM_gpio20_dir 0L // 64 2:9B mode 2 #define COMM_gpio20_dir 0L // 64 2:9B mode 2
#define COMM_gpio21_dir 0L // 65 2:9A mode 4 #define COMM_gpio21_dir 0L // 65 2:9A mode 4
#define COMM_gpio22_dir 0L // 66 2:12C mode 1 #define COMM_gpio22_dir 0L // 66 2:12C mode 1
@@ -26,7 +26,7 @@
#define COMM_gpio32_dir 1L // 74 2:10B DIOD green #define COMM_gpio32_dir 1L // 74 2:10B DIOD green
#define COMM_gpio33_dir 0L #define COMM_gpio33_dir 0L
#define COMM_gpio34_dir 1L // 142 — SCI #define COMM_gpio34_dir 1L // 142 — SCI
#define COMM_gpio48_dir 1L // 88 2:14C DIOD red #define COMM_gpio48_dir 1L // 88 2:14C DIOD red
#define COMM_gpio49_dir 1L // 89 2:14B select #define COMM_gpio49_dir 1L // 89 2:14B select
@@ -57,7 +57,7 @@
#define BKSD_gpio10_dir 0L // 19 2:6C oil #define BKSD_gpio10_dir 0L // 19 2:6C oil
#define BKSD_gpio11_dir 1L // 20 2:3C select #define BKSD_gpio11_dir 1L // 20 2:3C select
#define BKSD_gpio19_dir 1L // 63 — SPI #define BKSD_gpio19_dir 1L // 63 — SPI
#define BKSD_gpio20_dir 0L // 64 2:9B mode 2 #define BKSD_gpio20_dir 0L // 64 2:9B mode 2
#define BKSD_gpio21_dir 0L // 65 2:9A mode 4 #define BKSD_gpio21_dir 0L // 65 2:9A mode 4
#define BKSD_gpio22_dir 0L // 66 2:12C mode 1 #define BKSD_gpio22_dir 0L // 66 2:12C mode 1
@@ -69,7 +69,7 @@
#define BKSD_gpio32_dir 1L // 74 2:10B DIOD green #define BKSD_gpio32_dir 1L // 74 2:10B DIOD green
#define BKSD_gpio33_dir 0L #define BKSD_gpio33_dir 0L
#define BKSD_gpio34_dir 1L // 142 — SCI #define BKSD_gpio34_dir 1L // 142 — SCI
#define BKSD_gpio48_dir 1L // 88 2:14C DIOD red #define BKSD_gpio48_dir 1L // 88 2:14C DIOD red
#define BKSD_gpio49_dir 0L // 89 2:14B input 2 #define BKSD_gpio49_dir 0L // 89 2:14B input 2
@@ -100,7 +100,7 @@
#define BKST_gpio10_dir 0L #define BKST_gpio10_dir 0L
#define BKST_gpio11_dir 1L // 20 2:3C select #define BKST_gpio11_dir 1L // 20 2:3C select
#define BKST_gpio19_dir 1L // 63 — SPI #define BKST_gpio19_dir 1L // 63 — SPI
#define BKST_gpio20_dir 0L // 64 2:9B mode 2 #define BKST_gpio20_dir 0L // 64 2:9B mode 2
#define BKST_gpio21_dir 0L // 65 2:9A mode 4 #define BKST_gpio21_dir 0L // 65 2:9A mode 4
#define BKST_gpio22_dir 0L // 66 2:12C mode 1 #define BKST_gpio22_dir 0L // 66 2:12C mode 1
@@ -112,7 +112,7 @@
#define BKST_gpio32_dir 1L // 74 2:10B DIOD green #define BKST_gpio32_dir 1L // 74 2:10B DIOD green
#define BKST_gpio33_dir 0L #define BKST_gpio33_dir 0L
#define BKST_gpio34_dir 1L // 142 — SCI #define BKST_gpio34_dir 1L // 142 — SCI
#define BKST_gpio48_dir 1L // 88 2:14C DIOD red #define BKST_gpio48_dir 1L // 88 2:14C DIOD red
#define BKST_gpio49_dir 0L #define BKST_gpio49_dir 0L
@@ -143,7 +143,7 @@
#define PULT_gpio10_dir 0L #define PULT_gpio10_dir 0L
#define PULT_gpio11_dir 0L #define PULT_gpio11_dir 0L
#define PULT_gpio19_dir 1L // 63 — SPI #define PULT_gpio19_dir 1L // 63 — SPI
#define PULT_gpio20_dir 0L // 64 2:9B mode 2 #define PULT_gpio20_dir 0L // 64 2:9B mode 2
#define PULT_gpio21_dir 0L // 65 2:9A mode 4 #define PULT_gpio21_dir 0L // 65 2:9A mode 4
#define PULT_gpio22_dir 0L // 66 2:12C mode 1 #define PULT_gpio22_dir 0L // 66 2:12C mode 1
@@ -155,7 +155,7 @@
#define PULT_gpio32_dir 1L // 74 2:10B DIOD green #define PULT_gpio32_dir 1L // 74 2:10B DIOD green
#define PULT_gpio33_dir 0L #define PULT_gpio33_dir 0L
#define PULT_gpio34_dir 1L // 142 — SCI #define PULT_gpio34_dir 1L // 142 — SCI
#define PULT_gpio48_dir 1L // 88 2:14C DIOD red #define PULT_gpio48_dir 1L // 88 2:14C DIOD red
#define PULT_gpio49_dir 0L // 89 2:14B button #define PULT_gpio49_dir 0L // 89 2:14B button
@@ -186,7 +186,7 @@
#define PLT2_gpio10_dir 0L #define PLT2_gpio10_dir 0L
#define PLT2_gpio11_dir 0L #define PLT2_gpio11_dir 0L
#define PLT2_gpio19_dir 1L // 63 × SPI #define PLT2_gpio19_dir 1L // 63 Ч SPI
#define PLT2_gpio20_dir 0L // 64 2:9B mode 2 #define PLT2_gpio20_dir 0L // 64 2:9B mode 2
#define PLT2_gpio21_dir 0L // 65 2:9A mode 4 #define PLT2_gpio21_dir 0L // 65 2:9A mode 4
#define PLT2_gpio22_dir 0L // 66 2:12C mode 1 #define PLT2_gpio22_dir 0L // 66 2:12C mode 1
@@ -198,7 +198,7 @@
#define PLT2_gpio32_dir 1L // 74 2:10B DIOD green #define PLT2_gpio32_dir 1L // 74 2:10B DIOD green
#define PLT2_gpio33_dir 0L // 75 2:10C button #define PLT2_gpio33_dir 0L // 75 2:10C button
#define PLT2_gpio34_dir 1L // 142 × SCI #define PLT2_gpio34_dir 1L // 142 Ч SCI
#define PLT2_gpio48_dir 0L // 88 2:14C button #define PLT2_gpio48_dir 0L // 88 2:14C button
#define PLT2_gpio49_dir 0L // 89 2:14B button #define PLT2_gpio49_dir 0L // 89 2:14B button
@@ -229,7 +229,7 @@
#define SHKF_gpio10_dir 0L // 19 2:6C input #define SHKF_gpio10_dir 0L // 19 2:6C input
#define SHKF_gpio11_dir 0L // 20 2:3C input #define SHKF_gpio11_dir 0L // 20 2:3C input
#define SHKF_gpio19_dir 1L // 63 — SPI #define SHKF_gpio19_dir 1L // 63 — SPI
#define SHKF_gpio20_dir 0L // 64 2:9B mode 2 #define SHKF_gpio20_dir 0L // 64 2:9B mode 2
#define SHKF_gpio21_dir 0L // 65 2:9A mode 4 #define SHKF_gpio21_dir 0L // 65 2:9A mode 4
#define SHKF_gpio22_dir 0L // 66 2:12C mode 1 #define SHKF_gpio22_dir 0L // 66 2:12C mode 1
@@ -241,7 +241,7 @@
#define SHKF_gpio32_dir 0L // 74 2:10B input #define SHKF_gpio32_dir 0L // 74 2:10B input
#define SHKF_gpio33_dir 0L // 75 2:10C input #define SHKF_gpio33_dir 0L // 75 2:10C input
#define SHKF_gpio34_dir 1L // 142 — SCI #define SHKF_gpio34_dir 1L // 142 — SCI
#define SHKF_gpio48_dir 1L // 88 2:14C DIOD red #define SHKF_gpio48_dir 1L // 88 2:14C DIOD red
#define SHKF_gpio49_dir 0L // 89 2:14B input #define SHKF_gpio49_dir 0L // 89 2:14B input
@@ -272,7 +272,7 @@
#define LOAD_gpio10_dir 0L #define LOAD_gpio10_dir 0L
#define LOAD_gpio11_dir 0L // 20 2:3C res_in 0 #define LOAD_gpio11_dir 0L // 20 2:3C res_in 0
#define LOAD_gpio19_dir 1L // 63 — SPI #define LOAD_gpio19_dir 1L // 63 — SPI
#define LOAD_gpio20_dir 0L // 64 2:9B mode 2 #define LOAD_gpio20_dir 0L // 64 2:9B mode 2
#define LOAD_gpio21_dir 0L // 65 2:9A mode 4 #define LOAD_gpio21_dir 0L // 65 2:9A mode 4
#define LOAD_gpio22_dir 0L // 66 2:12C mode 1 #define LOAD_gpio22_dir 0L // 66 2:12C mode 1
@@ -284,7 +284,7 @@
#define LOAD_gpio32_dir 1L // 74 2:10B DIOD green #define LOAD_gpio32_dir 1L // 74 2:10B DIOD green
#define LOAD_gpio33_dir 0L #define LOAD_gpio33_dir 0L
#define LOAD_gpio34_dir 1L // 142 — SCI #define LOAD_gpio34_dir 1L // 142 — SCI
#define LOAD_gpio48_dir 1L // 88 2:14C DIOD red #define LOAD_gpio48_dir 1L // 88 2:14C DIOD red
#define LOAD_gpio49_dir 0L #define LOAD_gpio49_dir 0L

View File

@@ -1,5 +1,5 @@
/* Буферы UART разделяются ISR и main. main обрабатывает /* Буферы UART разделяются ISR и main. main обрабатывает
* законченный RS_Header. Размеры сверять с 16-битной ABI DSP. * законченный RS_Header. Размеры сверять с 16-битной ABI DSP.
*/ */
#ifndef _RS485 #ifndef _RS485
#define _RS485 #define _RS485
@@ -32,30 +32,30 @@ typedef struct
{ {
volatile struct SCI_REGS *SciRegs; volatile struct SCI_REGS *SciRegs;
unsigned int commnumber; // Номер порта unsigned int commnumber; // Номер порта
unsigned long RS_Length; // Длина пакета unsigned long RS_Length; // Длина пакета
unsigned int *pRS_RecvPtr; // Буфер приема unsigned int *pRS_RecvPtr; // Буфер приема
unsigned int *pRS_SendPtr; // Буфер посылки unsigned int *pRS_SendPtr; // Буфер посылки
unsigned int *pRecvPtr; unsigned int *pRecvPtr;
unsigned int RS_PrevCmd; // Предыдущаа комманда unsigned int RS_PrevCmd; // Предыдущаа комманда
unsigned int RS_Cmd; // Текущаа комманда unsigned int RS_Cmd; // Текущаа комманда
unsigned int RS_Header[MAX_RECEIVE_LENGTH]; // Заголовок unsigned int RS_Header[MAX_RECEIVE_LENGTH]; // Заголовок
unsigned int flag_TIMEOUT_to_Send; // Флаг ожиданиа таймаута на отсылку unsigned int flag_TIMEOUT_to_Send; // Флаг ожиданиа таймаута на отсылку
unsigned int flag_TIMEOUT_to_Receive; // Флаг ожиданиа таймаута на прием unsigned int flag_TIMEOUT_to_Receive; // Флаг ожиданиа таймаута на прием
unsigned int RS_DataReady; // Флаг готовности RS данных unsigned int RS_DataReady; // Флаг готовности RS данных
unsigned int buffer[MAX_SEND_LENGTH]; // Буфер дла отсылки по RS unsigned int buffer[MAX_SEND_LENGTH]; // Буфер дла отсылки по RS
unsigned int addr_answer; // адрес куда отвечать в режиме ведущего unsigned int addr_answer; // адрес куда отвечать в режиме ведущего
unsigned int addr_recive; // адрес по которому нас запросили unsigned int addr_recive; // адрес по которому нас запросили
unsigned int flag_LEADING; // Флаг режима контроллера (по умолчанию ведомый) unsigned int flag_LEADING; // Флаг режима контроллера (по умолчанию ведомый)
unsigned long RS_RecvLen; unsigned long RS_RecvLen;
unsigned long RS_SLength; // Длина пакета дла посылки unsigned long RS_SLength; // Длина пакета дла посылки
unsigned long RS_SendLen; // Количество байт уже передали unsigned long RS_SendLen; // Количество байт уже передали
char RS_SendBlockMode; // Режим передачи char RS_SendBlockMode; // Режим передачи
char RS_Flag9bit; // дла RS485???????? char RS_Flag9bit; // дла RS485????????
int BS_LoadOK; // Флаг успешности приема блока int BS_LoadOK; // Флаг успешности приема блока
int RS_FlagBegin; int RS_FlagBegin;
int RS_HeaderCnt; int RS_HeaderCnt;
int RS_FlagSkiping; int RS_FlagSkiping;
@@ -67,39 +67,39 @@ typedef struct
extern RS_DATA rs_a,rs_b; extern RS_DATA rs_a,rs_b;
extern unsigned int extern unsigned int
RS_Len[70]; /* Действительнаа длина команды (отладочной) + 1 */ RS_Len[70]; /* Действительнаа длина команды (отладочной) + 1 */
interrupt void RSA_RX_Handler(void); interrupt void RSA_RX_Handler(void);
interrupt void RSA_TX_Handler(void); interrupt void RSA_TX_Handler(void);
interrupt void RSB_RX_Handler(void); interrupt void RSB_RX_Handler(void);
interrupt void RSB_TX_Handler(void); interrupt void RSB_TX_Handler(void);
/* иницилизациа переменных rs_a,rs_b*/ /* иницилизациа переменных rs_a,rs_b*/
void create_uart_vars(char size_cmd15); void create_uart_vars(char size_cmd15);
/** Повторнаа инициализациа последовательного порта, используетса после подвиса */ /** Повторнаа инициализациа последовательного порта, используетса после подвиса */
/** Настройка режима приема/передачи */ /** Настройка режима приема/передачи */
void RS_SetBitMode(RS_DATA *rs_arr, int n); void RS_SetBitMode(RS_DATA *rs_arr, int n);
/** Посылка блока байтов. /** Посылка блока байтов.
Посылает массива 32-битных целых чисел старшие биты должны быть 0. Посылает массива 32-битных целых чисел старшие биты должны быть 0.
@precondition Работа ф-ции зависит от макро RS_TRANSMIT_INTR @precondition Работа ф-ции зависит от макро RS_TRANSMIT_INTR
@param buf адрес массива @param buf адрес массива
@param len количество байт @param len количество байт
@see RS_BSend, RS_TRANSMIT_INTR @see RS_BSend, RS_TRANSMIT_INTR
*/ */
int RS_Send(RS_DATA *rs_arr,unsigned int *pBuf, unsigned long len); int RS_Send(RS_DATA *rs_arr,unsigned int *pBuf, unsigned long len);
/** Посылка блока упакованных байтов. /** Посылка блока упакованных байтов.
@precondition Работа ф-ции зависит от макро RS_TRANSMIT_INTR @precondition Работа ф-ции зависит от макро RS_TRANSMIT_INTR
@param buf адрес массива @param buf адрес массива
@param len количество 8-битных байт @param len количество 8-битных байт
@see RS_Send, RS_TRANSMIT_INTR @see RS_Send, RS_TRANSMIT_INTR
*/ */
int RS_BSend(RS_DATA *rs_arr,unsigned int *pBuf, unsigned long len); int RS_BSend(RS_DATA *rs_arr,unsigned int *pBuf, unsigned long len);
/** Инициализациа последовательного порта */ /** Инициализациа последовательного порта */
void setup_uart(char commnumber,unsigned long speed_baud); /* speed_baud - скорость линии в бодах */ void setup_uart(char commnumber,unsigned long speed_baud); /* speed_baud - скорость линии в бодах */
void RS_SetLineMode(RS_DATA *rs_arr, int bit, char parity, int stop); void RS_SetLineMode(RS_DATA *rs_arr, int bit, char parity, int stop);
void RS_SetLineSpeed(RS_DATA *rs_arr, unsigned long speed); void RS_SetLineSpeed(RS_DATA *rs_arr, unsigned long speed);
@@ -107,17 +107,17 @@ void RS_SetLineSpeed(RS_DATA *rs_arr, unsigned long speed);
// Transmit a character from the SCI' // Transmit a character from the SCI'
#define SCI_send(x,y) x->SciRegs->SCITXBUF=(unsigned char)(y) #define SCI_send(x,y) x->SciRegs->SCITXBUF=(unsigned char)(y)
// Ожидание завершениа передачи UART // Ожидание завершениа передачи UART
// wait for TRDY =1 for empty state // wait for TRDY =1 for empty state
#define RS_Wait4OK(x) while(!(x->SciRegs->SCICTL2.bit.TXEMPTY)) #define RS_Wait4OK(x) while(!(x->SciRegs->SCICTL2.bit.TXEMPTY))
/** Переключение линии на прием */ /** Переключение линии на прием */
#define RS_Line_to_receive(x) if(x->commnumber==COM_2) GpioDataRegs.GPBDAT.bit.GPIO34 = 1; #define RS_Line_to_receive(x) if(x->commnumber==COM_2) GpioDataRegs.GPBDAT.bit.GPIO34 = 1;
/** Переключение линии на передачу */ /** Переключение линии на передачу */
#define RS_Line_to_send(x) if(x->commnumber==COM_2) GpioDataRegs.GPBDAT.bit.GPIO34 = 0; #define RS_Line_to_send(x) if(x->commnumber==COM_2) GpioDataRegs.GPBDAT.bit.GPIO34 = 0;
/** Разрешение прерываний по получению символа и ошибкам от UART */ /** Разрешение прерываний по получению символа и ошибкам от UART */
#define enableUARTInt(x) x->SciRegs->SCICTL2.all=2 #define enableUARTInt(x) x->SciRegs->SCICTL2.all=2
#define enableUARTIntW(x) x->SciRegs->SCICTL2.all=1 #define enableUARTIntW(x) x->SciRegs->SCICTL2.all=1

View File

@@ -1,5 +1,5 @@
/* Коды CMD_* являются частью формата обмена с ПК. Новые команды /* Коды CMD_* являются частью формата обмена с ПК. Новые команды
* добавляются без перенумерации существующих значений. * добавляются без перенумерации существующих значений.
*/ */
#ifndef _BIOS_DSP #ifndef _BIOS_DSP
#define _BIOS_DSP #define _BIOS_DSP
@@ -36,67 +36,67 @@ enum {
CMD_VECTOR=61, CMD_VECTOR=61,
CMD_IMPULSE, CMD_IMPULSE,
/* стандартные команды */ /* стандартные команды */
CMD_STD=65, CMD_STD_ANS CMD_STD=65, CMD_STD_ANS
}; };
enum {false=0, true}; enum {false=0, true};
/** Возвращает номер комманды, если есть или -1 если транзакций не было */ /** Возвращает номер комманды, если есть или -1 если транзакций не было */
int get_command(RS_DATA *rs_arr); int get_command(RS_DATA *rs_arr);
/** Стандартный ответ, без параметров */ /** Стандартный ответ, без параметров */
void Answer(RS_DATA *rs_arr,int n); void Answer(RS_DATA *rs_arr,int n);
/* начальные установки (не работает)*/ /* начальные установки (не работает)*/
void init(RS_DATA *rs_arr); void init(RS_DATA *rs_arr);
/**@name Комманды /**@name Комманды
* Комманды, вызываемые через последовательный канал*/ * Комманды, вызываемые через последовательный канал*/
//@{ //@{
/** Инициировать загрузку блока. /** Инициировать загрузку блока.
Настраивает прием блока данных */ Настраивает прием блока данных */
void initload(RS_DATA *rs_arr); void initload(RS_DATA *rs_arr);
/** Загрузка блока. /** Загрузка блока.
Вызываетса после загрузки блока через RS */ Вызываетса после загрузки блока через RS */
void load(RS_DATA *rs_arr); void load(RS_DATA *rs_arr);
/** Выполнить программу в формате Serial Boot. /** Выполнить программу в формате Serial Boot.
@precondition Должна быть произведена загрузка блока @precondition Должна быть произведена загрузка блока
Адрес программы беретса из заголовка и Адрес программы беретса из заголовка и
сравниваетса с переменной RecvPtr, заполнаемой в ф-ции load сравниваетса с переменной RecvPtr, заполнаемой в ф-ции load
@see load */ @see load */
void run (RS_DATA *rs_arr); void run (RS_DATA *rs_arr);
/** Прочитать ачейку памати */ /** Прочитать ачейку памати */
void peek(RS_DATA *rs_arr); void peek(RS_DATA *rs_arr);
/** Записать в ачейку памати */ /** Записать в ачейку памати */
void poke(RS_DATA *rs_arr); void poke(RS_DATA *rs_arr);
/** Передать блок памати */ /** Передать блок памати */
void upload(RS_DATA *rs_arr); void upload(RS_DATA *rs_arr);
/** Прошить XILINX. /** Прошить XILINX.
@precondition Должна быть произведена загрузка блока @precondition Должна быть произведена загрузка блока
Адрес и длина прошивки беретса из заголовка и Адрес и длина прошивки беретса из заголовка и
сравниваетса с переменными RecvPtr и Length, заполнаемыми в ф-ции load, сравниваетса с переменными RecvPtr и Length, заполнаемыми в ф-ции load,
так же смотрит магическое слово в начале прошивки так же смотрит магическое слово в начале прошивки
@see load */ @see load */
void xflash(RS_DATA *rs_arr); void xflash(RS_DATA *rs_arr);
/** Прошить TMS. /** Прошить TMS.
@precondition Должна быть произведена загрузка блока @precondition Должна быть произведена загрузка блока
Адрес и длина прошивки беретса из заголовка и Адрес и длина прошивки беретса из заголовка и
сравниваетса с переменными RecvPtr и Length, заполнаемыми в ф-ции load сравниваетса с переменными RecvPtr и Length, заполнаемыми в ф-ции load
@see load */ @see load */
void tflash(RS_DATA *rs_arr); void tflash(RS_DATA *rs_arr);
/* расширенные команды дла биоса */ /* расширенные команды дла биоса */
void extendbios(RS_DATA *rs_arr); void extendbios(RS_DATA *rs_arr);

View File

@@ -1,48 +1,48 @@
/* Заводские калибровки по версии BALSAM и типу платы. Здесь /* Заводские калибровки по версии BALSAM и типу платы. Здесь
* определяются массивы, а не только extern; не дублировать подключение. * определяются массивы, а не только extern; не дублировать подключение.
*/ */
#if BALSAM == 166 //------------------------------------------------------------- #if BALSAM == 166 //-------------------------------------------------------------
int def_cal[][8] = { int def_cal[][8] = {
// Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2 // Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2
4936, 4877, 4972, 4857, 1960, 1920, 2610, 2570, // Борт 0 4936, 4877, 4972, 4857, 1960, 1920, 2610, 2570, // Борт 0
4876, 5005, 4876, 4847, 1950, 1965, 2600, 2615, // Борт 1 4876, 5005, 4876, 4847, 1950, 1965, 2600, 2615, // Борт 1
// УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I // УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I
3820, 3790, 3505, 3380, 1718, 673, 854, 14, // Борт 0 3820, 3790, 3505, 3380, 1718, 673, 854, 14, // Борт 0
3835, 3785, 3522, 3332, 1697, 653, 860, 17, // Борт 1 3835, 3785, 3522, 3332, 1697, 653, 860, 17, // Борт 1
// ВЭП 380Ф1 380Ф2 300 1 300 2 400 1 400 2 // ВЭП 380Ф1 380Ф2 300 1 300 2 400 1 400 2
1281, 1272, 0, 0, 2049, 2050, 2749, 2750 }; 1281, 1272, 0, 0, 2049, 2050, 2749, 2750 };
#endif //--------------------------------------------------------------------- #endif //---------------------------------------------------------------------
#if BALSAM == 165 //------------------------------------------------------------- #if BALSAM == 165 //-------------------------------------------------------------
int def_cal[][8] = { int def_cal[][8] = {
// Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2 // Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2
5130, 4960, 4925, 5070, 1881, 1881, 2506, 2516, // Борт 0 5130, 4960, 4925, 5070, 1881, 1881, 2506, 2516, // Борт 0
5020, 5040, 4950, 5030, 1871, 1879, 2507, 2514, // Борт 1 5020, 5040, 4950, 5030, 1871, 1879, 2507, 2514, // Борт 1
// УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I // УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I
3890, 3865, 5100, 4850, 1730, 675, 854, 14, // Борт 0 3890, 3865, 5100, 4850, 1730, 675, 854, 14, // Борт 0
3845, 3800, 3250, 3100, 1044, 0, 860, 17, // Борт 1 3845, 3800, 3250, 3100, 1044, 0, 860, 17, // Борт 1
// ВЭП 380Ф1 380Ф2 300 1 300 2 400 1 400 2 // ВЭП 380Ф1 380Ф2 300 1 300 2 400 1 400 2
1289, 1280, 0, 0, 2073, 2071, 2773, 2771 }; 1289, 1280, 0, 0, 2073, 2071, 2773, 2771 };
#endif //--------------------------------------------------------------------- #endif //---------------------------------------------------------------------
#if BALSAM == 164 //------------------------------------------------------------- #if BALSAM == 164 //-------------------------------------------------------------
int def_cal[][8] = { int def_cal[][8] = {
// Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2 // Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2
7573, 7573, 7573, 7573, 1979, 1888, 2592, 2513, // Борт 0 7573, 7573, 7573, 7573, 1979, 1888, 2592, 2513, // Борт 0
7573, 7573, 7573, 7573, 1970, 1907, 2584, 2558, // Борт 1 7573, 7573, 7573, 7573, 1970, 1907, 2584, 2558, // Борт 1
// УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I // УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I
3920, 3905, 3300, 3220, 1015, 0, 854, 14, // Борт 0 3920, 3905, 3300, 3220, 1015, 0, 854, 14, // Борт 0
3835, 3785, 5100, 4600, 1750, 680, 860, 17, // Борт 1 3835, 3785, 5100, 4600, 1750, 680, 860, 17, // Борт 1
// ВЭП 380Ф1 380Ф2 300 1 300 2 400 1 400 2 // ВЭП 380Ф1 380Ф2 300 1 300 2 400 1 400 2
1266, 1267, 0, 0, 2063, 2040, 2678, 2655 }; 1266, 1267, 0, 0, 2063, 2040, 2678, 2655 };
#endif //--------------------------------------------------------------------- #endif //---------------------------------------------------------------------
@@ -51,15 +51,15 @@
#if PXXXXX == 1 //------------------------------------------------------------- #if PXXXXX == 1 //-------------------------------------------------------------
int def_cal[][6] = { int def_cal[][6] = {
// Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2 // Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2
0400, 0400, 0400, 0400, 1950, 1950, 2600, 2600, // Борт 0 0400, 0400, 0400, 0400, 1950, 1950, 2600, 2600, // Борт 0
0400, 0400, 0400, 0400, 1950, 1950, 2600, 2600, // Борт 1 0400, 0400, 0400, 0400, 1950, 1950, 2600, 2600, // Борт 1
// УМП UA UC IA IC 20mA 4mA // УМП UA UC IA IC 20mA 4mA
0400, 0400, 4800, 4800, 0, 0, 0, 0, // Борт 0 0400, 0400, 4800, 4800, 0, 0, 0, 0, // Борт 0
0400, 0400, 4800, 4800, 0, 0, 0, 0, // Борт 1 0400, 0400, 4800, 4800, 0, 0, 0, 0, // Борт 1
// ВЭП 380Ф1 380Ф2 300 1 300 2 400 1 400 2 // ВЭП 380Ф1 380Ф2 300 1 300 2 400 1 400 2
1270, 1270, 0, 0, 1950, 1950, 2600, 2600 }; 1270, 1270, 0, 0, 1950, 1950, 2600, 2600 };
#endif //--------------------------------------------------------------------- #endif //---------------------------------------------------------------------
*/ */

View File

@@ -0,0 +1,123 @@
#ifndef CAN_TELEMETRY_IMPL_H /* Реализация включается только в ecan.c после аппаратных типов и переменных штатного передатчика. */
#define CAN_TELEMETRY_IMPL_H /* Не допускает повторного определения состояния и функций в одной единице трансляции. */
#define CAN_HEARTBEAT_ADDR 0x0100U /* Как в варианте 167, отдельный адрес heartbeat находится вне R0–R127 и служебной области логгера 0x1000. */
#define CAN_HEARTBEAT_TICKS ((Uint32)READY_FREQ) /* READY_FREQ задаёт частоту Timer1 в герцах; это ровно одна секунда его тактов. */
#define CAN_REFRESH_TICKS ((Uint32)READY_FREQ * 13UL / 10UL) /* Тринадцать десятых секунды дают период повторения данных 1,3 с независимо от числа циклов main. */
#define CAN_SCAN_TICKS ((Uint32)READY_FREQ * CANPOWSE / 1000UL) /* Существующие CANPOWSE=20 мс ограничивают задержку обнаружения обновлений, но не скорость выдачи уже готовой очереди. */
#define CAN_ACK_TICKS ((Uint32)READY_FREQ / 10UL) /* Программная страховка через 100 мс отменяет зависший TX, если аппаратный timeout IRQ не был обработан. */
static Uint32 can_last_hi[ANSWER_LEN], can_last_lo[ANSWER_LEN], can_last_at[ANSWER_LEN]; /* Последний подтверждённый пакет и время ACK хранятся отдельно для каждого начального адреса R0–R127. */
static unsigned int can_valid[8], can_cursor[2], can_stream; /* Восемь 16-битных масок покрывают 128 адресов; два курсора и очередность обеспечивают справедливость потоков. */
static Uint32 can_tx_at, can_failed_at, can_heartbeat_at, can_scan_at; /* Беззнаковые отметки Timer1 поддерживают вычитание через переполнение 32-битного счётчика. */
static unsigned int can_backoff, can_started, can_heartbeat_count, can_heartbeat_due, can_scan_due; /* Отделяет секундную паузу после ошибки, старт часов, heartbeat и незавершённое сканирование масок. */
static int can_pending_addr; /* Значение -1 обозначает heartbeat, который не должен индексировать кэш технологических регистров. */
static volatile unsigned int can_tx_failed; /* Timeout ISR отмечает ошибку текущего mailbox до обработки ACK в основном цикле. */
static Uint32 CAN_millis(void) /* Возвращает согласованный счётчик Timer1; при READY_FREQ=1000 один такт соответствует миллисекунде. */
{ /* Чтение 32 бит защищается отдельно на 16-битном C28x без ожидания аппаратуры. */
unsigned int saved = __disable_interrupts(); /* Сохраняет исходное состояние IRQ, включая вызовы из уже защищённой отправки. */
Uint32 now = CpuTimer1.InterruptCount; /* Счётчик обновляют оба существующих обработчика Timer1 для пульта и измерительной платы. */
__restore_interrupts(saved); /* Немедленно возвращает прежнюю маску прерываний. */
return now; /* Наружу передаётся один целостный снимок времени. */
} /* Длительные расчёты масок выполняются с разрешёнными прерываниями. */
static void CAN_telemetry_init(void) /* Сбрасывает программное состояние при каждом InitCan, в том числе после запуска с грязной RAM. */
{ /* Крупные массивы не очищаются, потому что их элементы недоступны без valid-бита. */
unsigned int i; /* Перебирает восемь масок достоверности кэша. */
for (i = 0U; i < 8U; ++i) can_valid[i] = 0U; /* Первый пакет каждого разрешённого адреса обязательно передаётся после запуска. */
can_cursor[0] = can_cursor[1] = can_stream = 0U; /* Обе маски начинают обход с R0; далее потоки чередуются после реально поставленного кадра. */
can_backoff = can_started = can_heartbeat_count = can_heartbeat_due = 0U; /* Новые часы и секундный heartbeat начинают отсчёт при первом обслуживании main. */
can_scan_due = 1U; /* Первый снимок данных выдаётся сразу, без ожидания периода 1,3 с. */
can_pending_addr = -1; can_tx_failed = 0U; wait = 0; /* Исключает подтверждение кадра и ошибку из предыдущего запуска программы. */
} /* Сброс не меняет аппаратные CAN ID, маски регистров и настройки EEPROM. */
static int CAN_tx_ready(Uint32 now) /* Обслуживает завершение штатного mailbox 0; вызывающий код уже запретил IRQ на короткое время. */
{ /* Возвращает готовность без ожидания ACK, CANAA или освобождения шины в цикле. */
if ((ECanaRegs.CANTRS.all | ECanaRegs.CANTRR.all) & 1UL) { /* Бит 0 относится только к штатному TX; служебный mailbox 2 не перезаписывается. */
if (wait && !can_tx_failed && (ECanaRegs.CANTRS.all & 1UL) && now - can_tx_at >= CAN_ACK_TICKS) { /* Программный timeout страхует потерянное аппаратное прерывание спустя 100 мс. */
can_tx_failed = 1U; ++CanTimeOutErrorTR; /* Отмечает ошибку ровно один раз, пока этот запрос ещё ожидает завершения отмены. */
EALLOW; ECanaRegs.CANTOC.all &= ~1UL; EDIS; /* Снимает источник аппаратного timeout только для mailbox 0, сохраняя остальные биты контроля. */
ECanaRegs.CANTRR.all = 1UL; /* Запрашивает аппаратную отмену без блокирующего ожидания CANAA. */
} /* Данные занятого mailbox остаются неизменными до аппаратного освобождения. */
return 0; /* Текущий адрес и признак готовности сканирования сохраняются для повторного обслуживания. */
} /* Только свободный mailbox позволяет обработать завершение предыдущей передачи. */
if (wait) { /* ACK или ошибка относятся ровно к одному ранее запущенному кадру. */
if ((ECanaRegs.CANTA.all & 1UL) && !can_tx_failed) { /* Только успешный ACK позволяет подавлять повтор неизменившихся данных. */
if (can_pending_addr >= 0) { /* Heartbeat не занимает ограниченный технологический кэш. */
can_last_hi[can_pending_addr] = ECanaMboxes.MBOX0.MDH.all; /* Запоминает действительно доставленные адрес и первое слово из неизменявшегося mailbox. */
can_last_lo[can_pending_addr] = ECanaMboxes.MBOX0.MDL.all; /* Сохраняет второе и третье слова того же подтверждённого кадра. */
can_last_at[can_pending_addr] = now; /* Отсчитывает повтор через 1,3 с от последнего подтверждения, а не от неудачной попытки. */
can_valid[can_pending_addr >> 4] |= 1U << (can_pending_addr & 15); /* Устанавливает один бит достоверности начального адреса пакета. */
} /* Перекрывающиеся пакеты разных масок имеют независимые начальные адреса. */
} else { /* Отмена, ошибка или свободный TX без CANAA не подтверждают доставку текущих данных. */
can_failed_at = now; can_backoff = 1U; /* Ограничивает новые попытки одной секундой при отсутствии получателя и CAN ACK. */
} /* Старый подтверждённый кэш сохраняется, поэтому неудачная передача не теряет обновление. */
wait = 0; can_tx_failed = 0U; can_pending_addr = -1; /* Завершение обрабатывается один раз даже без отдельного CANAA после отмены. */
} /* Проверяет паузу после ошибки до подготовки следующего кадра. */
if (can_backoff && now - can_failed_at < CAN_HEARTBEAT_TICKS) return 0; /* Во время секундной паузы данные и heartbeat остаются ожидающими. */
can_backoff = 0U; /* Снятие паузы не требует изменения таймеров технологических данных. */
return 1; /* Mailbox свободен и может принять один новый актуальный кадр. */
} /* Чужие mailbox, аппаратный CAN ID и получаемые команды не меняются. */
int CAN_send(int Port, int data[], int Addr) /* Возвращает 0 при занятости, 1 после запуска TX и 2 при неизменном пакете до срока повторения. */
{ /* Снимок данных и запуск mailbox защищаются одним коротким запретом IRQ. */
Uint32 hiword, loword, now; /* Ровно два 32-битных поля соответствуют восьми октетам существующего формата BALZAM. */
unsigned int saved = __disable_interrupts(); /* Исключает разрыв трёхсловного снимка и гонку запуска с timeout ISR. */
(void)Port; now = CAN_millis(); /* Как прежний передатчик, использует eCAN-A; время берётся из общего Timer1. */
if (!CAN_tx_ready(now)) { __restore_interrupts(saved); return 0; } /* При занятости ничего не перезаписывает и не подтверждает данные программно. */
if (Addr == CAN_HEARTBEAT_ADDR) { /* Отдельный пакет состояния узла не обращается к data=NULL или к R256. */
hiword = 0xE0000000UL | ((Uint32)CAN_HEARTBEAT_ADDR << 16) | can_heartbeat_count; /* Сохраняет маркер BALZAM и передаёт циклический 16-битный счётчик секунд. */
loword = ((Uint32)(unsigned int)Mode << 16) | (unsigned int)Desk; /* Два следующих слова сообщают аппаратный Mode и тип платы Desk. */
can_pending_addr = -1; /* Успешный heartbeat не подтверждает ни один технологический пакет. */
} else { /* Первый снимок, изменение любого слова либо истечение периода вызывают одинаковую отправку данных. */
if (Addr < 0 || Addr >= ANSWER_LEN) { __restore_interrupts(saved); return 2; } /* Не допускает чтения за картой R0–R127 и позволяет планировщику пропустить неверный адрес. */
hiword = 0xE0000000UL | ((Uint32)Addr << 16) | ((Uint32)data[Addr] & 0xFFFFUL); /* Первый регистр занимает младшие шестнадцать бит старшей половины CAN-данных. */
loword = Addr + 1 < ANSWER_LEN ? ((Uint32)data[Addr + 1] & 0xFFFFUL) << 16 : 0UL; /* Отсутствующее второе слово у конца карты заменяется нулём. */
if (Addr + 2 < ANSWER_LEN) loword |= (Uint32)data[Addr + 2] & 0xFFFFUL; /* Третье слово дополняется только в пределах реального массива регистров. */
if ((can_valid[Addr >> 4] & (1U << (Addr & 15))) && can_last_hi[Addr] == hiword && can_last_lo[Addr] == loword && now - can_last_at[Addr] < CAN_REFRESH_TICKS) { /* Совпадение всех слов подавляет передачу только до индивидуального срока 1,3 с. */
__restore_interrupts(saved); return 2; /* Не сдвигает время подтверждения: неизменные данные всё равно повторятся по таймеру. */
} /* Изменение данных не ждёт окончания периода повторения. */
can_pending_addr = Addr; /* Подготовленное состояние попадёт в кэш только после успешного аппаратного ACK. */
} /* Для heartbeat и данных используется один и тот же безопасный жизненный цикл TX. */
ECanaRegs.CANTA.all = 1UL; ECanaRegs.CANAA.all = 1UL; /* Очищает старые ACK и отмену mailbox 0 записью единиц в соответствующие биты eCAN. */
ECanaMboxes.MBOX0.MDH.all = hiword; ECanaMboxes.MBOX0.MDL.all = loword; /* Записывает замороженный трёхсловный снимок без последующей подмены во время ожидания ACK. */
EALLOW; ECanaRegs.CANTOC.all &= ~1UL; ECanaRegs.CANTSC = 0UL; ECanaRegs.CANTOC.all |= 1UL; EDIS; /* Перезапускает аппаратный timeout только для нового штатного запроса TX. */
can_tx_at = now; can_tx_failed = 0U; wait = 1; /* Сохраняет момент запуска и принадлежность будущего ACK до разрешения прерываний. */
ECanaRegs.CANTRS.all = 1UL; /* Однократно запускает аппаратную передачу в штатном mailbox 0. */
led1_toggle(); __restore_interrupts(saved); /* Сохраняет индикацию передачи и возвращает исходную маску IRQ без ожидания шины. */
return 1; /* Подтверждает только постановку кадра, оставляя окончательную доставку аппаратному ACK. */
} /* Формат CAN ID, порядок слов и служебный mailbox логгера остаются прежними. */
void CAN_heartbeat_service(void) /* Обслуживает независимый секундный heartbeat и завершение ранее запущенного TX. */
{ /* Вызывается из main и не зависит от Cancount, масок данных или признака CanGO. */
Uint32 now = CAN_millis(), elapsed, seconds; /* Время Timer1 учитывает задержки main без накопления дрейфа секундной сетки. */
unsigned int saved = __disable_interrupts(); /* Короткая обработка ACK синхронизируется с timeout ISR. */
CAN_tx_ready(now); __restore_interrupts(saved); /* Сохраняет успешное завершение данных даже тогда, когда новых пакетов пока нет. */
if (!can_started) { can_started = 1U; can_heartbeat_at = can_scan_at = now; } /* Первый heartbeat появляется спустя полную секунду от начала обслуживания текущего запуска. */
elapsed = now - can_heartbeat_at; /* Беззнаковое вычитание корректно при переполнении 32-битного счётчика. */
if (elapsed >= CAN_HEARTBEAT_TICKS) { /* Формирует новую отметку на каждой секундной границе Timer1. */
seconds = elapsed / CAN_HEARTBEAT_TICKS; can_heartbeat_at += seconds * CAN_HEARTBEAT_TICKS; /* После паузы main оставляет последнее значение без очереди устаревших кадров. */
can_heartbeat_count = (unsigned int)((can_heartbeat_count + seconds) & 0xFFFFUL); can_heartbeat_due = 1U; /* Счётчик heartbeat циклически проходит диапазон 0..65535 секунд. */
} /* Занятый передатчик не теряет ожидающий heartbeat. */
if (can_heartbeat_due && CAN_send(0, 0, CAN_HEARTBEAT_ADDR) == 1) can_heartbeat_due = 0U; /* Приоритетно ставит один актуальный heartbeat после освобождения mailbox. */
} /* Следующий повтор heartbeat планируется секундной сеткой, а не длительностью обхода масок. */
void CAN_telemetry_service(void) /* Передаёт изменившиеся данные и повторяет каждый подтверждённый пакет через 1,3 с. */
{ /* Фоновое обслуживание не ждёт CAN ACK и выдаёт готовую очередь по мере освобождения mailbox. */
Uint32 now; unsigned int attempt, stream, pass, address, cursor; int result; /* Локальные счётчики ограничивают обход двумя потоками и конечной картой из 128 регистров. */
CAN_heartbeat_service(); now = CAN_millis(); /* Секундный heartbeat получает приоритет перед обычными данными независимо от настройки потоков. */
if (now - can_scan_at >= CAN_SCAN_TICKS) { can_scan_at += (now - can_scan_at) / CAN_SCAN_TICKS * CAN_SCAN_TICKS; can_scan_due = 1U; } /* Сохраняет сетку обнаружения изменений с интервалом 20 мс без накопления дрейфа после задержек main. */
if (!can_scan_due) return; /* При неизменных данных main не повторяет полный обход масок на каждой итерации. */
for (attempt = 0U; attempt < 2U; ++attempt) { /* После успешной постановки чередует потоки, исключая голодание медленной маски. */
stream = (can_stream + attempt) & 1U; cursor = can_cursor[stream]; /* Начинает следующий поиск после последнего принятого кадра данного потока. */
if (!Cancount[stream]) continue; /* Ноль сохраняет штатное отключение соответствующего потока; ненулевой период заменяется общим повтором 1,3 с. */
for (pass = 0U; pass < 2U; ++pass) { /* Два конечных прохода реализуют циклический обход без зависания на пустой маске. */
for (address = 0U; address < ANSWER_LEN;) { /* Формирует те же трёхсловные группы от первого разрешённого адреса маски. */
if (!(Maska[stream][address >> 4] & (1U << (address & 15)))) { ++address; continue; } /* Пропускает запрещённые регистры и гарантированно продвигает поиск. */
if ((pass == 0U && address >= cursor) || (pass == 1U && address < cursor)) { /* Сначала рассматривает хвост карты после курсора, затем оставшееся начало. */
result = CAN_send(0, modbus, address); /* Сравнивает полный снимок с подтверждённым кэшем и индивидуальным временем повтора. */
if (result != 2) { /* Только неизменный пакет до срока допускает переход к следующему кандидату в этом же вызове. */
if (result == 1) { can_cursor[stream] = address + 3U < ANSWER_LEN ? address + 3U : 0U; can_stream = stream ^ 1U; } /* Продвигает курсор лишь после постановки кадра и отдаёт следующий свободный слот другому потоку. */
return; /* При занятости сохраняет адрес; при постановке продолжит готовую очередь следующей итерацией main после ACK. */
} /* Пропущенные неизменные пакеты не занимают физическую шину. */
} /* Завершает проверку одного допустимого начального адреса. */
address += 3U; /* Как прежний протокол, один кадр покрывает три последовательных регистра независимо от разреженности маски. */
} /* Максимальный адрес ограничен размером реальной технологической карты. */
} /* После обхода обеих частей все пакеты потока рассмотрены ровно один раз. */
} /* Ни один разрешённый пакет не требует немедленной передачи. */
can_scan_due = 0U; /* Следующее плановое сканирование произойдёт через 20 мс; выдача готовой очереди этим ожиданием не задерживается. */
} /* Период 1,3 с относится к каждому пакету, а не к одному кадру всей маски за один период. */
#endif /* Закрывает единственную реализацию фоновой телеметрии текущей прошивки 166. */

View File

@@ -1,5 +1,5 @@
/* Собственный, общий и специальные адреса последовательного обмена. /* Собственный, общий и специальные адреса последовательного обмена.
* main задаёт адреса через set_cntrl_addr до начала обмена. * main задаёт адреса через set_cntrl_addr до начала обмена.
*/ */
#ifndef _CNTRL_ADR #ifndef _CNTRL_ADR
#define _CNTRL_ADR #define _CNTRL_ADR
@@ -8,22 +8,22 @@
extern "C" { extern "C" {
#endif #endif
/** адрес контроллера дла посылки всем АИНам */ /** адрес контроллера дла посылки всем АИНам */
extern int ADDR_FOR_ALL; extern int ADDR_FOR_ALL;
/** адрес контроллера дла посылки ответа */ /** адрес контроллера дла посылки ответа */
extern const int ADDR_ANSWER; extern const int ADDR_ANSWER;
/** адреса терминала дла посылки ответа */ /** адреса терминала дла посылки ответа */
extern const int ADDR_TERMINAL; extern const int ADDR_TERMINAL;
/* Адрес контроллера */ /* Адрес контроллера */
extern int CNTRL_ADDR; extern int CNTRL_ADDR;
/* Универсальный адрес контроллера */ /* Универсальный адрес контроллера */
extern const int CNTRL_ADDR_UNIVERSAL; extern const int CNTRL_ADDR_UNIVERSAL;
/** Установка адреса контроллера дла прошивки */ /** Установка адреса контроллера дла прошивки */
void set_cntrl_addr (int cntrl_addr,int cntrl_addr_for_all); void set_cntrl_addr (int cntrl_addr,int cntrl_addr_for_all);

View File

@@ -1,5 +1,5 @@
/* Интерфейсы CRC. Различать буфер кадра и массив слов EEPROM; /* Интерфейсы CRC. Различать буфер кадра и массив слов EEPROM;
* результат зависит от порядка обработки байтов. * результат зависит от порядка обработки байтов.
*/ */
typedef unsigned short WORD; typedef unsigned short WORD;
typedef unsigned char byte; typedef unsigned char byte;

View File

@@ -1,9 +1,11 @@
/* Телеметрия eCAN и фоновая выдача ответов логгера. /* Телеметрия eCAN и фоновая выдача ответов логгера.
* UMP_CAN_service вызывается из main, не из приёмного IRQ. * UMP_CAN_service вызывается из main, не из приёмного IRQ.
*/ */
void InitCan(int Port, int DevNum); void InitCan(int Port, int DevNum);
void CAN_send(int Port, int data[], int Addr); int CAN_send(int Port, int data[], int Addr); /* 0: занят, 1: кадр поставлен, 2: подтверждённые данные не изменились и 1,3 с ещё не прошли. */
void CAN_heartbeat_service(void); /* Планирует отдельный heartbeat по Timer1 с периодом одна секунда. */
void CAN_telemetry_service(void); /* В main обслуживает heartbeat, изменения данных и повтор каждого разрешённого пакета через 1,3 с. */
extern int CAN_input_data[]; extern int CAN_input_data[];
/* Неблокирующая передача ответов логгера отдельным CAN mailbox. */ /* Неблокирующая передача ответов логгера отдельным CAN mailbox. */
void UMP_CAN_service(void); void UMP_CAN_service(void);

View File

@@ -1,5 +1,5 @@
/* Коэффициенты и изменяемая история фильтра. Каждый независимый /* Коэффициенты и изменяемая история фильтра. Каждый независимый
* канал должен иметь отдельный экземпляр FILTERBAT. * канал должен иметь отдельный экземпляр FILTERBAT.
*/ */
#ifndef _FILTER_BAT2 #ifndef _FILTER_BAT2
#define _FILTER_BAT2 #define _FILTER_BAT2

View File

@@ -0,0 +1,10 @@
#ifndef BALSAM_FIRMWARE_INFO_H /* Исключает повторное объявление адаптера паспорта при совместном подключении RS и CAN. */
#define BALSAM_FIRMWARE_INFO_H /* Обозначает единственный интерфейс firmware-info v1 приложения 166. */
#include "firmware_info_static.h" /* Использует тот же статический 12-словный контракт общей библиотеки, который подключён в 167. */
#define FIRMWARE_INFO_ADDRESS 0x1200U /* Адрес firmware-info v1 из протокола 167 и SetGUI; не пересекается с логгером 0x1000..0x117B. */
#define FIRMWARE_INFO_END (FIRMWARE_INFO_ADDRESS + FIRMWARE_INFO_STATIC_COUNT) /* Исключающая верхняя граница 0x120C охватывает ровно двенадцать 16-битных регистров. */
static unsigned int firmware_info_range(unsigned int address, unsigned int count) /* Проверяет только чтение внутри паспорта без переполнения 16-битной суммы адреса и длины. */
{ /* Вычитание выполняется после проверки адреса, поэтому не переполняется на C28x. */
return address >= FIRMWARE_INFO_ADDRESS && address < FIRMWARE_INFO_END && count > 0U && count <= FIRMWARE_INFO_END - address; /* Разрешает полное и частичное чтение, запрещая нулевую длину и пересечение границы паспорта. */
} /* Не меняет правила остальных технологических и служебных адресов. */
#endif /* Завершает адаптер, не добавляя изменяемое состояние или параметры EEPROM. */

View File

@@ -1,4 +1,4 @@
/* Интерфейс канала индикации. Он не формирует START_DPTB /* Интерфейс канала индикации. Он не формирует START_DPTB
* и не должен использоваться вместо функций управления нагрузкой. * и не должен использоваться вместо функций управления нагрузкой.
*/ */
void kanal_Send(int adr, long dat, int dot); void kanal_Send(int adr, long dat, int dot);

View File

@@ -1,5 +1,5 @@
/* Контракт логгера с SetGUI: размер записи, версия и адреса. /* Контракт логгера с SetGUI: размер записи, версия и адреса.
* Чтение целого блока защищается от IRQ на стороне RS/CAN обработчика. * Чтение целого блока защищается от IRQ на стороне RS/CAN обработчика.
*/ */
#ifndef _LOG_TO_MEM #ifndef _LOG_TO_MEM
#define _LOG_TO_MEM #define _LOG_TO_MEM
@@ -8,11 +8,11 @@
extern "C" { extern "C" {
#endif #endif
/* Определениa длa работы логгера */ /* Определениa длa работы логгера */
#define LOG_PAGE_START 0x0200000 #define LOG_PAGE_START 0x0200000
#define LOG_PAGE_LEN 0xFA00 #define LOG_PAGE_LEN 0xFA00
extern int no_write, never_write; // Флаги, чтобы не писать (если что) extern int no_write, never_write; // Флаги, чтобы не писать (если что)
typedef struct typedef struct
{ {
@@ -25,22 +25,25 @@ typedef struct
extern LOG Log; extern LOG Log;
/* Запись словa в памать, где логи лежат */ /* Запись словa в памать, где логи лежат */
#define Log_to_mem(x) *(int *)(Log.Adres++) = x #define Log_to_mem(x) *(int *)(Log.Adres++) = x
/* Проверка границы памати дла логов */ /* Проверка границы памати дла логов */
#define Test_mem_limit(x) if(Log.Adres > (Log.Finis - (x))) Log.Adres = Log.Start #define Test_mem_limit(x) if(Log.Adres > (Log.Finis - (x))) Log.Adres = Log.Start
/* Очистка памати (обнуление) */ /* Очистка памати (обнуление) */
void clear_mem(); void clear_mem();
/* Логгер УМП: отдельное адресное пространство Modbus, без изменения /* Логгер УМП: отдельное адресное пространство Modbus, без изменения
* 128 технологических регистров. Два банка по 800 записей: * 128 технологических регистров. Два банка по 800 записей:
* текущий кольцевой журнал и зафиксированный фрагмент отключения. */ * текущий кольцевой журнал и зафиксированный фрагмент отключения. */
#define UMP_LOG_BASE 0x1000U #define UMP_LOG_BASE 0x1000U
#define UMP_LOG_DATA 0x1010U #define UMP_LOG_DATA 0x1010U
#define UMP_LOG_WORDS 40U /* Формат v4 совпадает с 167: 12 слов по 16 бит содержат выбранные сигналы и нулевой резерв для парной передачи CAN. */
#define UMP_LOG_WORDS 12U
#define UMP_LOG_CAPACITY 800U #define UMP_LOG_CAPACITY 800U
/* Онлайн-окно вмещает 120 слов полезных данных: при формате v4 это десять полных записей. */
#define UMP_LOG_LIVE_RECORDS (120U / UMP_LOG_WORDS)
#define UMP_LOG_LIVE 0x1100U #define UMP_LOG_LIVE 0x1100U
extern unsigned int ump_dac_ramp, ump_dac_duration, ump_dac_go10, ump_dac_stop10, ump_dac_position; extern unsigned int ump_dac_ramp, ump_dac_duration, ump_dac_go10, ump_dac_stop10, ump_dac_position;
void ump_log_tick(void); void ump_log_tick(void);

View File

@@ -1,5 +1,5 @@
/* ×àñòîòû è ñîñòîÿíèÿ èçìåðåíèé. READY â 166 — ñ÷¸ò÷èê äî íóëÿ. /* Частоты и состояния измерений. READY в 166 — счётчик до нуля.
* READY_FREQ çàäà¸ò òàéìåð ÑÈÔÓ, DAC_FREQ — ðàñ÷¸ò ÖÀÏ. * READY_FREQ задаёт таймер СИФУ, DAC_FREQ — расчёт ЦАП.
*/ */
#ifndef _MEASURE #ifndef _MEASURE
#define _MEASURE #define _MEASURE
@@ -65,14 +65,14 @@ typedef union
#define NOER 0xE000//C #define NOER 0xE000//C
#define EROR 0x01FF #define EROR 0x01FF
#define READY_FREQ (500.0 * 2)// Ãö #define READY_FREQ (500.0 * 2)// Гц
#define BLINK_FREQ 2 // Ãö #define BLINK_FREQ 2 // Гц
#define BLINK_TIME (READY_FREQ / BLINK_FREQ) #define BLINK_TIME (READY_FREQ / BLINK_FREQ)
#define CANPOWSE 20 #define CANPOWSE 20
#define ADC_FREQ 3750 //3885.0//777//2000//20000 //777 //3885 // Ãö (777*5) #define ADC_FREQ 3750 //3885.0//777//2000//20000 //777 //3885 // Гц (777*5)
#define DAC_FREQ 200//5 // Ãö #define DAC_FREQ 200//5 // Гц
#define LOAD_TIME 30//15 // sec #define LOAD_TIME 30//15 // sec
@@ -87,23 +87,23 @@ extern unsigned int Caliber_time;
#define ZERO 27 #define ZERO 27
#define Cooling 5 // (°Ñ) Ãèñòåðåçèñ ïî ñíàòèþ ïåðåãðåâà #define Cooling 5 // (°С) Гистерезис по снатию перегрева
#define COSPi6 0.86602540378443864676372317075294 #define COSPi6 0.86602540378443864676372317075294
#define RADIX2 1.4142135623730950488016887242097 #define RADIX2 1.4142135623730950488016887242097
#define POWER_380 0 // ïèòàíèå 380Â #define POWER_380 0 // питание 380В
#define POWER_38O 1 // ïèòàíèå 380Â #define POWER_38O 1 // питание 380В
#define CURRENT 2 // òîê #define CURRENT 2 // ток
#define VOLTAGE 3 // íàïðàæåíèå #define VOLTAGE 3 // напражение
#define POWER_31 4 // ïèòàíèå 31Â #define POWER_31 4 // питание 31В
#define POWER_27 5 // ïèòàíèå 24Â #define POWER_27 5 // питание 24В
#define POWER_24 6 // ïèòàíèå 24Â #define POWER_24 6 // питание 24В
#define POWER_15 7 // ïèòàíèå 15Â #define POWER_15 7 // питание 15В
#define TERMO_AD 8 // òåðìîäàò÷èê ìåëêîñõåìà #define TERMO_AD 8 // термодатчик мелкосхема
extern int TPL_CANS,tpl_cans; extern int TPL_CANS,tpl_cans;

View File

@@ -1,5 +1,5 @@
/* Технологические регистры и Modbus. ANSWER_LEN ограничивает /* Технологические регистры и Modbus. ANSWER_LEN ограничивает
* массив modbus; адресом логгера 0x1000 индексировать его нельзя. * массив modbus; адресом логгера 0x1000 индексировать его нельзя.
*/ */
#ifndef MESSAGE_H #ifndef MESSAGE_H
#define MESSAGE_H #define MESSAGE_H
@@ -14,8 +14,8 @@ typedef unsigned char CHAR;
typedef struct typedef struct
{ {
unsigned char Address; // Адрес контроллера unsigned char Address; // Адрес контроллера
unsigned char Number; // Номер команды unsigned char Number; // Номер команды
BAITE byte0; BAITE byte0;
BAITE byte1; BAITE byte1;

View File

@@ -1,10 +1,16 @@
/* Макросы обращаются к общей карте modbus, не к локальным данным. /* Макросы обращаются к общей карте modbus, не к локальным данным.
* START/STOP читаются через volatile. Входящая запись слова 127 * START/STOP читаются через volatile. Входящая запись слова 127
* должна пройти UMP_commands_write для фиксации фронта. * должна пройти UMP_commands_write для фиксации фронта.
*/ */
#ifndef PACKAGE #ifndef PACKAGE
#define PACKAGE #define PACKAGE
/* Задаёт числовой код прямого порядка индикаторов, чтобы сравнение OBOROT в препроцессоре не заменяло неопределённое имя нулём. */
#define STRAIGHT 0
/* Отличающийся код обратного порядка выбирает ветку перестановки двух показаний в pulto.c. */
#define REVERSE 1
/* Выбирает исполнение 166: соответствующие калибровки и обратный порядок индикаторов задаются условными блоками ниже. */
#define BALSAM 165 #define BALSAM 165
#if BALSAM == 166 #if BALSAM == 166
@@ -84,13 +90,13 @@
#define bSecretBt Buttons.bit.bit1 #define bSecretBt Buttons.bit.bit1
#define bTermoCal Buttons.bit.bit2 #define bTermoCal Buttons.bit.bit2
#define Cancount (modbus+0x60) // пауза между I посылками CAN #define Cancount (modbus+0x60) // пауза между I посылками CAN
#define Bright (modbus+0x62) // аркость сигнальных лампочек #define Bright (modbus+0x62) // аркость сигнальных лампочек
#define Brightness modbus[0x62] // аркость сигнальных лампочек #define Brightness modbus[0x62] // аркость сигнальных лампочек
/* Не врема! /* Не врема!
#define DAC_go modbus[0x64] // начало зарада #define DAC_go modbus[0x64] // начало зарада
#define DAC_stop modbus[0x65] // конец зарада #define DAC_stop modbus[0x65] // конец зарада
*/ */
#define m_FAST 0 #define m_FAST 0
@@ -135,7 +141,7 @@
#define LastMode Modbus[126].all #define LastMode Modbus[126].all
/* Слово меняется из CAN/RS; чтение команды не должно кешироваться. */ /* Слово меняется из CAN/RS; чтение команды не должно кешироваться. */
#define Commands (((volatile WORDE *)modbus)[127].all) #define Commands (((volatile WORDE *)modbus)[127].all)
#define cTestLamp Modbus[127].bit.bit0 #define cTestLamp Modbus[127].bit.bit0
#define cDefParam Modbus[127].bit.bit1 #define cDefParam Modbus[127].bit.bit1

View File

@@ -1,6 +1,6 @@
/* Физические GPIO с учётом режима и полярности. set означает /* Физические GPIO с учётом режима и полярности. set означает
* активировать функцию, не всегда выставить 1. START/STOP нагрузки * активировать функцию, не всегда выставить 1. START/STOP нагрузки
* активны единицей, RES_OUT_2 нулём. Дискретами владеет автомат СИФУ. * активны единицей, RES_OUT_2 нулём. Дискретами владеет автомат СИФУ.
*/ */
#include "DSP2833x_Device.h" // DSP281x Headerfile Include File #include "DSP2833x_Device.h" // DSP281x Headerfile Include File

View File

@@ -1,5 +1,5 @@
/* Состояния пульта dsk_EPLT. Обработчик таймера нагрузки /* Состояния пульта dsk_EPLT. Обработчик таймера нагрузки
* определён отдельно в measure.c. * определён отдельно в measure.c.
*/ */
//void what_is(void); //void what_is(void);

View File

@@ -1,11 +1,11 @@
/* Автомат SPI EEPROM продвигает таймер 2. Синхронное ожидание /* Автомат SPI EEPROM продвигает таймер 2. Синхронное ожидание
* требует разрешённых IRQ. PAGE_LEN/WORD_LEN задают адресацию страниц. * требует разрешённых IRQ. PAGE_LEN/WORD_LEN задают адресацию страниц.
*/ */
#ifndef __SPISE2P_H__ #ifndef __SPISE2P_H__
#define __SPISE2P_H__ #define __SPISE2P_H__
// Ёмкость памати в байтах // Ёмкость памати в байтах
#define SEEPROM_LEN 0x10000 #define SEEPROM_LEN 0x10000
#define NULL 0 #define NULL 0
@@ -97,25 +97,25 @@ void spiSe2pRead(SPISE2P_DRV *se2p, SE2P_DATA *data);
#define WORD_LEN 1 #define WORD_LEN 1
#endif #endif
/* Установка драйвера сериальной EEPROM. ** /* Установка драйвера сериальной EEPROM. **
** Инициализациа SPI и проч. Также настройка таймера. ** ** Инициализациа SPI и проч. Также настройка таймера. **
** Драйвер работает на прерываниах от таймера 2! */ ** Драйвер работает на прерываниах от таймера 2! */
void InitSeeprom(void); void InitSeeprom(void);
/* Запись блока в SEEPROM. Параметры таковы: ** /* Запись блока в SEEPROM. Параметры таковы: **
** adres - адрес в епромке, куда писать. ** ** adres - адрес в епромке, куда писать. **
** adres = 0..0x8000, если длина слова 8 бит ** ** adres = 0..0x8000, если длина слова 8 бит **
** adres = 0..0x4000, если длина слова 16 бит ** ** adres = 0..0x4000, если длина слова 16 бит **
** buf - указатель на памать, откуда писать. ** ** buf - указатель на памать, откуда писать. **
** size - длина блока в байтах. По-любому в байтах! */ ** size - длина блока в байтах. По-любому в байтах! */
void Seeprom_write(unsigned int adres, unsigned int buf[], unsigned int size); void Seeprom_write(unsigned int adres, unsigned int buf[], unsigned int size);
/* Чтение блока из SEEPROM. Параметры таковы: ** /* Чтение блока из SEEPROM. Параметры таковы: **
** adres - адрес в епромке, откуда читать. ** ** adres - адрес в епромке, откуда читать. **
** adres = 0..0x8000, если длина слова 8 бит ** ** adres = 0..0x8000, если длина слова 8 бит **
** adres = 0..0x4000, если длина слова 16 бит ** ** adres = 0..0x4000, если длина слова 16 бит **
** buf - указатель на памать, куда читать. ** ** buf - указатель на памать, куда читать. **
** size - длина блока в байтах. По-любому в байтах! */ ** size - длина блока в байтах. По-любому в байтах! */
void Seeprom_read(unsigned int adres, unsigned int buf[], unsigned int size); void Seeprom_read(unsigned int adres, unsigned int buf[], unsigned int size);
#endif #endif

View File

@@ -1,5 +1,5 @@
/* Инициализация памяти и задержки. pause_us не использовать /* Инициализация памяти и задержки. pause_us не использовать
* для длительности дискретов; их отсчитывает аппаратный таймер. * для длительности дискретов; их отсчитывает аппаратный таймер.
*/ */
#ifndef TOOLS_H #ifndef TOOLS_H
#define TOOLS_H #define TOOLS_H

View File

@@ -1,28 +1,34 @@
/* Служебный CAN-протокол логгера УМП. Не использует адреса 0..127 /* Служебный CAN-протокол логгера УМП. Не использует адреса 0..127
* технологического обмена. Формат полезных данных совместим с порядком * технологического обмена. Формат полезных данных совместим с порядком
* слов старого CAN: MDL (слова 1,2), затем MDH (маркер, слово 0). * слов старого CAN: MDL (слова 1,2), затем MDH (маркер, слово 0).
* Запрос: маркер 0x1F00, слово 0 = token:8 | function:8, * Запрос: маркер 0x1F00, слово 0 = token:8 | function:8,
* слова 1,2 = адрес расширения и число слов/записываемое значение. * слова 1,2 = адрес расширения и число слов/записываемое значение.
* Ответы: маркер 0x1F00 + номер фрагмента, слово 0 = token:8 | error:8, * Ответы: маркер 0x1F00 + номер фрагмента, слово 0 = token:8 | error:8,
* слова 1,2 = два слова единого зафиксированного снимка. * слова 1,2 = два слова единого зафиксированного снимка.
* Биты маски записи в заголовке запроса равны нулю: старая плата * Биты маски записи в заголовке запроса равны нулю: старая плата
* игнорирует запрос, не изменяя технологические регистры. */ * игнорирует запрос, не изменяя технологические регистры. */
#ifndef UMP_CAN_PROTOCOL_H #ifndef UMP_CAN_PROTOCOL_H
#define UMP_CAN_PROTOCOL_H #define UMP_CAN_PROTOCOL_H
#include "log_to_mem.h" #include "log_to_mem.h"
#include "firmware_info.h" /* Использует то же окно firmware-info v1, что FC03, сохраняя остальной служебный CAN-протокол 166. */
#define UMP_CAN_MARKER 0x1F00U #define UMP_CAN_MARKER 0x1F00U
#define UMP_CAN_MAX_WORDS 124U #define UMP_CAN_MAX_WORDS 124U
/* Вызывающий код защищает весь снимок от IRQ. Функция не ждёт CAN и /* Вызывающий код защищает весь снимок от IRQ. Функция не ждёт CAN и
* не пишет за пределами reply[124]. Ошибки возвращаются отдельным кадром. */ * не пишет за пределами reply[124]. Ошибки возвращаются отдельным кадром. */
static unsigned int ump_can_prepare(unsigned int function, unsigned int address, static unsigned int ump_can_prepare(unsigned int function, unsigned int address,
unsigned int value, unsigned int *reply, unsigned int *error) unsigned int value, unsigned int *reply, unsigned int *error)
{ {
unsigned int i; unsigned int i;
*error = 0; *error = 0;
if (function == 3) { if (function == 3) {
if (firmware_info_range(address, value)) { /* Признаёт только чтение внутри нового двенадцатисловного паспорта. */
for (i = 0; i < value; ++i) reply[i] = firmware_info_static_read(address - FIRMWARE_INFO_ADDRESS + i); /* Общий статический упаковщик выдаёт те же слова, что RS, без чтения архива логгера. */
return value; /* Передаёт паспорт существующему механизму фрагментов CAN без изменения mailbox, ID и повторов. */
} /* Все остальные запросы продолжают проходить прежнюю проверку окон логгера v4. */
if (!((address == UMP_LOG_BASE && value == 16) || if (!((address == UMP_LOG_BASE && value == 16) ||
(address == UMP_LOG_DATA && (value == 40 || value == 80 || value == 120)) || /* Разрешает от одной до десяти целых 12-словных записей v4 в пределах 120 слов полезного окна CAN. */
(address == UMP_LOG_DATA && value >= UMP_LOG_WORDS && value <= 120U && value % UMP_LOG_WORDS == 0U) ||
(address == UMP_LOG_LIVE && value == 124))) *error = 2; (address == UMP_LOG_LIVE && value == 124))) *error = 2;
else { else {
for (i = 0; i < value; i++) reply[i] = ump_log_read(address+i); for (i = 0; i < value; i++) reply[i] = ump_log_read(address+i);
@@ -32,7 +38,7 @@ static unsigned int ump_can_prepare(unsigned int function, unsigned int address,
if (address < UMP_LOG_BASE || address > UMP_LOG_BASE+3) *error = 2; if (address < UMP_LOG_BASE || address > UMP_LOG_BASE+3) *error = 2;
else if (!ump_log_write(address, value)) *error = 3; else if (!ump_log_write(address, value)) *error = 3;
} else *error = 1; } else *error = 1;
/* Для записи возвращаем эхо адреса и значения, для ошибки — её контекст. */ /* Для записи возвращаем эхо адреса и значения, для ошибки — её контекст. */
reply[0] = address; reply[1] = value; reply[0] = address; reply[1] = value;
return 2; return 2;
} }

View File

@@ -1,18 +1,18 @@
/* Подключается только из DAC.c; в host-тесте — с подменой GPIO/IRQ. */ /* Подключается только из DAC.c; в host-тесте — с подменой GPIO/IRQ. */
#ifndef UMP_CONTROL_IMPL_H #ifndef UMP_CONTROL_IMPL_H
#define UMP_CONTROL_IMPL_H #define UMP_CONTROL_IMPL_H
/* Аппаратная обёртка автомата. Храним её в существующем DAC.c, чтобы /* Аппаратная обёртка автомата. Храним её в существующем DAC.c, чтобы
* старый проект CCS и новый CCS12 собирали одинаковый набор исходников. * старый проект CCS и новый CCS12 собирали одинаковый набор исходников.
* Все входы ниже сохраняют прежнюю маску IRQ; нельзя просто делать EINT * Все входы ниже сохраняют прежнюю маску IRQ; нельзя просто делать EINT
* при выходе, поскольку вызов возможен из уже защищённого обработчика. */ * при выходе, поскольку вызов возможен из уже защищённого обработчика. */
static volatile UMP_PULSE_STATE ump_pulse; static volatile UMP_PULSE_STATE ump_pulse;
static volatile unsigned int ump_pulse_enabled; static volatile unsigned int ump_pulse_enabled;
static void UMP_apply_outputs(unsigned int previous_output, unsigned int previous_relay) static void UMP_apply_outputs(unsigned int previous_output, unsigned int previous_relay)
{ {
if (previous_output != ump_pulse.output) { if (previous_output != ump_pulse.output) {
/* Сначала снимаем старый сигнал, затем выставляем новый. /* Сначала снимаем старый сигнал, затем выставляем новый.
* Промежуточное состояние — оба выключены, а не оба включены. */ * Промежуточное состояние — оба выключены, а не оба включены. */
clear_START_DPTB(); clear_START_DPTB();
clear_STOP_DPTB(); clear_STOP_DPTB();
if (ump_pulse.output == UMP_PULSE_START) set_START_DPTB(); if (ump_pulse.output == UMP_PULSE_START) set_START_DPTB();
@@ -22,8 +22,8 @@ static void UMP_apply_outputs(unsigned int previous_output, unsigned int previou
if (ump_pulse.relay) set_RES_OUT_2(); if (ump_pulse.relay) set_RES_OUT_2();
else clear_RES_OUT_2(); else clear_RES_OUT_2();
} }
/* Старое имя оставлено для протокола логгера. Это теперь отражение /* Старое имя оставлено для протокола логгера. Это теперь отражение
* таймера автомата, а не переменная, которую одновременно правит main. */ * таймера автомата, а не переменная, которую одновременно правит main. */
IMPowse = ump_pulse.remaining; IMPowse = ump_pulse.remaining;
} }
@@ -34,8 +34,8 @@ void UMP_pulse_init(void)
ump_pulse_init(&ump_pulse, Commands); ump_pulse_init(&ump_pulse, Commands);
clear_START_DPTB(); clear_STOP_DPTB(); clear_RES_OUT_2(); clear_START_DPTB(); clear_STOP_DPTB(); clear_RES_OUT_2();
IMPowse = 0; IMPowse = 0;
/* Разрешаем обработку только после загрузки параметров и настройки /* Разрешаем обработку только после загрузки параметров и настройки
* ЦАП. Команды до этой точки не исполняются задним числом. */ * ЦАП. Команды до этой точки не исполняются задним числом. */
ump_pulse_enabled = 1; ump_pulse_enabled = 1;
} }
__restore_interrupts(saved); __restore_interrupts(saved);
@@ -47,9 +47,9 @@ void UMP_commands_write(unsigned int commands)
unsigned int output = ump_pulse.output, relay = ump_pulse.relay; unsigned int output = ump_pulse.output, relay = ump_pulse.relay;
Commands = commands; Commands = commands;
if (Desk == dsk_LOAD && ump_pulse_enabled) { if (Desk == dsk_LOAD && ump_pulse_enabled) {
/* Выполняем фронт в момент принятия слова. Нет очереди, которую /* Выполняем фронт в момент принятия слова. Нет очереди, которую
* main должен опросить после длительного обращения к EEPROM. * main должен опросить после длительного обращения к EEPROM.
* Здесь только несколько операций с памятью/GPIO, без ожиданий. */ * Здесь только несколько операций с памятью/GPIO, без ожиданий. */
ump_pulse_accept(&ump_pulse, commands, (unsigned int)READY_FREQ); ump_pulse_accept(&ump_pulse, commands, (unsigned int)READY_FREQ);
UMP_apply_outputs(output, relay); UMP_apply_outputs(output, relay);
} }
@@ -70,11 +70,11 @@ void UMP_pulse_tick(void)
void UMP_reset_parameter_commands(void) void UMP_reset_parameter_commands(void)
{ {
unsigned int saved = __disable_interrupts(); unsigned int saved = __disable_interrupts();
/* EEPROM содержит параметры, но не является источником команд пуска. /* EEPROM содержит параметры, но не является источником команд пуска.
* Сохраняем последние принятые START/STOP и историю фронтов автомата. * Сохраняем последние принятые START/STOP и историю фронтов автомата.
* Нельзя обнулить их при Load/Default: таймер ЦАП читает тот же уровень, * Нельзя обнулить их при Load/Default: таймер ЦАП читает тот же уровень,
* а следующий повтор пакета с единицей не должен стать ложным фронтом. * а следующий повтор пакета с единицей не должен стать ложным фронтом.
* Другие режимы платы сохраняют прежнее поведение полного сброса. */ * Другие режимы платы сохраняют прежнее поведение полного сброса. */
if (Desk == dsk_LOAD) Commands &= UMP_START_MASK | UMP_STOP_MASK; if (Desk == dsk_LOAD) Commands &= UMP_START_MASK | UMP_STOP_MASK;
else Commands = 0; else Commands = 0;
__restore_interrupts(saved); __restore_interrupts(saved);

View File

@@ -1,8 +1,8 @@
/* Управление импульсами СИФУ. Чистый автомат без доступа к GPIO. /* Управление импульсами СИФУ. Чистый автомат без доступа к GPIO.
* Один и тот же код используется прошивкой и host-тестом. * Один и тот же код используется прошивкой и host-тестом.
* ВАЖНО: вызывающая сторона сериализует init/accept/tick запретом IRQ. * ВАЖНО: вызывающая сторона сериализует init/accept/tick запретом IRQ.
* volatile обеспечивает обращения к общему состоянию, но не заменяет * volatile обеспечивает обращения к общему состоянию, но не заменяет
* критическую секцию: обновление нескольких полей не является атомарным. * критическую секцию: обновление нескольких полей не является атомарным.
*/ */
#ifndef UMP_PULSE_H #ifndef UMP_PULSE_H
#define UMP_PULSE_H #define UMP_PULSE_H
@@ -21,10 +21,10 @@ typedef struct {
static void ump_pulse_init(volatile UMP_PULSE_STATE *s, unsigned int commands) static void ump_pulse_init(volatile UMP_PULSE_STATE *s, unsigned int commands)
{ {
/* Уже активная команда при окончании загрузки не является новым пуском. /* Уже активная команда при окончании загрузки не является новым пуском.
* Снимаем физические выходы отдельно в аппаратной обёртке. * Снимаем физические выходы отдельно в аппаратной обёртке.
* Если начальное слово нулевое, первая свежая единица будет принята: * Если начальное слово нулевое, первая свежая единица будет принята:
* больше не нужен случайный проход main, успевший прочитать ноль. */ * больше не нужен случайный проход main, успевший прочитать ноль. */
s->previous = commands; s->previous = commands;
s->remaining = 0; s->remaining = 0;
s->output = UMP_PULSE_NONE; s->output = UMP_PULSE_NONE;
@@ -35,23 +35,23 @@ static void ump_pulse_accept(volatile UMP_PULSE_STATE *s,
unsigned int commands, unsigned int ticks) unsigned int commands, unsigned int ticks)
{ {
unsigned int rising = commands & ~s->previous; unsigned int rising = commands & ~s->previous;
/* История относится к каждому принятому слову CAN/RS, а не к редким /* История относится к каждому принятому слову CAN/RS, а не к редким
* снимкам main. Поэтому даже 1->0->1 между проходами main замечается. * снимкам main. Поэтому даже 1->0->1 между проходами main замечается.
* Повторные пакеты с удерживаемой единицей не продлевают импульс. */ * Повторные пакеты с удерживаемой единицей не продлевают импульс. */
s->previous = commands; s->previous = commands;
if (commands & UMP_STOP_MASK) { if (commands & UMP_STOP_MASK) {
/* STOP имеет приоритет даже при одновременном фронте START. /* STOP имеет приоритет даже при одновременном фронте START.
* Его удержание запрещает новый START. Запрещённый пуск не ставим * Его удержание запрещает новый START. Запрещённый пуск не ставим
* в очередь: снятие STOP не должно неожиданно запускать СИФУ. */ * в очередь: снятие STOP не должно неожиданно запускать СИФУ. */
if (rising & UMP_STOP_MASK) { if (rising & UMP_STOP_MASK) {
s->output = UMP_PULSE_STOP; s->output = UMP_PULSE_STOP;
s->remaining = ticks; s->remaining = ticks;
s->relay = 0; s->relay = 0;
} }
} else if (rising & UMP_START_MASK) { } else if (rising & UMP_START_MASK) {
/* Новый START после снятия команды STOP переключает выходы. /* Новый START после снятия команды STOP переключает выходы.
* Новый фронт во время START продлевает существующий импульс, * Новый фронт во время START продлевает существующий импульс,
* как раньше; отдельный электрический фронт здесь не обещается. */ * как раньше; отдельный электрический фронт здесь не обещается. */
s->output = UMP_PULSE_START; s->output = UMP_PULSE_START;
s->remaining = ticks; s->remaining = ticks;
s->relay = 1; s->relay = 1;
@@ -60,9 +60,9 @@ static void ump_pulse_accept(volatile UMP_PULSE_STATE *s,
static void ump_pulse_tick(volatile UMP_PULSE_STATE *s) static void ump_pulse_tick(volatile UMP_PULSE_STATE *s)
{ {
/* Единственный владелец отсчёта — таймер 1 кГц. main не участвует /* Единственный владелец отсчёта — таймер 1 кГц. main не участвует
* в завершении импульса, поэтому EEPROM не растягивает его. * в завершении импульса, поэтому EEPROM не растягивает его.
* RES_OUT_2 сохраняет последнее состояние после конца импульса. */ * RES_OUT_2 сохраняет последнее состояние после конца импульса. */
if (s->remaining && --s->remaining == 0) if (s->remaining && --s->remaining == 0)
s->output = UMP_PULSE_NONE; s->output = UMP_PULSE_NONE;
} }

View File

@@ -1,8 +1,8 @@
/* Низкоуровневый UART двух портов. RX ISR собирает RS_Header, /* Низкоуровневый UART двух портов. RX ISR собирает RS_Header,
* TX ISR продолжает передачу. RS_DataReady передаёт готовый кадр * TX ISR продолжает передачу. RS_DataReady передаёт готовый кадр
* в main для проверки CRC; приём байтов ещё не означает исполнения. * в main для проверки CRC; приём байтов ещё не означает исполнения.
* RS_Send содержит ожидания UART и не относится к быстрому пути СИФУ. * RS_Send содержит ожидания UART и не относится к быстрому пути СИФУ.
* Размеры буферов нужно понимать с учётом 16-битной ABI C2000. * Размеры буферов нужно понимать с учётом 16-битной ABI C2000.
*/ */
//#include "big_dsp_module.h" //#include "big_dsp_module.h"
@@ -28,7 +28,7 @@ static char size_cmd15=1;
void RS_RX_Handler(RS_DATA *rs_arr); void RS_RX_Handler(RS_DATA *rs_arr);
void RS_TX_Handler(RS_DATA *rs_arr); void RS_TX_Handler(RS_DATA *rs_arr);
/** Обработчик прерываний UART - принато */ /** Обработчик прерываний UART - принато */
interrupt void RSA_RX_Handler(void) interrupt void RSA_RX_Handler(void)
{ {
// Set interrupt priority: // Set interrupt priority:
@@ -101,7 +101,7 @@ interrupt void RSB_TX_Handler(void)
PieCtrlRegs.PIEIER9.all = TempPIEIER; PieCtrlRegs.PIEIER9.all = TempPIEIER;
} }
/** Обработчик прерываний UART - принато */ /** Обработчик прерываний UART - принато */
void RS_RX_Handler(RS_DATA *rs_arr) void RS_RX_Handler(RS_DATA *rs_arr)
{ {
char Rc; char Rc;
@@ -109,16 +109,16 @@ void RS_RX_Handler(RS_DATA *rs_arr)
// led1_on(); // led1_on();
for(;;) // 'goto' это не оператор азыка С for(;;) // 'goto' это не оператор азыка С
{ {
if(!rs_arr->SciRegs->SCIRXST.bit.RXRDY) // Receiver ready flag if(!rs_arr->SciRegs->SCIRXST.bit.RXRDY) // Receiver ready flag
{ {
PieCtrlRegs.PIEACK.bit.ACK9 |= 1; PieCtrlRegs.PIEACK.bit.ACK9 |= 1;
rs_arr->SciRegs->SCIFFRX.bit.RXFFINTCLR=1; // Clear INT flag rs_arr->SciRegs->SCIFFRX.bit.RXFFINTCLR=1; // Clear INT flag
return; // кстати это единственный выход из прерываниа return; // кстати это единственный выход из прерываниа
} }
Rc = rs_arr->SciRegs->SCIRXBUF.bit.RXDT; // Читаем символ в любом случае Rc = rs_arr->SciRegs->SCIRXBUF.bit.RXDT; // Читаем символ в любом случае
if(rs_arr->SciRegs->SCIRXST.bit.RXERROR) // Receiver error flag if(rs_arr->SciRegs->SCIRXST.bit.RXERROR) // Receiver error flag
{ {
@@ -128,110 +128,110 @@ void RS_RX_Handler(RS_DATA *rs_arr)
continue; continue;
} }
if(rs_arr->RS_DataReady) continue; // Не забрали данные if(rs_arr->RS_DataReady) continue; // Не забрали данные
if (rs_arr->RS_Flag9bit==1) // дла RS485???????? if (rs_arr->RS_Flag9bit==1) // дла RS485????????
{ {
// Инициализируем переменные и флаги // Инициализируем переменные и флаги
rs_arr->RS_FlagBegin = true; // Ждем заголовок rs_arr->RS_FlagBegin = true; // Ждем заголовок
rs_arr->RS_RecvLen = 0; rs_arr->RS_RecvLen = 0;
rs_arr->RS_FlagSkiping = false; rs_arr->RS_FlagSkiping = false;
rs_arr->RS_HeaderCnt = 0; rs_arr->RS_HeaderCnt = 0;
rs_arr->RS_Cmd = 0; rs_arr->RS_Cmd = 0;
} }
if(rs_arr->RS_FlagSkiping) continue; // Не нам if(rs_arr->RS_FlagSkiping) continue; // Не нам
if (rs_arr->RS_FlagBegin) // Заголовок if (rs_arr->RS_FlagBegin) // Заголовок
{ {
if (rs_arr->RS_HeaderCnt==0) // Адрес контроллера или стандартнаа команда if (rs_arr->RS_HeaderCnt==0) // Адрес контроллера или стандартнаа команда
{ {
if( (Rc == CNTRL_ADDR_UNIVERSAL) || (Rc == CNTRL_ADDR && CNTRL_ADDR!=0) || ((Rc == rs_arr->addr_answer) && rs_arr->flag_LEADING) if( (Rc == CNTRL_ADDR_UNIVERSAL) || (Rc == CNTRL_ADDR && CNTRL_ADDR!=0) || ((Rc == rs_arr->addr_answer) && rs_arr->flag_LEADING)
|| ((Rc == ADDR_FOR_ALL && ADDR_FOR_ALL!=0) && !rs_arr->flag_LEADING)) || ((Rc == ADDR_FOR_ALL && ADDR_FOR_ALL!=0) && !rs_arr->flag_LEADING))
{ {
rs_arr->addr_recive=Rc; // запомнили адрес по которому нас запросили rs_arr->addr_recive=Rc; // запомнили адрес по которому нас запросили
rs_arr->RS_Header[rs_arr->RS_HeaderCnt++] = Rc; // Первый байт rs_arr->RS_Header[rs_arr->RS_HeaderCnt++] = Rc; // Первый байт
RS_SetBitMode(rs_arr,8); // перестроились в 8-бит режим RS_SetBitMode(rs_arr,8); // перестроились в 8-бит режим
} }
else else
{ {
rs_arr->RS_FlagSkiping = true; // Не нашему контроллеру rs_arr->RS_FlagSkiping = true; // Не нашему контроллеру
rs_arr->RS_FlagBegin = false; // остались в 9-бит режиме rs_arr->RS_FlagBegin = false; // остались в 9-бит режиме
// led1_off(); // led1_off();
} }
} }
else else
{ {
rs_arr->RS_Header[rs_arr->RS_HeaderCnt++] = Rc; // Второй байт и т.д. rs_arr->RS_Header[rs_arr->RS_HeaderCnt++] = Rc; // Второй байт и т.д.
if (rs_arr->RS_HeaderCnt == 7 && rs_arr->RS_Cmd==CMD_MODBUS_16 && !rs_arr->flag_LEADING) if (rs_arr->RS_HeaderCnt == 7 && rs_arr->RS_Cmd==CMD_MODBUS_16 && !rs_arr->flag_LEADING)
{ {
RS_Len[CMD_MODBUS_16] = (10+Rc); RS_Len[CMD_MODBUS_16] = (10+Rc);
} }
// если второй байт - это команда // если второй байт - это команда
if (rs_arr->RS_HeaderCnt == 2) if (rs_arr->RS_HeaderCnt == 2)
{ {
rs_arr->RS_Cmd = Rc; rs_arr->RS_Cmd = Rc;
// Проверка длины посылки // Проверка длины посылки
// CMD_LOAD - младшаа на данный момент // CMD_LOAD - младшаа на данный момент
// CMD_STD_ANS - старшаа на данный момент // CMD_STD_ANS - старшаа на данный момент
if ((rs_arr->RS_Cmd < CMD_MODBUS_3) || (rs_arr->RS_Cmd > CMD_STD_ANS) || (RS_Len[rs_arr->RS_Cmd]<3) if ((rs_arr->RS_Cmd < CMD_MODBUS_3) || (rs_arr->RS_Cmd > CMD_STD_ANS) || (RS_Len[rs_arr->RS_Cmd]<3)
|| ((rs_arr->RS_Cmd == CMD_LOAD)&&(rs_arr->RS_PrevCmd != CMD_INITLOAD)) || ((rs_arr->RS_Cmd == CMD_LOAD)&&(rs_arr->RS_PrevCmd != CMD_INITLOAD))
) )
{ {
RS_SetBitMode(rs_arr,9); // Получили все перестроились в 9-бит дла RS485? RS_SetBitMode(rs_arr,9); // Получили все перестроились в 9-бит дла RS485?
rs_arr->RS_HeaderCnt = 0; // Потому что команда не та rs_arr->RS_HeaderCnt = 0; // Потому что команда не та
rs_arr->RS_FlagBegin = true; rs_arr->RS_FlagBegin = true;
rs_arr->RS_FlagSkiping = false; rs_arr->RS_FlagSkiping = false;
rs_arr->RS_Cmd=0; rs_arr->RS_Cmd=0;
// led1_off(); // led1_off();
continue; continue;
} }
if (rs_arr->RS_Cmd == CMD_LOAD) // Дла этой команды заголовок очень короткий if (rs_arr->RS_Cmd == CMD_LOAD) // Дла этой команды заголовок очень короткий
rs_arr->RS_FlagBegin = false;// дальше идут данные rs_arr->RS_FlagBegin = false;// дальше идут данные
} }
if( (rs_arr->RS_HeaderCnt >= RS_Len[rs_arr->RS_Cmd]) || if( (rs_arr->RS_HeaderCnt >= RS_Len[rs_arr->RS_Cmd]) ||
(rs_arr->RS_HeaderCnt >= sizeof(rs_arr->RS_Header))) (rs_arr->RS_HeaderCnt >= sizeof(rs_arr->RS_Header)))
{ // Получили заголовок { // Получили заголовок
RS_SetBitMode(rs_arr,9); // Получили все перестроились в 9-бит дла RS485? RS_SetBitMode(rs_arr,9); // Получили все перестроились в 9-бит дла RS485?
rs_arr->RS_FlagBegin = false; rs_arr->RS_FlagBegin = false;
rs_arr->RS_FlagSkiping = true; rs_arr->RS_FlagSkiping = true;
rs_arr->RS_DataReady = true; rs_arr->RS_DataReady = true;
rs_arr->RS_Cmd=0; rs_arr->RS_Cmd=0;
// led1_off(); // led1_off();
} } } } } }
else // Поток данных else // Поток данных
{ {
if(rs_arr->pRS_RecvPtr<(unsigned int *)Rec_Bloc_Begin || rs_arr->pRS_RecvPtr>(unsigned int *)Rec_Bloc_End) if(rs_arr->pRS_RecvPtr<(unsigned int *)Rec_Bloc_Begin || rs_arr->pRS_RecvPtr>(unsigned int *)Rec_Bloc_End)
{ {
rs_arr->pRS_RecvPtr = (unsigned int *)Rec_Bloc_Begin; // На программу надейса, а сам не плошай rs_arr->pRS_RecvPtr = (unsigned int *)Rec_Bloc_Begin; // На программу надейса, а сам не плошай
rs_arr->pRecvPtr = (unsigned int *)Rec_Bloc_Begin; // На программу надейса, а сам не плошай rs_arr->pRecvPtr = (unsigned int *)Rec_Bloc_Begin; // На программу надейса, а сам не плошай
} }
if(rs_arr->RS_PrevCmd != CMD_INITLOAD) continue; // Мы здесь оказались по какой-то чудовищной ошибке if(rs_arr->RS_PrevCmd != CMD_INITLOAD) continue; // Мы здесь оказались по какой-то чудовищной ошибке
if(rs_arr->RS_DataReady) // Если данные в основном цикле не забраны, if(rs_arr->RS_DataReady) // Если данные в основном цикле не забраны,
{ // то пропускаем следующую посылку { // то пропускаем следующую посылку
rs_arr->RS_FlagSkiping = true; // Игнорируем до следующего заголовка rs_arr->RS_FlagSkiping = true; // Игнорируем до следующего заголовка
// led1_off(); // led1_off();
continue; continue;
} }
RS_BytePtr = rs_arr->RS_RecvLen++ % 2; RS_BytePtr = rs_arr->RS_RecvLen++ % 2;
if(RS_BytePtr) *rs_arr->pRS_RecvPtr++ |= Rc; // Получили слово if(RS_BytePtr) *rs_arr->pRS_RecvPtr++ |= Rc; // Получили слово
else *rs_arr->pRS_RecvPtr = Rc<<8; else *rs_arr->pRS_RecvPtr = Rc<<8;
if(rs_arr->RS_Length <= rs_arr->RS_RecvLen) // Конец посылки if(rs_arr->RS_Length <= rs_arr->RS_RecvLen) // Конец посылки
{ {
rs_arr->RS_PrevCmd = rs_arr->RS_Header[1] = CMD_LOAD; rs_arr->RS_PrevCmd = rs_arr->RS_Header[1] = CMD_LOAD;
RS_SetBitMode(rs_arr,9); // Получили все данные перестроились в 9-бит дла RS485? RS_SetBitMode(rs_arr,9); // Получили все данные перестроились в 9-бит дла RS485?
rs_arr->RS_FlagSkiping = true; // Игнорируем до следующего заголовка rs_arr->RS_FlagSkiping = true; // Игнорируем до следующего заголовка
rs_arr->RS_DataReady = true; // Флаг в основной цикл - данные получены rs_arr->RS_DataReady = true; // Флаг в основной цикл - данные получены
// led1_off(); // led1_off();
} } } } } } } }
/** Обработчик прерываний UART - послано */ /** Обработчик прерываний UART - послано */
void RS_TX_Handler(RS_DATA *rs_arr) void RS_TX_Handler(RS_DATA *rs_arr)
{ {
char RS_BytePtr; char RS_BytePtr;
@@ -241,19 +241,19 @@ void RS_TX_Handler(RS_DATA *rs_arr)
{ {
if(++rs_arr->RS_SendLen >= rs_arr->RS_SLength) if(++rs_arr->RS_SendLen >= rs_arr->RS_SLength)
{ {
enableUARTInt(rs_arr); /* Запрещаем прерываниа по передаче */ enableUARTInt(rs_arr); /* Запрещаем прерываниа по передаче */
} }
SCI_send(rs_arr,*(rs_arr->pRS_SendPtr++)); SCI_send(rs_arr,*(rs_arr->pRS_SendPtr++));
if(rs_arr->RS_SendLen >= rs_arr->RS_SLength) if(rs_arr->RS_SendLen >= rs_arr->RS_SLength)
{ {
RS_Wait4OK(rs_arr); RS_Wait4OK(rs_arr);
// for (i=0; i <= TIME_WAIT_RS_BYTE_OUT; i++){} /* Пауза дла PC */ // for (i=0; i <= TIME_WAIT_RS_BYTE_OUT; i++){} /* Пауза дла PC */
RS_SetBitMode(rs_arr,9); /* Передали все перестроились в 9-бит дла RS485?*/ RS_SetBitMode(rs_arr,9); /* Передали все перестроились в 9-бит дла RS485?*/
RS_Line_to_receive(rs_arr); /* режим приема RS485 */ RS_Line_to_receive(rs_arr); /* режим приема RS485 */
rs_arr->flag_TIMEOUT_to_Send=false; /* сбросили флаг ожиданиа таймаута */ rs_arr->flag_TIMEOUT_to_Send=false; /* сбросили флаг ожиданиа таймаута */
} }
} }
else /* BM_PACKED */ else /* BM_PACKED */
@@ -262,7 +262,7 @@ void RS_TX_Handler(RS_DATA *rs_arr)
RS_BytePtr = (rs_arr->RS_SendLen++) % 2; RS_BytePtr = (rs_arr->RS_SendLen++) % 2;
if(rs_arr->RS_SendLen >= rs_arr->RS_SLength) if(rs_arr->RS_SendLen >= rs_arr->RS_SLength)
{ {
enableUARTInt(rs_arr); /* Запрещаем прерываниа по передаче */ enableUARTInt(rs_arr); /* Запрещаем прерываниа по передаче */
} }
if(RS_BytePtr) SCI_send(rs_arr, LOBYTE( *(rs_arr->pRS_SendPtr++) )); if(RS_BytePtr) SCI_send(rs_arr, LOBYTE( *(rs_arr->pRS_SendPtr++) ));
else SCI_send(rs_arr, HIBYTE( *rs_arr->pRS_SendPtr )); else SCI_send(rs_arr, HIBYTE( *rs_arr->pRS_SendPtr ));
@@ -270,9 +270,9 @@ void RS_TX_Handler(RS_DATA *rs_arr)
if(rs_arr->RS_SendLen >= rs_arr->RS_SLength) if(rs_arr->RS_SendLen >= rs_arr->RS_SLength)
{ {
RS_Wait4OK(rs_arr); RS_Wait4OK(rs_arr);
// for (i=0; i <= TIME_WAIT_RS_BYTE_OUT; i++){} /* Пауза дла PC */ // for (i=0; i <= TIME_WAIT_RS_BYTE_OUT; i++){} /* Пауза дла PC */
// RS_SetBitMode(rs_arr,9); /* Передали все перестроились в 9-бит дла RS485?*/ // RS_SetBitMode(rs_arr,9); /* Передали все перестроились в 9-бит дла RS485?*/
// RS_Line_to_receive(); /* режим приема RS485 */ // RS_Line_to_receive(); /* режим приема RS485 */
} }
} }
@@ -281,7 +281,7 @@ void RS_TX_Handler(RS_DATA *rs_arr)
// rs_arr->SciRegs->SCIFFTX.bit.TXINTCLR=1; // Clear INT flag // rs_arr->SciRegs->SCIFFTX.bit.TXINTCLR=1; // Clear INT flag
} }
/** Инициализациа массива длин команд */ /** Инициализациа массива длин команд */
void setup_arr_cmd_length() void setup_arr_cmd_length()
{ {
int i; int i;
@@ -307,89 +307,89 @@ void setup_arr_cmd_length()
RS_Len[CMD_EXTEND] = 18; RS_Len[CMD_EXTEND] = 18;
} }
/** Настройка режима приема/передачи */ /** Настройка режима приема/передачи */
void RS_SetBitMode(RS_DATA *rs_arr,int n) void RS_SetBitMode(RS_DATA *rs_arr,int n)
{ {
if(n == 8) if(n == 8)
{ {
RS_SetLineMode(rs_arr,8,'N',1); /* режим линии */ RS_SetLineMode(rs_arr,8,'N',1); /* режим линии */
rs_arr->RS_Flag9bit=0; rs_arr->RS_Flag9bit=0;
} }
if(n == 9) if(n == 9)
{ {
RS_SetLineMode(rs_arr,8,'N',1); /* режим линии */ RS_SetLineMode(rs_arr,8,'N',1); /* режим линии */
rs_arr->RS_Flag9bit=1; rs_arr->RS_Flag9bit=1;
} } } }
/** Посылка блока байтов. /** Посылка блока байтов.
Посылает массива 32-битных целых чисел старшие биты должны быть 0. Посылает массива 32-битных целых чисел старшие биты должны быть 0.
@precondition Работа ф-ции зависит от макро RS_TRANSMIT_INTR @precondition Работа ф-ции зависит от макро RS_TRANSMIT_INTR
@param buf адрес массива @param buf адрес массива
@param len количество байт @param len количество байт
@see RS_BSend, RS_TRANSMIT_INTR */ @see RS_BSend, RS_TRANSMIT_INTR */
/* Передачу продолжает TX ISR. Здесь есть старые программные паузы /* Передачу продолжает TX ISR. Здесь есть старые программные паузы
* и ожидания UART: не вызывать из CAN ISR или секции автомата СИФУ. * и ожидания UART: не вызывать из CAN ISR или секции автомата СИФУ.
*/ */
int RS_Send(RS_DATA *rs_arr,unsigned int *pBuf,unsigned long len) int RS_Send(RS_DATA *rs_arr,unsigned int *pBuf,unsigned long len)
{ {
unsigned int i; unsigned int i;
for (i=0; i <= 30000; i++){} /* Пауза дла PC */ for (i=0; i <= 30000; i++){} /* Пауза дла PC */
RS_Line_to_send(rs_arr); /* режим передачи RS485 */ RS_Line_to_send(rs_arr); /* режим передачи RS485 */
for (i=0; i <= 10000; i++){} /* Пауза дла PC */ for (i=0; i <= 10000; i++){} /* Пауза дла PC */
rs_arr->RS_SLength = len; /* Настраиваем переменные */ rs_arr->RS_SLength = len; /* Настраиваем переменные */
rs_arr->pRS_SendPtr = pBuf + 1; rs_arr->pRS_SendPtr = pBuf + 1;
rs_arr->RS_SendBlockMode = BM_CHAR32; rs_arr->RS_SendBlockMode = BM_CHAR32;
RS_Wait4OK(rs_arr); /* Дожидаемса ухода */ RS_Wait4OK(rs_arr); /* Дожидаемса ухода */
RS_SetBitMode(rs_arr,8); /* Остальные в 8-бит режиме */ RS_SetBitMode(rs_arr,8); /* Остальные в 8-бит режиме */
rs_arr->RS_SendLen = 1; /* Два байта уже передали */ rs_arr->RS_SendLen = 1; /* Два байта уже передали */
if(len > 1) if(len > 1)
{ {
enableUARTIntW(rs_arr); /* Разрешаем прерываниа по передаче */ enableUARTIntW(rs_arr); /* Разрешаем прерываниа по передаче */
SCI_send(rs_arr, *pBuf); // Передаем второй байт по прерыванию SCI_send(rs_arr, *pBuf); // Передаем второй байт по прерыванию
} }
else else
{ {
SCI_send(rs_arr, *pBuf); // Передаем второй байт по прерыванию SCI_send(rs_arr, *pBuf); // Передаем второй байт по прерыванию
RS_Wait4OK(rs_arr); /* Дожидаемса ухода без прерываниа */ RS_Wait4OK(rs_arr); /* Дожидаемса ухода без прерываниа */
for (i=0; i <= TIME_WAIT_RS_BYTE_OUT; i++){} /* Пауза дла PC */ for (i=0; i <= TIME_WAIT_RS_BYTE_OUT; i++){} /* Пауза дла PC */
RS_SetBitMode(rs_arr,9); /* Обратно в 9-бит режим */ RS_SetBitMode(rs_arr,9); /* Обратно в 9-бит режим */
RS_Line_to_receive(rs_arr); /* режим приема RS485 */ RS_Line_to_receive(rs_arr); /* режим приема RS485 */
} }
return 0; return 0;
} }
// Посылка блока упакованных байтов // Посылка блока упакованных байтов
int RS_BSend(RS_DATA *rs_arr,unsigned int *pBuf, unsigned long len) int RS_BSend(RS_DATA *rs_arr,unsigned int *pBuf, unsigned long len)
{ {
RS_Line_to_send(rs_arr); // режим передачи RS485 RS_Line_to_send(rs_arr); // режим передачи RS485
rs_arr->RS_SLength = len; // Настраиваем переменные rs_arr->RS_SLength = len; // Настраиваем переменные
rs_arr->pRS_SendPtr = pBuf; rs_arr->pRS_SendPtr = pBuf;
rs_arr->RS_SendBlockMode = BM_PACKED; rs_arr->RS_SendBlockMode = BM_PACKED;
RS_Wait4OK(rs_arr); // Ожидаем очистки и ухода последнего байта RS_Wait4OK(rs_arr); // Ожидаем очистки и ухода последнего байта
RS_SetBitMode(rs_arr,8); /* Остальные в 8-бит режиме */ RS_SetBitMode(rs_arr,8); /* Остальные в 8-бит режиме */
rs_arr->RS_SendLen = 1; // Один байт уже передали rs_arr->RS_SendLen = 1; // Один байт уже передали
enableUARTIntW(rs_arr); /* Разрешаем прерываниа по передаче */ enableUARTIntW(rs_arr); /* Разрешаем прерываниа по передаче */
SCI_send(rs_arr,HIBYTE(*pBuf));// Передаем первый байт SCI_send(rs_arr,HIBYTE(*pBuf));// Передаем первый байт
return 0; return 0;
} }
/** Устанавливает скорость обмена. /** Устанавливает скорость обмена.
@param speed скорость RS в бод */ @param speed скорость RS в бод */
/** Устанавливает скорость обмена. /** Устанавливает скорость обмена.
@param speed скорость RS в бод */ @param speed скорость RS в бод */
void RS_SetLineSpeed(RS_DATA *rs_arr,unsigned long speed) void RS_SetLineSpeed(RS_DATA *rs_arr,unsigned long speed)
{ {
long SciBaud; long SciBaud;
@@ -403,7 +403,7 @@ void RS_SetLineSpeed(RS_DATA *rs_arr,unsigned long speed)
} }
/** Инициализациа последовательного порта */ /** Инициализациа последовательного порта */
void create_uart_vars(char size_cmd15_set) void create_uart_vars(char size_cmd15_set)
{ {
size_cmd15=size_cmd15_set; size_cmd15=size_cmd15_set;
@@ -413,7 +413,7 @@ void create_uart_vars(char size_cmd15_set)
/** Инициализациа последовательного порта */ /** Инициализациа последовательного порта */
void setup_uart(char commnumber, unsigned long speed_baud) void setup_uart(char commnumber, unsigned long speed_baud)
{ {
@@ -478,14 +478,14 @@ void setup_uart(char commnumber, unsigned long speed_baud)
SciRegs->SCICTL1.bit.RXENA=1; SciRegs->SCICTL1.bit.RXENA=1;
SciRegs->SCIFFTX.bit.SCIFFENA=0; // fifo off SciRegs->SCIFFTX.bit.SCIFFENA=0; // fifo off
SciRegs->SCIFFRX.bit.RXFFIL=1; // Длина наименьшей команды SciRegs->SCIFFRX.bit.RXFFIL=1; // Длина наименьшей команды
setup_arr_cmd_length(); setup_arr_cmd_length();
RS_SetLineSpeed(rs_arr,speed_baud); // скорость линии RS_SetLineSpeed(rs_arr,speed_baud); // скорость линии
RS_Line_to_receive(rs_arr); // режим приема RS485 RS_Line_to_receive(rs_arr); // режим приема RS485
enableUARTInt(rs_arr); // разрешение прерываний UART enableUARTInt(rs_arr); // разрешение прерываний UART
RS_SetBitMode(rs_arr,9); RS_SetBitMode(rs_arr,9);
rs_arr->RS_PrevCmd = 0; // не было никаких команд rs_arr->RS_PrevCmd = 0; // не было никаких команд
rs_arr->flag_TIMEOUT_to_Send = 0; rs_arr->flag_TIMEOUT_to_Send = 0;
rs_arr->flag_LEADING = 0; rs_arr->flag_LEADING = 0;
@@ -493,10 +493,10 @@ void setup_uart(char commnumber, unsigned long speed_baud)
SciRegs->SCICTL1.bit.SWRESET=1; // Relinquish SCI from Reset SciRegs->SCICTL1.bit.SWRESET=1; // Relinquish SCI from Reset
} }
/** Настройка режима линии. /** Настройка режима линии.
@param bit количество бит данных @param bit количество бит данных
@param parity режим четности (N,O,E,M,S) @param parity режим четности (N,O,E,M,S)
@param stop количество стоповых бит */ @param stop количество стоповых бит */
void RS_SetLineMode(RS_DATA *rs_arr, int bit, char parity, int stop) void RS_SetLineMode(RS_DATA *rs_arr, int bit, char parity, int stop)
{ {
volatile struct SCI_REGS *SciRegs; volatile struct SCI_REGS *SciRegs;
@@ -539,7 +539,7 @@ void clear_timer_rs_live(RS_DATA *rs_arr)
rs_arr->time_wait_rs_out=0; rs_arr->time_wait_rs_out=0;
} }
/* проверка на живучесть RS */ /* проверка на живучесть RS */
void test_rs_live(RS_DATA *rs_arr) void test_rs_live(RS_DATA *rs_arr)
{ {
/* if (rs_arr->time_wait_rs_out < RS_TIME_OUT) /* if (rs_arr->time_wait_rs_out < RS_TIME_OUT)
@@ -547,6 +547,6 @@ void test_rs_live(RS_DATA *rs_arr)
else else
{ {
rs_arr->time_wait_rs_out=0; rs_arr->time_wait_rs_out=0;
RS_Line_to_receive(rs_arr); // режим приема RS485 RS_Line_to_receive(rs_arr); // режим приема RS485
RS_SetBitMode(rs_arr,9); RS_SetBitMode(rs_arr,9);
}*/ } }*/ }

View File

@@ -1,8 +1,8 @@
/* Служебные команды доступа к памяти и загрузки. get_command /* Служебные команды доступа к памяти и загрузки. get_command
* проверяет завершённый RS-кадр и CRC перед диспетчеризацией в main. * проверяет завершённый RS-кадр и CRC перед диспетчеризацией в main.
* Произвольная запись памяти сервисной командой не проходит * Произвольная запись памяти сервисной командой не проходит
* автомат фронтов СИФУ. Формат CMD_* согласован с загрузчиком ПК; * автомат фронтов СИФУ. Формат CMD_* согласован с загрузчиком ПК;
* нельзя перенумеровывать команды при расширении протокола. * нельзя перенумеровывать команды при расширении протокола.
*/ */
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "RS485.h" #include "RS485.h"
@@ -14,14 +14,14 @@
//#include "spartan_tools.h" //#include "spartan_tools.h"
//#include "big_dsp_module.h" //#include "big_dsp_module.h"
int flag_DEBUG = false; /* Флаг отладочного режима */ int flag_DEBUG = false; /* Флаг отладочного режима */
//static unsigned int *RecvPtr; //static unsigned int *RecvPtr;
//static int BS_LoadOK = false; /** Флаг успешности приема блока */ //static int BS_LoadOK = false; /** Флаг успешности приема блока */
/**********************************************************/ /**********************************************************/
/* Прототипы функций, используемых и определенных в файле */ /* Прототипы функций, используемых и определенных в файле */
/**********************************************************/ /**********************************************************/
//static int _getbyte(int *addr, int offs); //static int _getbyte(int *addr, int offs);
@@ -36,60 +36,60 @@ void write_memory(unsigned long addr, unsigned int data)
} }
/** Возвращает номер комманды, если есть или -1 если транзакций не было */ /** Возвращает номер комманды, если есть или -1 если транзакций не было */
int get_command(RS_DATA *rs_arr) int get_command(RS_DATA *rs_arr)
{ {
int cmd; int cmd;
unsigned int crc, rcrc; unsigned int crc, rcrc;
if(rs_arr->RS_DataReady) // Данные по RS пришли if(rs_arr->RS_DataReady) // Данные по RS пришли
{ {
rs_arr->RS_DataReady = false; rs_arr->RS_DataReady = false;
cmd = rs_arr->RS_Header[1]; // Прочитали номер команды cmd = rs_arr->RS_Header[1]; // Прочитали номер команды
// Провераем длину команды дла считываниа CRC // Провераем длину команды дла считываниа CRC
if((RS_Len[cmd]<3) || (RS_Len[cmd]>MAX_RECEIVE_LENGTH)) if((RS_Len[cmd]<3) || (RS_Len[cmd]>MAX_RECEIVE_LENGTH))
{ {
RS_Line_to_receive(rs_arr); // режим приема RS485 RS_Line_to_receive(rs_arr); // режим приема RS485
RS_SetBitMode(rs_arr,9); RS_SetBitMode(rs_arr,9);
return -1; return -1;
} }
if(cmd == CMD_LOAD) // Если команда загрузки if(cmd == CMD_LOAD) // Если команда загрузки
{ {
rs_arr->RS_PrevCmd = cmd; rs_arr->RS_PrevCmd = cmd;
return cmd; // Нет проверки crc return cmd; // Нет проверки crc
} }
else // Все остальные команды else // Все остальные команды
{ {
// Считываем crc из посылки // Считываем crc из посылки
crc = (rs_arr->RS_Header[RS_Len[cmd]-1] << 8) | crc = (rs_arr->RS_Header[RS_Len[cmd]-1] << 8) |
(rs_arr->RS_Header[RS_Len[cmd]-2]) ; (rs_arr->RS_Header[RS_Len[cmd]-2]) ;
} }
// Рассчитываем crc из посылки // Рассчитываем crc из посылки
rcrc = 0xffff; rcrc = 0xffff;
rcrc = get_crc_16( rcrc, rs_arr->RS_Header, (RS_Len[cmd]-2) ); rcrc = get_crc_16( rcrc, rs_arr->RS_Header, (RS_Len[cmd]-2) );
if(crc == rcrc) // Провераем crc if(crc == rcrc) // Провераем crc
{ {
rs_arr->RS_PrevCmd = cmd; rs_arr->RS_PrevCmd = cmd;
return cmd; return cmd;
} }
else else
{ {
RS_Line_to_receive(rs_arr); // режим приема RS485 RS_Line_to_receive(rs_arr); // режим приема RS485
RS_SetBitMode(rs_arr,9); RS_SetBitMode(rs_arr,9);
} } } }
return -1; return -1;
} }
/** Стандартный ответ, без параметров */ /** Стандартный ответ, без параметров */
void Answer(RS_DATA *rs_arr,int n) void Answer(RS_DATA *rs_arr,int n)
{ {
int crc; int crc;
flag_DEBUG = true; // Флаг отладочного режима flag_DEBUG = true; // Флаг отладочного режима
rs_arr->buffer[0] = rs_arr->addr_recive; //CNTRL_ADDR; rs_arr->buffer[0] = rs_arr->addr_recive; //CNTRL_ADDR;
rs_arr->buffer[1] = n; rs_arr->buffer[1] = n;
@@ -105,7 +105,7 @@ void Answer(RS_DATA *rs_arr,int n)
RS_Send(rs_arr,rs_arr->buffer, 6); RS_Send(rs_arr,rs_arr->buffer, 6);
} }
/* Внутреннаа ф-циа */ /* Внутреннаа ф-циа */
static char _getbyte(unsigned int *addr, int32 offs) static char _getbyte(unsigned int *addr, int32 offs)
{ {
unsigned int *address; unsigned int *address;
@@ -118,7 +118,7 @@ static char _getbyte(unsigned int *addr, int32 offs)
} }
/* начальные установки (не работает)*/ /* начальные установки (не работает)*/
void init(RS_DATA *rs_arr) void init(RS_DATA *rs_arr)
{ {
/* /*
@@ -141,13 +141,13 @@ void init(RS_DATA *rs_arr)
*/ */
} }
/**@name Комманды /**@name Комманды
* Комманды, вызываемые через последовательный канал * Комманды, вызываемые через последовательный канал
*/ */
//@{ //@{
/** Инициировать загрузку блока. /** Инициировать загрузку блока.
Настраивает прием блока данных */ Настраивает прием блока данных */
void initload(RS_DATA *rs_arr) void initload(RS_DATA *rs_arr)
{ {
unsigned long Address; unsigned long Address;
@@ -171,8 +171,8 @@ void initload(RS_DATA *rs_arr)
Answer(rs_arr,CMD_INITLOAD); Answer(rs_arr,CMD_INITLOAD);
} }
/** Загрузка блока. /** Загрузка блока.
Вызываетса после загрузки блока через RS */ Вызываетса после загрузки блока через RS */
void load(RS_DATA *rs_arr) void load(RS_DATA *rs_arr)
{ {
unsigned int rcrc, crc; unsigned int rcrc, crc;
@@ -197,27 +197,27 @@ void load(RS_DATA *rs_arr)
else else
{ {
rs_arr->BS_LoadOK = false; rs_arr->BS_LoadOK = false;
RS_Line_to_receive(rs_arr); // режим приема RS485 RS_Line_to_receive(rs_arr); // режим приема RS485
RS_SetBitMode(rs_arr,9); RS_SetBitMode(rs_arr,9);
} } } }
/** Выполнить программу в формате Serial Boot. /** Выполнить программу в формате Serial Boot.
@precondition Должна быть произведена загрузка блока @precondition Должна быть произведена загрузка блока
Адрес программы беретса из заголовка и Адрес программы беретса из заголовка и
сравниваетса с переменной RecvPtr, заполнаемой в ф-ции load сравниваетса с переменной RecvPtr, заполнаемой в ф-ции load
@see load */ @see load */
void run (RS_DATA *rs_arr) void run (RS_DATA *rs_arr)
{ {
return; return;
} }
/** Прочитать ачейку памати */ /** Прочитать ачейку памати */
void peek(RS_DATA *rs_arr) void peek(RS_DATA *rs_arr)
{ {
unsigned long Address; unsigned long Address;
unsigned int Data, crc; unsigned int Data, crc;
flag_DEBUG = true; // Флаг отладочного режима flag_DEBUG = true; // Флаг отладочного режима
Address = rs_arr->RS_Header[5] & 0xFF; Address = rs_arr->RS_Header[5] & 0xFF;
Address = (Address<<8) | (rs_arr->RS_Header[4] & 0xFF); Address = (Address<<8) | (rs_arr->RS_Header[4] & 0xFF);
@@ -250,7 +250,7 @@ void peek(RS_DATA *rs_arr)
} }
/** Записать в ачейку памати */ /** Записать в ачейку памати */
void poke(RS_DATA *rs_arr) void poke(RS_DATA *rs_arr)
{ {
unsigned long Address; unsigned long Address;
@@ -272,12 +272,12 @@ void poke(RS_DATA *rs_arr)
Answer(rs_arr,CMD_POKE); Answer(rs_arr,CMD_POKE);
} }
/** Передать блок памати */ /** Передать блок памати */
void upload(RS_DATA *rs_arr) void upload(RS_DATA *rs_arr)
{ {
int32 Address, Length, crc; int32 Address, Length, crc;
no_write = 1; // Флаг отладочного режима no_write = 1; // Флаг отладочного режима
// stopp=1; // stopp=1;
Address = rs_arr->RS_Header[5] & 0xFF; Address = rs_arr->RS_Header[5] & 0xFF;
@@ -297,10 +297,10 @@ void upload(RS_DATA *rs_arr)
crc = get_crc_16( crc, rs_arr->buffer, 2); crc = get_crc_16( crc, rs_arr->buffer, 2);
crc = get_crc_16b( crc, (unsigned int *)Address, Length); crc = get_crc_16b( crc, (unsigned int *)Address, Length);
RS_Send(rs_arr,rs_arr->buffer, 1); // <=2 байт по флагу RS_Send(rs_arr,rs_arr->buffer, 1); // <=2 байт по флагу
rs_arr->buffer[0] = CMD_UPLOAD; rs_arr->buffer[0] = CMD_UPLOAD;
RS_Send(rs_arr,rs_arr->buffer, 1); // <=2 байт по флагу RS_Send(rs_arr,rs_arr->buffer, 1); // <=2 байт по флагу
RS_Wait4OK(rs_arr); RS_Wait4OK(rs_arr);
RS_BSend(rs_arr,(unsigned int*)Address, Length); RS_BSend(rs_arr,(unsigned int*)Address, Length);
@@ -314,21 +314,21 @@ void upload(RS_DATA *rs_arr)
} }
/** Прошить XILINX. /** Прошить XILINX.
@precondition Должна быть произведена загрузка блока @precondition Должна быть произведена загрузка блока
Адрес и длина прошивки беретса из заголовка и Адрес и длина прошивки беретса из заголовка и
сравниваетса с переменными RecvPtr и Length, заполнаемыми в ф-ции load, сравниваетса с переменными RecvPtr и Length, заполнаемыми в ф-ции load,
так же смотрит магическое слово в начале прошивки так же смотрит магическое слово в начале прошивки
@see load */ @see load */
void xflash(RS_DATA *rs_arr) void xflash(RS_DATA *rs_arr)
{ {
return; return;
} }
/** Прошить TMS. /** Прошить TMS.
@precondition Должна быть произведена загрузка блока @precondition Должна быть произведена загрузка блока
Адрес и длина прошивки беретса из заголовка и Адрес и длина прошивки беретса из заголовка и
сравниваетса с переменными RecvPtr и Length, заполнаемыми в ф-ции load сравниваетса с переменными RecvPtr и Length, заполнаемыми в ф-ции load
@see load */ @see load */
void tflash(RS_DATA *rs_arr) void tflash(RS_DATA *rs_arr)
{ {
@@ -337,7 +337,7 @@ void tflash(RS_DATA *rs_arr)
/* /*
if(!rs_arr->BS_LoadOK) if(!rs_arr->BS_LoadOK)
{ {
RS_Line_to_receive(rs_arr); // режим приема RS485 RS_Line_to_receive(rs_arr); // режим приема RS485
RS_SetBitMode(rs_arr,9); RS_SetBitMode(rs_arr,9);
return; return;
} }
@@ -362,7 +362,7 @@ void tflash(RS_DATA *rs_arr)
if( (Address2 < 0x100000) || (Address2 > 0x180000) || ((Address2+LengthW) > 0x180000) ) if( (Address2 < 0x100000) || (Address2 > 0x180000) || ((Address2+LengthW) > 0x180000) )
{ {
RS_Line_to_receive(rs_arr); // режим приема RS485 RS_Line_to_receive(rs_arr); // режим приема RS485
RS_SetBitMode(rs_arr,9); RS_SetBitMode(rs_arr,9);
return; return;
} }
@@ -374,10 +374,10 @@ void tflash(RS_DATA *rs_arr)
return; return;
} }
/** Прошить TMS. /** Прошить TMS.
@precondition Должна быть произведена загрузка блока @precondition Должна быть произведена загрузка блока
Адрес и длина прошивки беретса из заголовка и Адрес и длина прошивки беретса из заголовка и
сравниваетса с переменными RecvPtr и Length, заполнаемыми в ф-ции load сравниваетса с переменными RecvPtr и Length, заполнаемыми в ф-ции load
@see load */ @see load */
void extendbios(RS_DATA *rs_arr) void extendbios(RS_DATA *rs_arr)
{ {
@@ -403,10 +403,10 @@ void extendbios(RS_DATA *rs_arr)
switch ( code ) switch ( code )
{ {
// Прошиваем EPROM Из RAM // Прошиваем EPROM Из RAM
case 4: Seeprom_write(Address1,(unsigned int*)Address2,Length); case 4: Seeprom_write(Address1,(unsigned int*)Address2,Length);
break; break;
// Читаем из EPROM в RAM // Читаем из EPROM в RAM
case 5: Seeprom_read(Address1,(unsigned int*)Address2,Length); case 5: Seeprom_read(Address1,(unsigned int*)Address2,Length);
break; break;

View File

@@ -1,7 +1,7 @@
/* Адресация последовательного протокола. set_cntrl_addr задаёт /* Адресация последовательного протокола. set_cntrl_addr задаёт
* собственный и общий адрес. CAN ID вычисляется отдельно из Mode. * собственный и общий адрес. CAN ID вычисляется отдельно из Mode.
* Общий RS-адрес не заменяет собственный во всех ответах: для * Общий RS-адрес не заменяет собственный во всех ответах: для
* логгера SetGUI использовать собственный адрес платы (обычно 5/6). * логгера SetGUI использовать собственный адрес платы (обычно 5/6).
*/ */
#include "cntrl_adr.h" #include "cntrl_adr.h"
@@ -11,25 +11,25 @@
#define ADDR_UNIVERSAL_DEF 10 #define ADDR_UNIVERSAL_DEF 10
/** Установка адреса контроллера дла посылки всем АИНам */ /** Установка адреса контроллера дла посылки всем АИНам */
int ADDR_FOR_ALL = ADDR_FOR_ALL_DEF; int ADDR_FOR_ALL = ADDR_FOR_ALL_DEF;
/** Установка адреса контроллера дла посылки ответа */ /** Установка адреса контроллера дла посылки ответа */
const int ADDR_ANSWER = ADDR_ANSWER_DEF; const int ADDR_ANSWER = ADDR_ANSWER_DEF;
/** Установка адреса терминала дла посылки ответа */ /** Установка адреса терминала дла посылки ответа */
const int ADDR_TERMINAL = ADDR_TERMINAL_DEF; const int ADDR_TERMINAL = ADDR_TERMINAL_DEF;
/* Универсальный адрес контроллера */ /* Универсальный адрес контроллера */
const int CNTRL_ADDR_UNIVERSAL=ADDR_UNIVERSAL_DEF; const int CNTRL_ADDR_UNIVERSAL=ADDR_UNIVERSAL_DEF;
/* Адрес контроллера */ /* Адрес контроллера */
int CNTRL_ADDR=1; int CNTRL_ADDR=1;
int cntr_addr_c; int cntr_addr_c;
int cntr_addr_c_all; int cntr_addr_c_all;
/** Установка адреса контроллера дла прошивки */ /** Установка адреса контроллера дла прошивки */
void set_cntrl_addr (int cntrl_addr,int cntrl_addr_for_all) void set_cntrl_addr (int cntrl_addr,int cntrl_addr_for_all)
{ {
CNTRL_ADDR = cntrl_addr; CNTRL_ADDR = cntrl_addr;

View File

@@ -1,8 +1,8 @@
/* CRC кадров обмена и параметров EEPROM. get_crc_16 работает /* CRC кадров обмена и параметров EEPROM. get_crc_16 работает
* с представлением буфера протокола, get_crc16 обрабатывает оба * с представлением буфера протокола, get_crc16 обрабатывает оба
* байта каждого слова параметров. Порядок байтов существенен. * байта каждого слова параметров. Порядок байтов существенен.
* Нельзя заменять эти функции реализацией для ПК без проверки * Нельзя заменять эти функции реализацией для ПК без проверки
* представления данных и особенностей 16-битной ABI C2000. * представления данных и особенностей 16-битной ABI C2000.
*/ */
#include "crc16.h" #include "crc16.h"
#define MAKE_TABS 0 /* Builds tables below */ #define MAKE_TABS 0 /* Builds tables below */

View File

@@ -1,8 +1,8 @@
/* Команды и телеметрия eCAN. MBOX1 принимает кадры, MBOX0 передаёт /* Команды и телеметрия eCAN. MBOX1 принимает кадры, MBOX0 передаёт
* технологические регистры, MBOX2 выделен под ответы логгера. * технологические регистры, MBOX2 выделен под ответы логгера.
* Слово 127 проходит UMP_commands_write непосредственно в CAN ISR. * Слово 127 проходит UMP_commands_write непосредственно в CAN ISR.
* Запрос архива ISR лишь ставит на обслуживание; фрагментация * Запрос архива ISR лишь ставит на обслуживание; фрагментация
* ответов выполняется UMP_CAN_service из фонового цикла. * ответов выполняется UMP_CAN_service из фонового цикла.
*/ */
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_SWPrioritizedIsrLevels.h" #include "DSP2833x_SWPrioritizedIsrLevels.h"
@@ -39,9 +39,9 @@ int CanTimeOutErrorTR = 0;
int wait=0; int wait=0;
/* MBOX2 выделен под ответы регистратора; штатный MBOX0 продолжает /* MBOX2 выделен под ответы регистратора; штатный MBOX0 продолжает
* передавать технологические данные независимо. ISR только ставит запрос, * передавать технологические данные независимо. ISR только ставит запрос,
* а снимок и отправка короткими шагами выполняются в основном цикле. */ * а снимок и отправка короткими шагами выполняются в основном цикле. */
static volatile unsigned int ump_can_pending; static volatile unsigned int ump_can_pending;
static volatile unsigned int ump_can_tag, ump_can_address, ump_can_value; static volatile unsigned int ump_can_tag, ump_can_address, ump_can_value;
static unsigned int ump_can_reply[UMP_CAN_MAX_WORDS]; static unsigned int ump_can_reply[UMP_CAN_MAX_WORDS];
@@ -49,6 +49,8 @@ static unsigned int ump_can_length, ump_can_index, ump_can_reply_tag;
static unsigned int ump_can_waiting; static unsigned int ump_can_waiting;
static unsigned long ump_can_sent_at; static unsigned long ump_can_sent_at;
#include "can_telemetry_impl.h" /* Определяет heartbeat, подтверждённый кэш и повтор данных через 1,3 с после объявления состояния штатного TX. */
void InitCan(int Port, int DevNum) void InitCan(int Port, int DevNum)
{ {
struct ECAN_REGS ECanShadow; struct ECAN_REGS ECanShadow;
@@ -59,6 +61,7 @@ void InitCan(int Port, int DevNum)
long id = 0x80BA0000; long id = 0x80BA0000;
CAN_telemetry_init(); /* Сбрасывает кэш, очередь и секундный heartbeat до разрешения аппаратных прерываний. */
DevNum--; DevNum--;
if(DevNum<0)DevNum=0; if(DevNum<0)DevNum=0;
if(DevNum>15)DevNum=15; if(DevNum>15)DevNum=15;
@@ -86,17 +89,17 @@ void InitCan(int Port, int DevNum)
// Required before writing the MSGIDs // Required before writing the MSGIDs
ECanRegs->CANME.all = 0; ECanRegs->CANME.all = 0;
// задаем адрес 0 ащикa на передачу // задаем адрес 0 ащикa на передачу
ECanMboxes->MBOX0.MSGID.all = id + 0x10 + DevNum; ECanMboxes->MBOX0.MSGID.all = id + 0x10 + DevNum;
// задаем адрес 1 ащикa на прием // задаем адрес 1 ащикa на прием
ECanMboxes->MBOX1.MSGID.all = id + DevNum; //поменать!!!! 1 и 0!!! ECanMboxes->MBOX1.MSGID.all = id + DevNum; //поменать!!!! 1 и 0!!!
// MBOX0 и MBOX2 передают данные; MBOX1 принимает команды. // MBOX0 и MBOX2 передают данные; MBOX1 принимает команды.
ECanMboxes->MBOX2.MSGID.all = id + 0x20 + DevNum; ECanMboxes->MBOX2.MSGID.all = id + 0x20 + DevNum;
ECanRegs->CANMD.all = 0xFFFFFFFA; ECanRegs->CANMD.all = 0xFFFFFFFA;
// Включаем три mailbox: телеметрия, команды и ответы логгера. // Включаем три mailbox: телеметрия, команды и ответы логгера.
ECanRegs->CANME.all = 0x00000007; ECanRegs->CANME.all = 0x00000007;
// Clear all TAn bits // Clear all TAn bits
@@ -121,7 +124,7 @@ void InitCan(int Port, int DevNum)
ECanRegs->CANMC.all = ECanShadow.CANMC.all; ECanRegs->CANMC.all = ECanShadow.CANMC.all;
while(!ECanRegs->CANES.bit.CCE); // Wait for CCE bit to be set.. while(!ECanRegs->CANES.bit.CCE); // Wait for CCE bit to be set..
// настриваем скорость CAN // настриваем скорость CAN
ECanShadow.CANBTC.all = ECanRegs->CANBTC.all; ECanShadow.CANBTC.all = ECanRegs->CANBTC.all;
ECanShadow.CANBTC.bit.SJWREG=1; ECanShadow.CANBTC.bit.SJWREG=1;
@@ -134,7 +137,7 @@ void InitCan(int Port, int DevNum)
ECanRegs->CANMC.all = ECanShadow.CANMC.all; ECanRegs->CANMC.all = ECanShadow.CANMC.all;
while(ECanRegs->CANES.bit.CCE); // Wait for CCE bit to be cleared.. while(ECanRegs->CANES.bit.CCE); // Wait for CCE bit to be cleared..
// задаем таймауты дла ожиданиа отправки получениа посылки // задаем таймауты дла ожиданиа отправки получениа посылки
ECanMOTORegs->MOTO0 = 550000; ECanMOTORegs->MOTO0 = 550000;
ECanMOTORegs->MOTO1 = 550000; ECanMOTORegs->MOTO1 = 550000;
@@ -161,7 +164,7 @@ void InitCan(int Port, int DevNum)
IER |= M_INT9; // Enable CPU INT IER |= M_INT9; // Enable CPU INT
EDIS; EDIS;
// завершили настройку CAN ащиков // завершили настройку CAN ащиков
MessageReceivedCount = 0; MessageReceivedCount = 0;
ErrorCount = 0; ErrorCount = 0;
@@ -169,43 +172,10 @@ void InitCan(int Port, int DevNum)
MessageTransivedCount=0; MessageTransivedCount=0;
} }
/* При занятом MBOX0 возвращается без ожидания ACK в цикле. /* При занятом MBOX0 возвращается без ожидания ACK в цикле.
* Это отличается от блокирующих UART/EEPROM операций main. * Это отличается от блокирующих UART/EEPROM операций main.
*/ */
void CAN_send(int Port, int data[], int Addr) /* CAN_send определён общим для этой единицы трансляции блоком can_telemetry_impl.h выше. */
{
unsigned long hiword,loword;
volatile struct ECAN_REGS * ECanRegs;
volatile struct ECAN_MBOXES * ECanMboxes;
ECanRegs = &ECanaRegs;
ECanMboxes = &ECanaMboxes;
if(wait)
if(!(ECanRegs->CANTA.all & 1))
if(!(ECanRegs->CANAA.all & 1))
return;
ECanRegs->CANTA.all = 1;
ECanRegs->CANAA.all = 1;
hiword= ((((Uint32) Addr ) & 0xffff)<<16)| 0xE0000000 |
((((Uint32)data[Addr ]) & 0xffff) );
loword= ((((Uint32)data[Addr+1]) & 0xffff)<<16)|
((((Uint32)data[Addr+2]) & 0xffff) );
ECanMboxes->MBOX0.MDH.all = hiword;
ECanMboxes->MBOX0.MDL.all = loword;
EALLOW;
ECanRegs->CANTSC = 0; // clear time-out counter
EDIS;
ECanRegs->CANTRS.all = 1; // запустить передачу
wait=1;
led1_toggle();
}
void Handlai(volatile struct ECAN_MBOXES * ECanMboxes) void Handlai(volatile struct ECAN_MBOXES * ECanMboxes)
@@ -220,9 +190,9 @@ void Handlai(volatile struct ECAN_MBOXES * ECanMboxes)
hiword = ECanMboxes->MBOX1.MDH.all; hiword = ECanMboxes->MBOX1.MDH.all;
loword = ECanMboxes->MBOX1.MDL.all; loword = ECanMboxes->MBOX1.MDL.all;
/* Служебный запрос логгера не является командой УМП и сам не должен /* Служебный запрос логгера не является командой УМП и сам не должен
* заполнять журнал CAN-событиями при онлайн-чтении. Короткие кадры * заполнять журнал CAN-событиями при онлайн-чтении. Короткие кадры
* отбрасываются: незаполненные байты mailbox могли остаться от прошлого. */ * отбрасываются: незаполненные байты mailbox могли остаться от прошлого. */
if ((unsigned int)(hiword >> 16) == UMP_CAN_MARKER) { if ((unsigned int)(hiword >> 16) == UMP_CAN_MARKER) {
if (ECanMboxes->MBOX1.MSGCTRL.bit.DLC == 8) { if (ECanMboxes->MBOX1.MSGCTRL.bit.DLC == 8) {
ump_can_tag = (unsigned int)hiword; ump_can_tag = (unsigned int)hiword;
@@ -244,10 +214,10 @@ void Handlai(volatile struct ECAN_MBOXES * ECanMboxes)
Data[1] = (loword>>16) & 0xffff; Data[1] = (loword>>16) & 0xffff;
Data[2] = (loword ) & 0xffff; Data[2] = (loword ) & 0xffff;
/* Каждое разрешённое слово имеет собственный адрес. Не опрашиваем /* Каждое разрешённое слово имеет собственный адрес. Не опрашиваем
* Commands после кадра безусловно: пакет телеметрии не должен * Commands после кадра безусловно: пакет телеметрии не должен
* превращать внутренний сброс параметров в командный фронт. * превращать внутренний сброс параметров в командный фронт.
* Адрес 127 проходит через единый обработчик полного слова. */ * Адрес 127 проходит через единый обработчик полного слова. */
{ {
unsigned int i; unsigned int i;
for (i = 0; i < 3; i++, adr++) { for (i = 0; i < 3; i++, adr++) {
@@ -258,7 +228,7 @@ void Handlai(volatile struct ECAN_MBOXES * ECanMboxes)
} }
} }
/* Фиксируем применённую команду до выхода из обработчика CAN. */ /* Фиксируем применённую команду до выхода из обработчика CAN. */
ump_log_can((unsigned int)(hiword >> 16), Data[0], Data[1], Data[2]); ump_log_can((unsigned int)(hiword >> 16), Data[0], Data[1], Data[2]);
led2_toggle(); led2_toggle();
} }
@@ -292,8 +262,17 @@ interrupt void CANa_reset_err(void)
PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts
EINT; EINT;
ECanaRegs.CANTRR.all = 1; /* Проверяет реальный тайм-аут mailbox 0: отложенное PIE-прерывание после успешного TX уже может не иметь причины. */
CanTimeOutErrorTR++; if (ECanaRegs.CANTOS.all & 1UL)
{ /* Обрабатывает только штатный передатчик; служебный mailbox 2 контролируется отдельно в UMP_CAN_service. */
EALLOW; /* Разрешает изменение управляющего регистра eCAN перед снятием источника прерывания. */
ECanaRegs.CANTOC.all &= ~1UL; /* Снимает timeout только mailbox 0, сохраняя контроль служебных передач. */ /* Сброс TOC снимает TOS и MTOF согласно SPRUI07, 13.8.18.3; одной отмены TX недостаточно. */
EDIS; /* Восстанавливает защиту регистров до выхода из ветви обработки тайм-аута. */
if (ECanaRegs.CANTRS.all & 1UL) /* Передача могла завершиться между чтением TOS и снятием контроля. */
ECanaRegs.CANTRR.all = 1UL; /* Запрашивает отмену только ещё занятого mailbox 0, не задерживая прерывание ожиданием CANAA. */
can_tx_failed = 1U; /* Не допускает записи повреждённого или отменённого кадра в подтверждённый кэш телеметрии. */
CanTimeOutErrorTR++; /* Считает обнаруженный тайм-аут один раз, исключая фантомные повторные входы PIE. */
} /* Следующая штатная передача сама заново включит TOC после сброса временного счётчика. */
PieCtrlRegs.PIEACK.bit.ACK9 |= 1; PieCtrlRegs.PIEACK.bit.ACK9 |= 1;
@@ -307,10 +286,10 @@ interrupt void CANa_reset_err(void)
//=========================================================================== //===========================================================================
/* Один вызов обслуживает максимум один кадр и никогда не ждёт ACK в цикле. /* Один вызов обслуживает максимум один кадр и никогда не ждёт ACK в цикле.
* Снимок фиксируется один раз на запрос: CAN-фрагменты не смешивают * Снимок фиксируется один раз на запрос: CAN-фрагменты не смешивают
* значения до/после переключения кольцевого банка. Новые запросы забираем * значения до/после переключения кольцевого банка. Новые запросы забираем
* после завершения предыдущего ответа. GUI держит только один запрос. */ * после завершения предыдущего ответа. GUI держит только один запрос. */
void UMP_CAN_service(void) void UMP_CAN_service(void)
{ {
unsigned int saved, tag, address, value, error; unsigned int saved, tag, address, value, error;
@@ -321,11 +300,11 @@ void UMP_CAN_service(void)
ump_can_waiting = 0; ump_can_waiting = 0;
} else if ((ECanaRegs.CANAA.all & 4UL) || } else if ((ECanaRegs.CANAA.all & 4UL) ||
((unsigned long)CpuTimer1.InterruptCount - ump_can_sent_at > 250UL)) { ((unsigned long)CpuTimer1.InterruptCount - ump_can_sent_at > 250UL)) {
/* Нет подтверждения шины: отменяем только служебный mailbox. /* Нет подтверждения шины: отменяем только служебный mailbox.
* GUI обнаружит неполный ответ по тайм-ауту; управление MBOX0 * GUI обнаружит неполный ответ по тайм-ауту; управление MBOX0
* и приём команд MBOX1 продолжаются. */ * и приём команд MBOX1 продолжаются. */
ECanaRegs.CANTRR.all = 4UL; ECanaRegs.CANTRR.all = 4UL;
/* До фактического завершения отмены mailbox не переиспользуем. */ /* До фактического завершения отмены mailbox не переиспользуем. */
if (!(ECanaRegs.CANAA.all & 4UL)) return; if (!(ECanaRegs.CANAA.all & 4UL)) return;
ECanaRegs.CANAA.all = 4UL; ECanaRegs.CANAA.all = 4UL;
ump_can_waiting = 0; ump_can_waiting = 0;
@@ -342,7 +321,7 @@ void UMP_CAN_service(void)
__restore_interrupts(saved); __restore_interrupts(saved);
} }
if (ump_can_index >= ump_can_length) return; if (ump_can_index >= ump_can_length) return;
/* Перед следующим фрагментом уступаем штатной телеметрии MBOX0. */ /* Перед следующим фрагментом уступаем штатной телеметрии MBOX0. */
if (ECanaRegs.CANTRS.all & 1UL) return; if (ECanaRegs.CANTRS.all & 1UL) return;
hiword = ((unsigned long)(UMP_CAN_MARKER + ump_can_index/2) << 16) | ump_can_reply_tag; hiword = ((unsigned long)(UMP_CAN_MARKER + ump_can_index/2) << 16) | ump_can_reply_tag;
loword = ((unsigned long)ump_can_reply[ump_can_index] << 16) | ump_can_reply[ump_can_index+1]; loword = ((unsigned long)ump_can_reply[ump_can_index] << 16) | ump_can_reply[ump_can_index+1];

View File

@@ -1,7 +1,7 @@
/* Рекурсивный фильтр. FILTERBAT хранит коэффициенты и историю /* Рекурсивный фильтр. FILTERBAT хранит коэффициенты и историю
* двух входов/выходов; каждый вызов изменяет переданный экземпляр. * двух входов/выходов; каждый вызов изменяет переданный экземпляр.
* Независимым каналам нужны отдельные состояния. Синхронизации * Независимым каналам нужны отдельные состояния. Синхронизации
* здесь нет: смену коэффициентов согласовывает вызывающий код. * здесь нет: смену коэффициентов согласовывает вызывающий код.
*/ */
#include "filter_bat2.h" #include "filter_bat2.h"

View File

@@ -1,7 +1,7 @@
/* Программный канал индикации. digits/readr задают символы и выбор /* Программный канал индикации. digits/readr задают символы и выбор
* элементов, DCLK/DOUT и kanal_Send формируют последовательность GPIO. * элементов, DCLK/DOUT и kanal_Send формируют последовательность GPIO.
* Это другой интерфейс, чем dCLK/dCS в DAC.c. Похожие имена не * Это другой интерфейс, чем dCLK/dCS в DAC.c. Похожие имена не
* означают общий ЦАП или общий выход запуска нагрузки. * означают общий ЦАП или общий выход запуска нагрузки.
*/ */
#include "DSP2833x_Device.h" // DSP281x Headerfile Include File #include "DSP2833x_Device.h" // DSP281x Headerfile Include File
#include "DSP2833x_SWPrioritizedIsrLevels.h" #include "DSP2833x_SWPrioritizedIsrLevels.h"
@@ -88,7 +88,7 @@ void kanal_Send(int adr, long dat, int dot)
long Word,data,aliq_part,dg[4]; long Word,data,aliq_part,dg[4];
int i,j,bit,byt,addr,sgn=0,punkt=0,aliq_len=0,full_len, isdot=0; int i,j,bit,byt,addr,sgn=0,punkt=0,aliq_len=0,full_len, isdot=0;
if(adr>1) // Лампочки if(adr>1) // Лампочки
{ {
Word =dat; Word =dat;
} }
@@ -139,7 +139,7 @@ void kanal_Send(int adr, long dat, int dot)
for(i=3;i>0;i--) for(i=3;i>0;i--)
{ {
if((dg[i]==0)&&(i!=dot)) if((dg[i]==0)&&(i!=dot))
dg[i]=0xF; // Это значит пусто dg[i]=0xF; // Это значит пусто
else break; else break;
} }
@@ -148,7 +148,7 @@ void kanal_Send(int adr, long dat, int dot)
{ {
if( (dg[i]==0xF)||(i==3)) if( (dg[i]==0xF)||(i==3))
{ {
dg[i]=0xA; // Это значит минус dg[i]=0xA; // Это значит минус
break; break;
} } } }

View File

@@ -1,8 +1,8 @@
/* Регистратор УМП во внешней памяти .logg: два банка по 800 записей /* Регистратор УМП во внешней памяти .logg: два банка по 800 записей
* из 40 слов для SetGUI. Архив отключения не мешает дальнейшей записи. * из 12 слов формата v4 для SetGUI. Архив отключения не мешает дальнейшей записи.
* Писатели из main/CAN/таймера защищаются короткими секциями IRQ * Писатели из main/CAN/таймера защищаются короткими секциями IRQ
* с восстановлением прежней маски. Архив не энергонезависимый. * с восстановлением прежней маски. Архив не энергонезависимый.
* clear_mem выполняется при запуске до включения прерываний. * clear_mem выполняется при запуске до включения прерываний.
*/ */
#include "DSP2833x_Device.h" #include "DSP2833x_Device.h"
#include "filter_bat2.h" #include "filter_bat2.h"
@@ -16,7 +16,7 @@
#include "log_to_mem.h" #include "log_to_mem.h"
int no_write = 0, int no_write = 0,
never_write = 0; // Флаги, чтобы не писать (если что) never_write = 0; // Изначально разрешает запись; установленный флаг прекращает сохранение снимков до следующего запуска регистратора.
#pragma DATA_SECTION(logs_block,".logg"); #pragma DATA_SECTION(logs_block,".logg");
unsigned int logs_block[0xFA00]; unsigned int logs_block[0xFA00];
@@ -24,7 +24,7 @@ unsigned int logs_block[0xFA00];
LOG Log; LOG Log;
unsigned int flog=0; unsigned int flog=0;
// Очищение памати, где логи лежат // Очищение памати, где логи лежат
void clear_mem() void clear_mem()
{ {
unsigned long i; unsigned long i;
@@ -37,27 +37,27 @@ void clear_mem()
for (i=Log.Start; i<Log.Finis; i++) for (i=Log.Start; i<Log.Finis; i++)
*(volatile int *)i = 0; *(volatile int *)i = 0;
} }
/* Два банка используют уже выделенную внешнюю RAM .logg (64000 слов). /* Два банка используют уже выделенную внешнюю RAM .logg (64000 слов).
* Активный банк кольцевой. Через 1000 мс после команды отключения он * Активный банк кольцевой. Через 1000 мс после команды отключения он
* становится архивом, а запись продолжается во втором банке. Переключение * становится архивом, а запись продолжается во втором банке. Переключение
* занимает постоянное время: копирования 30 тысяч слов под запретом IRQ нет. * занимает постоянное время: копирования 30 тысяч слов под запретом IRQ нет.
* Архив переживает разрыв RS-связи, но НЕ исчезновение питания платы. */ * Архив переживает разрыв RS-связи, но НЕ исчезновение питания платы. */
static volatile unsigned int ump_state, ump_count, ump_cursor, ump_next; static volatile unsigned int ump_state, ump_count, ump_cursor, ump_next;
static volatile unsigned int ump_period = 20, ump_divider; static volatile unsigned int ump_period = 20, ump_divider;
static volatile unsigned long ump_time, ump_sequence; static volatile unsigned long ump_time, ump_sequence;
static unsigned int ump_bank, ump_archive_bank = 1; static unsigned int ump_bank, ump_archive_bank = 1;
static unsigned int ump_archive_count, ump_archive_next, ump_generation; static unsigned int ump_archive_count, ump_archive_next, ump_generation;
static unsigned int ump_source, ump_post, ump_post_dropped; static unsigned int ump_source, ump_post, ump_post_dropped;
static unsigned int ump_can_header, ump_can_data[3], ump_can_count; /* Хранит последние ЗПТ1/ЗПТ2 в вольтах из регистров ПМ67 306/9; явные нули попадают в инициализацию COFF до первого CAN-кадра. */
static unsigned int ump_pm67_voltage[2] = {0, 0};
static unsigned int ump_prev_commands, ump_prev_inputs, ump_prev_outputs; static unsigned int ump_prev_commands, ump_prev_inputs, ump_prev_outputs;
extern int CanTimeOutErrorTR; /* Диагностика внутренних переменных разгона. Обновляется самим Load_runner,
/* Диагностика внутренних переменных разгона. Обновляется самим Load_runner, * не пересчитывает и не изменяет управляющий алгоритм. */
* не пересчитывает и не изменяет управляющий алгоритм. */
unsigned int ump_dac_ramp, ump_dac_duration, ump_dac_go10, ump_dac_stop10, ump_dac_position; unsigned int ump_dac_ramp, ump_dac_duration, ump_dac_go10, ump_dac_stop10, ump_dac_position;
/* Логические уровни входов платы нагрузки: физический ноль означает 1. /* Логические уровни входов платы нагрузки: физический ноль означает 1.
* Чтение GPIO непосредственно здесь позволяет записать вход до следующего * Чтение GPIO непосредственно здесь позволяет записать вход до следующего
* обновления регистра Inputs в основном цикле. */ * обновления регистра Inputs в основном цикле. */
static unsigned int ump_inputs(void) static unsigned int ump_inputs(void)
{ {
return (!GpioDataRegs.GPADAT.bit.GPIO6) | return (!GpioDataRegs.GPADAT.bit.GPIO6) |
@@ -65,7 +65,7 @@ static unsigned int ump_inputs(void)
((!GpioDataRegs.GPADAT.bit.GPIO11) << 2); ((!GpioDataRegs.GPADAT.bit.GPIO11) << 2);
} }
/* START/STOP активны единицей; RES_OUT_2 активен физическим нулём. */ /* START/STOP активны единицей; RES_OUT_2 активен физическим нулём. */
static unsigned int ump_outputs(void) static unsigned int ump_outputs(void)
{ {
return GpioDataRegs.GPBDAT.bit.GPIO62 | return GpioDataRegs.GPBDAT.bit.GPIO62 |
@@ -73,62 +73,62 @@ static unsigned int ump_outputs(void)
((!GpioDataRegs.GPADAT.bit.GPIO3) << 2); ((!GpioDataRegs.GPADAT.bit.GPIO3) << 2);
} }
/* Вызывается только внутри короткой критической секции. Все три источника /* Вызывается только внутри короткой критической секции. Все три источника
* записей (main, CAN ISR, timer ISR) используют одну блокировку IRQ с * записей (main, CAN ISR, timer ISR) используют одну блокировку IRQ с
* восстановлением прежнего состояния, включая вызовы из прерывания. */ * восстановлением прежнего состояния, включая вызовы из прерывания. */
static void ump_capture(unsigned int reason) static void ump_capture(unsigned int reason)
{ {
volatile unsigned int *p; /* Указывает на начало одной 12-словной записи во внешней RAM; volatile сохраняет фактические обращения к памяти. */
unsigned int i, commands; volatile unsigned int *record;
/* Сохраняет полное слово команд для прежней логики триггера; в запись попадут только биты пуска и сброса. */
unsigned int commands;
if (ump_state != 1 || Desk != dsk_LOAD || READY) return; if (ump_state != 1 || Desk != dsk_LOAD || READY) return;
if (no_write || never_write) { ump_state = 3; return; } if (no_write || never_write) { ump_state = 3; return; }
commands = Commands; commands = Commands;
/* Отключение: фронт cUMPreset (бит 6) либо спад cUMPstart (бит 7). /* Отключение: фронт cUMPreset (бит 6) либо спад cUMPstart (бит 7).
* Повторные команды не сдвигают конец уже начатого постинтервала. */ * Повторные команды не сдвигают конец уже начатого постинтервала. */
if (!ump_post && (((commands & 0x40) && !(ump_prev_commands & 0x40)) || if (!ump_post && (((commands & 0x40) && !(ump_prev_commands & 0x40)) ||
(!(commands & 0x80) && (ump_prev_commands & 0x80)))) { (!(commands & 0x80) && (ump_prev_commands & 0x80)))) {
/* Половину банка резервируем под постинтервал. Даже при периоде /* Половину банка резервируем под постинтервал. Даже при периоде
* 1 мс или шквале CAN событие отключения не вытесняется кольцом. */ * 1 мс или шквале CAN событие отключения не вытесняется кольцом. */
if (ump_count >= UMP_LOG_CAPACITY/2) ump_count = UMP_LOG_CAPACITY/2-1; if (ump_count >= UMP_LOG_CAPACITY/2) ump_count = UMP_LOG_CAPACITY/2-1;
ump_post_dropped = 0; ump_post_dropped = 0;
ump_post = 1000; ump_post = 1000;
reason |= 0x100; reason |= 0x100;
} }
/* Последнее место оставляем для снимка конца постинтервала. При /* Последнее место оставляем для снимка конца постинтервала. При
* переполнении честно отмечаем усечение битом 0x200 в конечной записи. */ * переполнении честно отмечаем усечение битом 0x200 в конечной записи. */
if (ump_post && ump_count >= UMP_LOG_CAPACITY-1) { if (ump_post && ump_count >= UMP_LOG_CAPACITY-1) {
ump_post_dropped = 1; ump_post_dropped = 1;
return; return;
} }
if (reason == 5 && ump_post_dropped) reason |= 0x200; if (reason == 5 && ump_post_dropped) reason |= 0x200;
p = logs_block + ((unsigned long)ump_bank * UMP_LOG_CAPACITY + ump_next) * UMP_LOG_WORDS; /* Выбирает слот банка по числу 16-битных слов записи; ёмкость 800 записей сохранена для исполнения 166. */
p[0] = (unsigned int)ump_time; p[1] = (unsigned int)(ump_time >> 16); record = logs_block + ((unsigned long)ump_bank * UMP_LOG_CAPACITY + ump_next) * UMP_LOG_WORDS;
p[2] = reason; p[3] = commands; /* Слова 0/1 передают 32-битное время в миллисекундах младшей половиной вперёд, как в формате v4 исполнения 167. */
p[4] = ump_inputs(); p[5] = ump_outputs(); record[0] = (unsigned int)ump_time; record[1] = (unsigned int)(ump_time >> 16);
p[6] = (unsigned int)IMPowse; p[7] = (unsigned int)WAKEpowse; /* Слово 2 содержит событие, а маска 0xC0 оставляет в слове 3 только назначенные протоколом биты 7/6 пуска и сброса УМП. */
p[8] = modbus[0x7B]; p[9] = modbus[0x1C]; record[2] = reason; record[3] = commands & 0xC0U;
for (i = 0; i < 4; i++) { p[10+i] = sens_data[i]; p[14+i] = modbus[i]; } /* Слова 4/5 сохраняют фактические логические входы и выходы нагрузки для дискретных дорожек SetGUI. */
p[18] = ump_can_header; record[4] = ump_inputs(); record[5] = ump_outputs();
p[19] = ump_can_data[0]; p[20] = ump_can_data[1]; p[21] = ump_can_data[2]; /* Слово 6 содержит расчётное задание тока регистра 0x1C в единицах 0,1 мА; физическое измерение тока здесь не выполняется. */
p[22] = ump_can_count; p[23] = CanTimeOutErrorTR; record[6] = modbus[0x1C];
/* Исходные уставки — мА; эффективные уставки после ограничений — 0.1 мА. /* Слова 7/8 содержат штатные фиксированные уставки разгона 166: начальные 6 мА и конечные 16 мА. */
* p[8] — отправленный код, а p[9] — расчётное задание, НЕ измерение тока. */ record[7] = 6; record[8] = 16;
/* 166: fixed ramp endpoints; no configurable DAC_go/DAC_stop. */ /* Слова 9/10 передают последние ЗПТ1/ЗПТ2 в вольтах из CAN-индексов 305/8, соответствующих регистрам ПМ67 306/9. */
p[24] = 6; p[25] = 16; record[9] = ump_pm67_voltage[0]; record[10] = ump_pm67_voltage[1];
p[26] = DAC_min(); p[27] = DAC_max(); p[28] = DAC_cal(); /* Нулевое слово 11 дополняет запись до чётной длины: служебный CAN передаёт данные парами 16-битных слов. */
p[29] = DAC_04; p[30] = DAC_20; record[11] = 0;
p[31] = ump_dac_ramp; p[32] = ump_dac_duration; /* Обновляет полные команды и фактические дискреты для обнаружения следующих событий, сохраняя алгоритм триггера 166. */
p[33] = ump_dac_go10; p[34] = ump_dac_stop10; p[35] = ump_dac_position; ump_prev_commands = commands; ump_prev_inputs = record[4]; ump_prev_outputs = record[5];
for (i = 0; i < 4; i++) p[36+i] = adc_table_lem[i];
ump_prev_commands = commands; ump_prev_inputs = p[4]; ump_prev_outputs = p[5];
ump_next++; ump_next++;
if (ump_next == UMP_LOG_CAPACITY) ump_next = 0; if (ump_next == UMP_LOG_CAPACITY) ump_next = 0;
if (ump_count < UMP_LOG_CAPACITY) ump_count++; if (ump_count < UMP_LOG_CAPACITY) ump_count++;
ump_sequence++; ump_sequence++;
} }
/* Завершённый банк больше не изменяется до следующего отключения. /* Завершённый банк больше не изменяется до следующего отключения.
* Номер поколения позволяет GUI обнаружить замену архива во время чтения. */ * Номер поколения позволяет GUI обнаружить замену архива во время чтения. */
static void ump_freeze(void) static void ump_freeze(void)
{ {
ump_archive_bank = ump_bank; ump_archive_bank = ump_bank;
@@ -152,8 +152,8 @@ void ump_log_tick(void)
__restore_interrupts(saved); __restore_interrupts(saved);
} }
/* Дополнительный снимок только при изменении команд, входов или выходов. /* Дополнительный снимок только при изменении команд, входов или выходов.
* Это не заменяет периодическую запись аналоговых величин в таймере. */ * Это не заменяет периодическую запись аналоговых величин в таймере. */
void ump_log_io(void) void ump_log_io(void)
{ {
unsigned int saved; unsigned int saved;
@@ -164,17 +164,34 @@ void ump_log_io(void)
__restore_interrupts(saved); __restore_interrupts(saved);
} }
/* Вызывается после применения слов принятого CAN-кадра: снимок содержит /* Обновляет напряжения из принятых слов CAN даже до запуска записи;
* новые команды, а также исходный адрес/маску и все три слова кадра. */ * активный регистратор дополнительно сохраняет событие приёма. */
void ump_log_can(unsigned int header, unsigned int a, unsigned int b, unsigned int c) void ump_log_can(unsigned int header, unsigned int a, unsigned int b, unsigned int c)
{ {
unsigned int saved; /* Хранит прежнюю маску IRQ, индекс слова, текущий CAN-адрес, маску разрешения и три принятых 16-битных значения. */
if (ump_state != 1 || Desk != dsk_LOAD) return; unsigned int saved, word_index, address, mask, can_words[3];
/* Напряжения и журнал принадлежат плате нагрузки; другие аппаратные режимы их не обновляют. */
if (Desk != dsk_LOAD) return;
/* Исключает смешивание обновления напряжений с периодическим снимком таймера и восстанавливает прежние IRQ в конце. */
saved = __disable_interrupts(); saved = __disable_interrupts();
ump_can_header = header; /* Располагает три принятых слова в том же порядке, в котором заголовок задаёт их последовательные адреса. */
ump_can_data[0] = a; ump_can_data[1] = b; ump_can_data[2] = c; can_words[0] = a; can_words[1] = b; can_words[2] = c;
ump_can_count++; /* Младшие 13 бит заголовка задают нулевой индекс первого регистра CAN; верхние три бита являются масками слов. */
address = header & 0x1FFFU;
/* Старший бит 0x8000 разрешает первое слово, далее используются биты 0x4000 и 0x2000. */
mask = 0x8000U;
/* Продвигает адрес и маску для всех трёх позиций, включая пропущенные слова, чтобы не перепутать регистры ПМ67. */
for (word_index = 0; word_index < 3; word_index++, address++, mask >>= 1) {
/* Не использует содержимое позиции, если соответствующий бит заголовка не подтверждает её передачу. */
if (!(header & mask)) continue;
/* Индекс 305 соответствует регистру 306 ПМ67: суммарное напряжение ЗПТ1 передаётся в целых вольтах. */
if (address == 305U) ump_pm67_voltage[0] = can_words[word_index];
/* Индекс 8 соответствует регистру 9 ПМ67: суммарное напряжение ЗПТ2 передаётся в целых вольтах. */
if (address == 8U) ump_pm67_voltage[1] = can_words[word_index];
} /* Завершает разбор трёх слов CAN после обновления только подтверждённых напряжений. */
/* Сохраняет компактный снимок только при активной записи и готовности 166, которые проверяет ump_capture. */
ump_capture(2); ump_capture(2);
/* Возвращает исходную маску IRQ, в том числе при вызове из обработчика CAN. */
__restore_interrupts(saved); __restore_interrupts(saved);
} }
@@ -185,8 +202,8 @@ void ump_log_rs(void)
__restore_interrupts(saved); __restore_interrupts(saved);
} }
/* Управление журналом отделено от технологических команд: начало записи /* Управление журналом отделено от технологических команд: начало записи
* НЕ запускает УМП. Выбор архива не останавливает текущую запись. */ * НЕ запускает УМП. Выбор архива не останавливает текущую запись. */
int ump_log_write(unsigned int address, unsigned int value) int ump_log_write(unsigned int address, unsigned int value)
{ {
unsigned int saved, valid = 1; unsigned int saved, valid = 1;
@@ -211,8 +228,8 @@ int ump_log_write(unsigned int address, unsigned int value)
return valid; return valid;
} }
/* Преобразование хронологического индекса в физическую позицию кольца. /* Преобразование хронологического индекса в физическую позицию кольца.
* Для архива сохранены собственные count/next, независимые от живого банка. */ * Для архива сохранены собственные count/next, независимые от живого банка. */
static unsigned int ump_word(unsigned int archived, unsigned int record, unsigned int word) static unsigned int ump_word(unsigned int archived, unsigned int record, unsigned int word)
{ {
unsigned int count = archived ? ump_archive_count : ump_count; unsigned int count = archived ? ump_archive_count : ump_count;
@@ -225,16 +242,17 @@ static unsigned int ump_word(unsigned int archived, unsigned int record, unsigne
return logs_block[((unsigned long)bank * UMP_LOG_CAPACITY + slot) * UMP_LOG_WORDS + word]; return logs_block[((unsigned long)bank * UMP_LOG_CAPACITY + slot) * UMP_LOG_WORDS + word];
} }
/* Весь Modbus-блок читается вызывающим кодом под одной блокировкой IRQ. /* Весь Modbus-блок читается вызывающим кодом под одной блокировкой IRQ.
* Поэтому timestamp/данные и заголовок онлайн-блока относятся к одному * Поэтому timestamp/данные и заголовок онлайн-блока относятся к одному
* состоянию кольца, даже если в этот момент приходит новая CAN-команда. */ * состоянию кольца, даже если в этот момент приходит новая CAN-команда. */
unsigned int ump_log_read(unsigned int address) unsigned int ump_log_read(unsigned int address)
{ {
unsigned int offset, count; unsigned int offset, count;
unsigned long first; unsigned long first;
switch (address) { switch (address) {
case UMP_LOG_BASE: return 0x554D; case UMP_LOG_BASE: return 0x554D;
case UMP_LOG_BASE+1: return 2; /* Версия 4 сообщает SetGUI о 12-словной записи, исключая её ошибочный разбор как прежних 40 слов v2. */
case UMP_LOG_BASE+1: return 4;
case UMP_LOG_BASE+2: return ump_source ? 3 : ump_state; case UMP_LOG_BASE+2: return ump_source ? 3 : ump_state;
case UMP_LOG_BASE+3: return ump_source ? ump_archive_count : ump_count; case UMP_LOG_BASE+3: return ump_source ? ump_archive_count : ump_count;
case UMP_LOG_BASE+4: return UMP_LOG_WORDS; case UMP_LOG_BASE+4: return UMP_LOG_WORDS;
@@ -254,10 +272,11 @@ unsigned int ump_log_read(unsigned int address)
offset = address - UMP_LOG_DATA; offset = address - UMP_LOG_DATA;
return ump_word(ump_source, ump_cursor + offset / UMP_LOG_WORDS, offset % UMP_LOG_WORDS); return ump_word(ump_source, ump_cursor + offset / UMP_LOG_WORDS, offset % UMP_LOG_WORDS);
} }
/* Последние три записи для онлайн-графика, без остановки и без /* Последние десять записей для онлайн-графика, без остановки и без
* изменения курсора архивного чтения. Первые два слова — их номер. */ * изменения курсора архивного чтения. Первые два слова — их номер. */
if (address >= UMP_LOG_LIVE && address < UMP_LOG_LIVE+124) { if (address >= UMP_LOG_LIVE && address < UMP_LOG_LIVE+124) {
count = ump_count < 3 ? ump_count : 3; /* Ограничивает число целых записей ёмкостью 120-словного окна: формат v4 позволяет передать до десяти снимков. */
count = ump_count < UMP_LOG_LIVE_RECORDS ? ump_count : UMP_LOG_LIVE_RECORDS;
first = ump_sequence - count; first = ump_sequence - count;
offset = address - UMP_LOG_LIVE; offset = address - UMP_LOG_LIVE;
if (offset == 0) return (unsigned int)first; if (offset == 0) return (unsigned int)first;

View File

@@ -1,8 +1,8 @@
/* Инициализация и фоновый цикл платы. После настройки GPIO, обмена, /* Инициализация и фоновый цикл платы. После настройки GPIO, обмена,
* параметров и ЦАП UMP_pulse_init разрешает свежие команды СИФУ. * параметров и ЦАП UMP_pulse_init разрешает свежие команды СИФУ.
* В main остаются телеметрия, EEPROM и разбор готовых RS-пакетов. * В main остаются телеметрия, EEPROM и разбор готовых RS-пакетов.
* CAN-пуск и окончание импульса работают в IRQ, не ожидая main. * CAN-пуск и окончание импульса работают в IRQ, не ожидая main.
* RS-команда ещё должна пройти проверку CRC в get_command из main. * RS-команда ещё должна пройти проверку CRC в get_command из main.
*/ */
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
@@ -43,8 +43,7 @@ void timer_Init()
void main() void main()
{ {
int i,j,mask; int i,j; /* Счётчики остались для прежних операций main; выбор CAN-пакетов перенесён в независимый сервис. */
static unsigned int cancount[2], cancell[2];
RS_DATA * rs; RS_DATA * rs;
int presbyt=0; int presbyt=0;
@@ -100,7 +99,7 @@ void main()
if(Desk==dsk_LOAD) if(Desk==dsk_LOAD)
Setup_DAC_time(); Setup_DAC_time();
/* Завершена начальная настройка: только теперь разрешаем дискреты. */ /* Завершена начальная настройка: только теперь разрешаем дискреты. */
UMP_pulse_init(); UMP_pulse_init();
LastMode = Mode; LastMode = Mode;
@@ -110,32 +109,9 @@ void main()
while(1) while(1)
{ {
/* Чтение логгера по CAN не блокирует цикл управления. */ /* Чтение логгера по CAN не блокирует цикл управления. */
UMP_CAN_service(); UMP_CAN_service();
if(CanGO) CAN_telemetry_service(); /* Обслуживает heartbeat 1 Гц, изменения масок данных и индивидуальные повторы 1,3 с без ожидания CAN ACK. */
{
CanGO=0;
for(i=0;i<2;i++)
if(Cancount[i])
if(++cancount[i] >= Cancount[i])
{
cancount[i] = 0;
while(1)
{
if(cancell[i] >= 0x80) cancell[i]=0;
mask = Maska[i][cancell[i]/16] >> (cancell[i]%16);
if(!mask) cancell[i] = (cancell[i] + 0x10) & 0xFFF0;
else
{
while(!(mask & 1))
{
cancell[i]++; mask >>= 1;
}
break;
} }
CAN_send(0,modbus,cancell[i]);
cancell[i]+=3;
} }
if(cDefParam) if(cDefParam)
{ {
@@ -169,10 +145,10 @@ void main()
presbyt = bTermoCal; presbyt = bTermoCal;
} }
/* START/STOP исполняются при приёме CAN/RS, снимаются таймером. /* START/STOP исполняются при приёме CAN/RS, снимаются таймером.
* Здесь больше нет опроса уровня: main может ожидать EEPROM. */ * Здесь больше нет опроса уровня: main может ожидать EEPROM. */
/* Снимок после обновления входов и формирования пусковых выходов. */ /* Снимок после обновления входов и формирования пусковых выходов. */
ump_log_io(); ump_log_io();
for(i=0;i<2;i++) for(i=0;i<2;i++)
@@ -188,16 +164,16 @@ void main()
led2_toggle(); led2_toggle();
switch(j) switch(j)
{ {
case CMD_INIT: init(rs); break; // начальные установки case CMD_INIT: init(rs); break; // начальные установки
case CMD_INITLOAD: initload(rs); break; // настройка загрузки case CMD_INITLOAD: initload(rs); break; // настройка загрузки
case CMD_RUN: run(rs); break; // загрузить блок case CMD_RUN: run(rs); break; // загрузить блок
case CMD_LOAD: load(rs); break; // загрузить блок case CMD_LOAD: load(rs); break; // загрузить блок
case CMD_PEEK: peek(rs); break; // прочитать ачейку памати case CMD_PEEK: peek(rs); break; // прочитать ачейку памати
case CMD_POKE: poke(rs); break; // записать в ачейку памати case CMD_POKE: poke(rs); break; // записать в ачейку памати
case CMD_UPLOAD: upload(rs); break; // передать блок памати case CMD_UPLOAD: upload(rs); break; // передать блок памати
case CMD_EXTEND: extendbios(rs); break; // расширенные команды дла биоса case CMD_EXTEND: extendbios(rs); break; // расширенные команды дла биоса
case CMD_TFLASH: tflash(rs); break; // прошить TMS case CMD_TFLASH: tflash(rs); break; // прошить TMS
case CMD_MODBUS_3: ReceiveCommandModbus3(rs); break; case CMD_MODBUS_3: ReceiveCommandModbus3(rs); break;
case CMD_MODBUS_6: ReceiveCommandModbus6(rs); break; case CMD_MODBUS_6: ReceiveCommandModbus6(rs); break;

View File

@@ -1,8 +1,8 @@
/* Измерения, диагностика и периодическое обслуживание. ADC ISR /* Измерения, диагностика и периодическое обслуживание. ADC ISR
* поставляет выборки; таймер 1 обслуживает индикацию и телеметрию. * поставляет выборки; таймер 1 обслуживает индикацию и телеметрию.
* Для dsk_LOAD он сначала завершает импульс СИФУ, затем вызывает * Для dsk_LOAD он сначала завершает импульс СИФУ, затем вызывает
* расчёт ЦАП и снимок логгера. Частоты находятся в measure.h; * расчёт ЦАП и снимок логгера. Частоты находятся в measure.h;
* при их изменении требуется пересчитать зависимые интервалы. * при их изменении требуется пересчитать зависимые интервалы.
*/ */
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_SWPrioritizedIsrLevels.h" #include "DSP2833x_SWPrioritizedIsrLevels.h"
@@ -20,13 +20,13 @@
#include "message.h" #include "message.h"
#include "log_to_mem.h" #include "log_to_mem.h"
#include <math.h> // Это чтобы мерить амплитуду! sqrt без этого будет крив!!! #include <math.h> // Это чтобы мерить амплитуду! sqrt без этого будет крив!!!
unsigned int CanPowse=CANPOWSE,CanGO=0; unsigned int CanPowse=CANPOWSE,CanGO=0;
unsigned int Maska[2][8]; unsigned int Maska[2][8];
int TPL_CANS=0; // Количество температурных каналов int TPL_CANS=0; // Количество температурных каналов
int tpl_cans=0; int tpl_cans=0;
int cal_addr=0; int cal_addr=0;
@@ -53,23 +53,23 @@ int Curr_Edge;
float powK[] = float powK[] =
{ {
0.127, // питание 380В 0.127, // питание 380В
0.127, // питание 380В 0.127, // питание 380В
1.000, // ток 1.000, // ток
1.000, // напражение 1.000, // напражение
0.0076, // питание 31В 0.0076, // питание 31В
0.0076, // питание 24В 0.0076, // питание 24В
0.0076, // питание 24В 0.0076, // питание 24В
0.0076, // питание 15В 0.0076, // питание 15В
1.0000, // термодатчик мелкосхема 1.0000, // термодатчик мелкосхема
}; };
FILTERBAT def_FILTERBAT = DEF_FILTERBAT; FILTERBAT def_FILTERBAT = DEF_FILTERBAT;
FILTERBAT adc_filter[20+4]; // макс.TPL*2 + 4 калибр FILTERBAT adc_filter[20+4]; // макс.TPL*2 + 4 калибр
FILTERBAT out_filter[20+4]; // макс.TPL*2 + 4 напраж FILTERBAT out_filter[20+4]; // макс.TPL*2 + 4 напраж
FILTERBAT zer_filter[4]; // 4 напраж FILTERBAT zer_filter[4]; // 4 напраж
long sens_count[24+4]; long sens_count[24+4];
@@ -79,7 +79,7 @@ float K_T1,K_T2;
interrupt void cpu_timer1_isr_SENS(void); interrupt void cpu_timer1_isr_SENS(void);
/********************************************************************/ /********************************************************************/
/* Расчет модула тока из показаний двух фаз */ /* Расчет модула тока из показаний двух фаз */
/********************************************************************/ /********************************************************************/
float im_calc(float ia,float ib) float im_calc(float ia,float ib)
{ {
@@ -115,8 +115,8 @@ interrupt void cpu_timer1_isr_SENS(void)
int TST; int TST;
#define err_lamp work_lamp // это дла шкапа, #define err_lamp work_lamp // это дла шкапа,
#define alm_lamp heat_lamp // чтоб было понатнее #define alm_lamp heat_lamp // чтоб было понатнее
EALLOW; EALLOW;
CpuTimer1.InterruptCount++; CpuTimer1.InterruptCount++;
@@ -140,10 +140,10 @@ interrupt void cpu_timer1_isr_SENS(void)
if(Desk==dsk_LOAD) if(Desk==dsk_LOAD)
{ {
/* Снять истёкший импульс до расчёта ЦАП, независимо от main. */ /* Снять истёкший импульс до расчёта ЦАП, независимо от main. */
UMP_pulse_tick(); UMP_pulse_tick();
Load_runner(); Load_runner();
/* База времени 1 мс; снимок содержит результат текущего шага ЦАП. */ /* База времени 1 мс; снимок содержит результат текущего шага ЦАП. */
ump_log_tick(); ump_log_tick();
return; return;
} }
@@ -156,9 +156,9 @@ interrupt void cpu_timer1_isr_SENS(void)
((Desk==dsk_COMM) && heat_lamp) ) set_RES_OUT_1(); ((Desk==dsk_COMM) && heat_lamp) ) set_RES_OUT_1();
else clear_RES_OUT_1(); else clear_RES_OUT_1();
if(work_lamp) set_LED_OUT_1(); // Она же err_lamp дла шкапа if(work_lamp) set_LED_OUT_1(); // Она же err_lamp дла шкапа
else clear_LED_OUT_1(); else clear_LED_OUT_1();
if(heat_lamp) set_LED_OUT_2(); // Она же alm_lamp дла шкапа if(heat_lamp) set_LED_OUT_2(); // Она же alm_lamp дла шкапа
else clear_LED_OUT_2(); else clear_LED_OUT_2();
} }
@@ -360,37 +360,37 @@ void Init_packMask()
switch(Desk) switch(Desk)
{ {
case dsk_EPLT: case dsk_EPLT:
Maska[m_SLOW][0]|= 0x000F; // Полученное Maska[m_FAST][0]|= 0x000F; // Включает R0–R3 в быструю обратную связь VPU для ПМ67; четыре младших бита маски исключают ожидание медленного обхода параметров.
Maska[m_SLOW][6]|= 0x01FC; // Яркость ламп и одиночество Maska[m_SLOW][6]|= 0x01FC; // Яркость ламп и одиночество
break; break;
default: default:
for(i=0;i<can;i++) for(i=0;i<can;i++)
{ {
Maska[m_FAST][ i /16]|=(1<<( i %16)); // Диагностика Maska[m_FAST][ i /16]|=(1<<( i %16)); // Диагностика
Maska[m_FAST][(i+24)/16]|=(1<<((i+24)%16)); // Показаниа Maska[m_FAST][(i+24)/16]|=(1<<((i+24)%16)); // Показаниа
} }
for(i=0;i<3; i++) for(i=0;i<3; i++)
Maska[m_SLOW][i+3] = Maska[m_FAST][i]; // Уставки Maska[m_SLOW][i+3] = Maska[m_FAST][i]; // Уставки
if(Desk==dsk_BKSD) Maska[m_SLOW][7]|= 0x0300; // Калибровка термодатчиков if(Desk==dsk_BKSD) Maska[m_SLOW][7]|= 0x0300; // Калибровка термодатчиков
else else
Maska[m_SLOW][7]|= 0x0F00; // Калибровка термодатчиков Maska[m_SLOW][7]|= 0x0F00; // Калибровка термодатчиков
if(Kurrent) if(Kurrent)
{ Maska[m_SLOW][7]|= 0x000F; // Ноль датчиков напражениа { Maska[m_SLOW][7]|= 0x000F; // Ноль датчиков напражениа
Maska[m_SLOW][7]|= 0x00F0; // Калибровка датчиков напражениа Maska[m_SLOW][7]|= 0x00F0; // Калибровка датчиков напражениа
Maska[m_FAST][6]|= 0x3F00; // Фазные значениа Maska[m_FAST][6]|= 0x3F00; // Фазные значениа
} }
if(Desk==dsk_LOAD) if(Desk==dsk_LOAD)
{ Maska[m_SLOW][7]|= 0x0030; // Калибровка ЦАП { Maska[m_SLOW][7]|= 0x0030; // Калибровка ЦАП
Maska[m_FAST][7]|= 0xE000; // Дублировать команды Maska[m_FAST][7]|= 0xE000; // Дублировать команды
Maska[m_FAST][1]|= 0x3000; // Управлающий ток СИФУ Maska[m_FAST][1]|= 0x3000; // Управлающий ток СИФУ
} } } }
Maska[m_FAST][1]|= 0x0001; // Дискретные входы Maska[m_FAST][1]|= 0x0001; // Дискретные входы
Maska[m_SLOW][6]|= 0x0007; // Яркость ламп и периоды посылок Maska[m_SLOW][6]|= 0x0007; // Яркость ламп и периоды посылок
Maska[m_SLOW][7]|= 0xE000; // Адрес, команды, и чтоб не вылазило Maska[m_SLOW][7]|= 0xE000; // Адрес, команды, и чтоб не вылазило
} }
int er_anal(int term, long * count, long edge, int pre) int er_anal(int term, long * count, long edge, int pre)
@@ -449,26 +449,26 @@ void Current_count(int chan)
modbus[0x64+chan] = Numb; modbus[0x64+chan] = Numb;
// Средний (он же нулевой) уровень показаний АЦП // Средний (он же нулевой) уровень показаний АЦП
zer_count[chan] += (Numb-zer_count[chan])/(5.0 * ADC_FREQ); zer_count[chan] += (Numb-zer_count[chan])/(5.0 * ADC_FREQ);
Zero_lev[chan] = (int)(filterbat(&zer_filter[chan],zer_count[chan])); Zero_lev[chan] = (int)(filterbat(&zer_filter[chan],zer_count[chan]));
// Мгновенное значение фазы // Мгновенное значение фазы
Current = (Numb - Zero_lev[chan]) * powK[chan]; Current = (Numb - Zero_lev[chan]) * powK[chan];
// Действующее (среднеквадратичное) значение фазы // Действующее (среднеквадратичное) значение фазы
lev_quadr[chan] += ((Current*Current)-lev_quadr[chan])/(1.0 * ADC_FREQ); lev_quadr[chan] += ((Current*Current)-lev_quadr[chan])/(1.0 * ADC_FREQ);
lev_count[chan] = sqrt(lev_quadr[chan]); lev_count[chan] = sqrt(lev_quadr[chan]);
// Запомним // Запомним
if(ist) if(ist)
{ {
if(Desk==dsk_COMM) aCurrent =-Current; if(Desk==dsk_COMM) aCurrent =-Current;
else aCurrent = Current; // Запомнили мгновенное значение - дла амплитуды else aCurrent = Current; // Запомнили мгновенное значение - дла амплитуды
} }
else else
{ {
// Вычисление амплитуды // Вычисление амплитуды
Amplitude = filterbat(&out_filter[sens], im_calc(Current,aCurrent)); Amplitude = filterbat(&out_filter[sens], im_calc(Current,aCurrent));
if(sens_type[chan]==VOLTAGE) if(sens_type[chan]==VOLTAGE)
@@ -485,7 +485,7 @@ modbus[0x64+chan] = Numb;
sens_data[sens-1] = Level; sens_data[sens-1] = Level;
} }
// Действующее (среднеквадратичное) значение третьей фазы // Действующее (среднеквадратичное) значение третьей фазы
Numb =-Current-aCurrent; Numb =-Current-aCurrent;
lev_quadr[thrd] += (Numb*Numb-lev_quadr[thrd])/(1.0 * ADC_FREQ); lev_quadr[thrd] += (Numb*Numb-lev_quadr[thrd])/(1.0 * ADC_FREQ);
lev_count[thrd] = sqrt(lev_quadr[thrd]); lev_count[thrd] = sqrt(lev_quadr[thrd]);
@@ -511,12 +511,12 @@ modbus[0x68+fazz+1] = lev_count[chan];
modbus[0x68+fazz+2] = lev_count[thrd]; modbus[0x68+fazz+2] = lev_count[thrd];
} }
// Это максимальное // Это максимальное
Numb = lev_count[chan]; Numb = lev_count[chan];
if(Numb<lev_count[pair]) Numb = lev_count[pair]; if(Numb<lev_count[pair]) Numb = lev_count[pair];
if(Numb<lev_count[thrd]) Numb = lev_count[thrd]; if(Numb<lev_count[thrd]) Numb = lev_count[thrd];
// Зашиты! // Зашиты!
error.all = 0; error.all = 0;
no_ignor = !sens_error[chan].bit.Ignor; no_ignor = !sens_error[chan].bit.Ignor;
@@ -659,7 +659,7 @@ void Temper_count(int chan)
if(chan>tpl_cans) return; if(chan>tpl_cans) return;
// Kun именно чтоб скомпенсировать нечетность // Kun именно чтоб скомпенсировать нечетность
if(kun&1) Numb = (Numb-K300_2)*K_T2+ZERO; if(kun&1) Numb = (Numb-K300_2)*K_T2+ZERO;
else Numb = (Numb-K300_1)*K_T1+ZERO; else Numb = (Numb-K300_1)*K_T1+ZERO;
} }
@@ -706,7 +706,7 @@ sens_data[chan+8] = adc_table_tpl[chan];
error.all = 0; error.all = 0;
no_ignor = !sens_error[chan].bit.Ignor; no_ignor = !sens_error[chan].bit.Ignor;
// Обрыв или неисправность // Обрыв или неисправность
if(Temper==-20 || Temper==200) if(Temper==-20 || Temper==200)
{ {
error.bit.Tear = 1; error.bit.Tear = 1;
@@ -714,7 +714,7 @@ sens_data[chan+8] = adc_table_tpl[chan];
} }
else else
// Перегрев // Перегрев
if(((Temper>sens_hi_edge[chan]-Cooling) && (sens_error[chan].bit.Hyper)) || if(((Temper>sens_hi_edge[chan]-Cooling) && (sens_error[chan].bit.Hyper)) ||
(Temper>sens_hi_edge[chan]) ) (Temper>sens_hi_edge[chan]) )
{ {
@@ -724,7 +724,7 @@ sens_data[chan+8] = adc_table_tpl[chan];
} }
else else
// Предупреждение по температуре // Предупреждение по температуре
if(Temper>sens_lo_edge[chan]) if(Temper>sens_lo_edge[chan])
{ {
error.bit.Over = 1; error.bit.Over = 1;
@@ -796,7 +796,7 @@ void Power_count(int chan)
error.bit.Stop = 1; error.bit.Stop = 1;
} } } }
/* Повышенное напражение /* Повышенное напражение
if(Power > sens_hi_edge[chan]) if(Power > sens_hi_edge[chan])
{ {
error.bit.Hyper = 1; error.bit.Hyper = 1;

View File

@@ -1,8 +1,8 @@
/* Параметры и обработчики Modbus после проверки CRC. Массив modbus /* Параметры и обработчики Modbus после проверки CRC. Массив modbus
* содержит обычные адреса 0..127, область 0x1000 обслуживает логгер. * содержит обычные адреса 0..127, область 0x1000 обслуживает логгер.
* EEPROM хранит параметры, но не является источником START/STOP: * EEPROM хранит параметры, но не является источником START/STOP:
* при загрузке сохраняется последняя живая команда нагрузки. * при загрузке сохраняется последняя живая команда нагрузки.
* Функции вызываются из main; EEPROM блокирует этот контекст. * Функции вызываются из main; EEPROM блокирует этот контекст.
*/ */
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "package.h" #include "package.h"
@@ -21,9 +21,12 @@
#include "ecan.h" #include "ecan.h"
#include "pulto.h" #include "pulto.h"
#include "spise2p.h" #include "spise2p.h"
#include "include/balsam167_eeprom_block.h" /* Использует общий с 167 контракт FC03: окно 0x8000..0xBFFF, до 120 слов AT25256B за запрос. */
#include "caliber.h" #include "caliber.h"
#include "log_to_mem.h" #include "log_to_mem.h"
#include "firmware_info.h" /* Подключает адрес и границы неизменяемого паспорта 0x1200, совместимого с проверкой прошивки в 167. */
#include "../src/firmware_info_static.c" /* Собирает общие 12 слов firmware-info через include-путь firmware-info/include; как в 167, копии упаковщика в проекте нет. */
#include "DAC.h" #include "DAC.h"
int modbus[ANSWER_LEN+1]; int modbus[ANSWER_LEN+1];
@@ -47,7 +50,7 @@ void Default_params()
for(i=0;i<ANSWER_LEN;i++) for(i=0;i<ANSWER_LEN;i++)
{ {
/* Команда нагрузки не является параметром по умолчанию. */ /* Команда нагрузки не является параметром по умолчанию. */
if (Desk != dsk_LOAD || i != 127) Modbus[i].all = 0; if (Desk != dsk_LOAD || i != 127) Modbus[i].all = 0;
} }
@@ -56,17 +59,17 @@ void Default_params()
if(Desk == dsk_EPLT) if(Desk == dsk_EPLT)
{ {
Cancount[m_FAST] = 2; // пауза между посылками CAN Cancount[m_FAST] = 10; // Задаёт для пульта быстрый CAN-пакет раз в 10 базовых интервалов CANPOWSE по 20 мс, то есть примерно 200 мс; это значение по умолчанию, которое могут заменить параметры EEPROM.
for(i=0;i<6;i++) Bright[i] = bright[i]; for(i=0;i<6;i++) Bright[i] = bright[i];
} }
else else
{ {
Cancount[m_FAST] = 10; // пауза между посылками CAN Cancount[m_FAST] = 12; // пауза между посылками CAN
Brightness = 8; Brightness = 8;
} }
Cancount[m_SLOW] = 101; // пауза между посылками CAN Cancount[m_SLOW] = 50; // Задаёт медленную CAN-рассылку раз в 50 базовых интервалов CANPOWSE по 20 мс, то есть примерно раз в секунду; это значение по умолчанию могут заменить параметры EEPROM.
if(Kalibro) if(Kalibro)
{ {
@@ -126,9 +129,9 @@ void Default_params()
DAC_20 = Caliber[6]; DAC_20 = Caliber[6];
DAC_04 = Caliber[7]; DAC_04 = Caliber[7];
/* Не врема! /* Не врема!
DAC_go = 6; // начало зарада DAC_go = 6; // начало зарада
DAC_stop= 15; // конец зарада DAC_stop= 15; // конец зарада
*/ */
} }
@@ -139,9 +142,9 @@ void Default_params()
Init_sensors_more(); Init_sensors_more();
} }
/* CRC и Mode проверяются до применения EEPROM. Слово 127 /* CRC и Mode проверяются до применения EEPROM. Слово 127
* нагрузки не копируется даже временно: ISR не должен увидеть * нагрузки не копируется даже временно: ISR не должен увидеть
* старый START из EEPROM либо потерять текущую CAN-команду. * старый START из EEPROM либо потерять текущую CAN-команду.
*/ */
void Load_params() void Load_params()
{ {
@@ -153,7 +156,7 @@ void Load_params()
(crc !=0xFFFF) && (crc !=0xFFFF) &&
(Mode == param[126])) (Mode == param[126]))
{ {
/* Не восстанавливать START/STOP из EEPROM даже на один тик ISR. */ /* Не восстанавливать START/STOP из EEPROM даже на один тик ISR. */
for(i=0;i<ANSWER_LEN;i++) for(i=0;i<ANSWER_LEN;i++)
if (Desk != dsk_LOAD || i != 127) modbus[i] = param[i]; if (Desk != dsk_LOAD || i != 127) modbus[i] = param[i];
UMP_reset_parameter_commands(); UMP_reset_parameter_commands();
@@ -169,9 +172,9 @@ void Load_params()
Caliber_time = 0xFFFF; Caliber_time = 0xFFFF;
} } } } } }
/* ISR продолжает менять измерения во время сбора param. CRC /* ISR продолжает менять измерения во время сбора param. CRC
* относится к собранному массиву, а не атомарному снимку всей платы. * относится к собранному массиву, а не атомарному снимку всей платы.
* Не вызывать сохранение из критического пути дискретов. * Не вызывать сохранение из критического пути дискретов.
*/ */
void Save_params() void Save_params()
{ {
@@ -191,8 +194,8 @@ void Save_params()
/***************************************************************/ /***************************************************************/
/***************************************************************/ /***************************************************************/
/* Передача данных по протоколу ModBus - команда 3 /* Передача данных по протоколу ModBus - команда 3
Чтение ачеек данных */ Чтение ачеек данных */
/***************************************************************/ /***************************************************************/
/***************************************************************/ /***************************************************************/
@@ -212,40 +215,63 @@ void ReceiveCommandModbus3(RS_DATA *rs_arr)
{ {
unsigned int crc, Address_MB, Length_MB, i, value, saved = 0; unsigned int crc, Address_MB, Length_MB, i, value, saved = 0;
// получили начальный адрес чтениа // получили начальный адрес чтениа
Address_MB = (rs_arr->RS_Header[2] << 8) | rs_arr->RS_Header[3]; Address_MB = (rs_arr->RS_Header[2] << 8) | rs_arr->RS_Header[3];
// получили количество слов данных // получили количество слов данных
Length_MB = (rs_arr->RS_Header[4] << 8) | rs_arr->RS_Header[5]; Length_MB = (rs_arr->RS_Header[4] << 8) | rs_arr->RS_Header[5];
if (Address_MB >= BALSAM167_EEPROM_RTU_BASE) { /* Выделяет только верхнее окно EEPROM; старые регистры, логгер и паспорт обрабатываются прежним кодом ниже. */
if (!balsam167_eeprom_block_valid_profile(CMD_MODBUS_3, Address_MB, Length_MB, 0U)) { /* Профиль 0 сохраняет контракт 167 для 32 КиБ: запрещает пустой блок, более 120 слов, M95 и выход за конец окна. */
modbus_exception(rs_arr, CMD_MODBUS_3, 2U); /* Возвращает Illegal Data Address с CRC до любого обращения к SPI при неверном диапазоне. */
return; /* Не допускает перехода ошибочного запроса EEPROM к backend логгера или обычным регистрам. */
} /* Валидатор проверяет конец через вычитание, поэтому переполнение 16-битного адреса не разрешает чтение. */
Seeprom_read(Address_MB - BALSAM167_EEPROM_RTU_BASE, &rs_arr->buffer[3], Length_MB * 2U); /* Как в 167, SPI получает адрес в 16-битных словах и длину в октетах; IRQ остаются разрешены для автомата Timer2. */
for (i = Length_MB; i > 0U; --i) { /* Разворачивает прочитанные слова с конца в том же UART-буфере без нового массива и перезаписи ещё не обработанных слов. */
value = rs_arr->buffer[i + 2U]; /* Временное слово сохраняет оба SPI-октета до расширения одного элемента C28x в два октета RTU. */
rs_arr->buffer[i * 2U + 2U] = value & 0xFFU; /* Записывает младший октет слова после старшего, как требует физический дамп EEPROM в SETGUI. */
rs_arr->buffer[i * 2U + 1U] = (value >> 8) & 0xFFU; /* Маска 0xFF выделяет восемь бит линии из 16-битного unsigned int C28x. */
} /* Обратный обход корректен и для одного слова, и для максимального блока из 120 слов. */
rs_arr->buffer[0] = CNTRL_ADDR; /* Отвечает собственным адресом платы, сохраняя поддержку общего адреса 16 существующим приёмником. */
rs_arr->buffer[1] = CMD_MODBUS_3; /* Возвращает стандартную команду FC03 без введения отдельной команды BIOS или записи памяти. */
rs_arr->buffer[2] = Length_MB * 2U; /* Число полезных октетов находится в диапазоне 2..240 и помещается в одном октете RTU. */
crc = get_crc_16(0xFFFFU, rs_arr->buffer, Length_MB * 2U + 3U); /* Проверяет адрес, команду, длину и весь блок тем же Modbus CRC16, что остальные ответы прошивки. */
rs_arr->buffer[Length_MB * 2U + 3U] = LOBYTE(crc); /* Передаёт младший октет CRC первым в соответствии с Modbus RTU. */
rs_arr->buffer[Length_MB * 2U + 4U] = HIBYTE(crc); /* Завершает кадр старшим октетом CRC без устаревшего нулевого хвоста. */
rs_arr->flag_TIMEOUT_to_Send = true; /* Использует штатное управление таймаутом UART при отправке готового ответа из main. */
RS_Send(rs_arr, rs_arr->buffer, Length_MB * 2U + 5U); /* Отправляет ровно 5 служебных октетов плюс данные, максимум 245 элементов из существующего буфера на 400. */
return; /* Завершает только новый маршрут EEPROM, сохраняя прежние форматы остальных ответов FC03. */
} /* Новый маршрут не меняет PEEK, запись EEPROM, адреса параметров или драйвер SPI. */
if (!Length_MB || Length_MB > 125 || if (!Length_MB || Length_MB > 125 ||
!((Address_MB < ANSWER_LEN && Length_MB <= ANSWER_LEN-Address_MB) || !((Address_MB < ANSWER_LEN && Length_MB <= ANSWER_LEN-Address_MB) ||
(Address_MB >= UMP_LOG_BASE && Address_MB <= UMP_LOG_BASE+15 && (Address_MB >= UMP_LOG_BASE && Address_MB <= UMP_LOG_BASE+15 &&
Length_MB <= UMP_LOG_BASE+16-Address_MB) || Length_MB <= UMP_LOG_BASE+16-Address_MB) ||
(Address_MB >= UMP_LOG_DATA && Address_MB < UMP_LOG_DATA+120 && (Address_MB >= UMP_LOG_DATA && Address_MB < UMP_LOG_DATA+120 &&
Length_MB <= UMP_LOG_DATA+120-Address_MB) || Length_MB <= UMP_LOG_DATA+120-Address_MB) ||
(Address_MB == UMP_LOG_LIVE && Length_MB == 124))) { (Address_MB == UMP_LOG_LIVE && Length_MB == 124) || /* Сохраняет точное прежнее 124-словное онлайн-окно логгера. */
firmware_info_range(Address_MB, Length_MB))) { /* Дополнительно разрешает только полное или частичное чтение двенадцати регистров паспорта. */
modbus_exception(rs_arr, CMD_MODBUS_3, 2); return; modbus_exception(rs_arr, CMD_MODBUS_3, 2); return;
} }
///////////////////////////////////////////////// /////////////////////////////////////////////////
// Отсылка // Отсылка
/* Посчитали контрольную сумму перед самой посылкой */ /* Посчитали контрольную сумму перед самой посылкой */
rs_arr->buffer[0] = CNTRL_ADDR; rs_arr->buffer[0] = CNTRL_ADDR;
rs_arr->buffer[1] = CMD_MODBUS_3; rs_arr->buffer[1] = CMD_MODBUS_3;
rs_arr->buffer[2] = Length_MB*2; rs_arr->buffer[2] = Length_MB*2;
/* Защищаем целостность одного снимка/блока; передача UART идёт уже /* Защищаем целостность одного снимка/блока; передача UART идёт уже
* с разрешёнными прерываниями и не задерживает измерение/управление. */ * с разрешёнными прерываниями и не задерживает измерение/управление. */
if (Address_MB >= UMP_LOG_BASE) saved = __disable_interrupts(); if (Address_MB >= UMP_LOG_BASE && Address_MB < FIRMWARE_INFO_ADDRESS) saved = __disable_interrupts(); /* Неизменяемый паспорт не требует блокировки IRQ; целостность прежних снимков логгера сохраняется. */
for (i=0;i<Length_MB;i++) for (i=0;i<Length_MB;i++)
{ {
value = Address_MB >= UMP_LOG_BASE ? ump_log_read(Address_MB+i) : modbus[Address_MB+i]; if (Address_MB >= FIRMWARE_INFO_ADDRESS) value = firmware_info_static_read(Address_MB - FIRMWARE_INFO_ADDRESS + i); /* После проверки диапазона читает только соответствующее слово статического паспорта, без обращения к логгеру. */
else value = Address_MB >= UMP_LOG_BASE ? ump_log_read(Address_MB+i) : (unsigned int)modbus[Address_MB+i]; /* Сохраняет прежнюю маршрутизацию и беззнаковое представление 16-битных слов технологической карты и логгера v4. */
rs_arr->buffer[3+i*2] = (value >> 8) & 0xFF; rs_arr->buffer[3+i*2] = (value >> 8) & 0xFF;
rs_arr->buffer[3+i*2+1] = value & 0xFF; rs_arr->buffer[3+i*2+1] = value & 0xFF;
} }
if (Address_MB >= UMP_LOG_BASE) __restore_interrupts(saved); if (Address_MB >= UMP_LOG_BASE && Address_MB < FIRMWARE_INFO_ADDRESS) __restore_interrupts(saved); /* Возвращает сохранённую маску только для действительно защищённого снимка логгера. */
crc = 0xffff; crc = 0xffff;
crc = get_crc_16(crc, rs_arr->buffer, Length_MB*2+3); crc = get_crc_16(crc, rs_arr->buffer, Length_MB*2+3);
@@ -258,9 +284,9 @@ void ReceiveCommandModbus3(RS_DATA *rs_arr)
rs_arr->buffer[Length_MB*2+8] = 0; rs_arr->buffer[Length_MB*2+8] = 0;
rs_arr->flag_TIMEOUT_to_Send=true; rs_arr->flag_TIMEOUT_to_Send=true;
/* Расширение логгера отвечает точным кадром Modbus без хвостовых /* Расширение логгера отвечает точным кадром Modbus без хвостовых
* нулей: они иначе попали бы в начало ответа следующего блока GUI. * нулей: они иначе попали бы в начало ответа следующего блока GUI.
* Исторический формат технологических регистров оставлен прежним. */ * Исторический формат технологических регистров оставлен прежним. */
RS_Send(rs_arr, rs_arr->buffer, Length_MB*2+(Address_MB >= UMP_LOG_BASE ? 5 : 8)); RS_Send(rs_arr, rs_arr->buffer, Length_MB*2+(Address_MB >= UMP_LOG_BASE ? 5 : 8));
return; return;
@@ -271,26 +297,27 @@ void ReceiveCommandModbus6(RS_DATA *rs_arr)
unsigned int Address_MB, Data_MB, i; unsigned int Address_MB, Data_MB, i;
///////////////////////////////////////////////// /////////////////////////////////////////////////
// Отсылка // Отсылка
/* Отправлаем назад то же самое */ /* Отправлаем назад то же самое */
for (i=0;i<8;i++) for (i=0;i<8;i++)
rs_arr->buffer[i] = rs_arr->RS_Header[i]; rs_arr->buffer[i] = rs_arr->RS_Header[i];
// получили начальный адрес записи // получили начальный адрес записи
Address_MB = (rs_arr->RS_Header[2] << 8) | rs_arr->RS_Header[3]; Address_MB = (rs_arr->RS_Header[2] << 8) | rs_arr->RS_Header[3];
// получили слово данных // получили слово данных
Data_MB = (rs_arr->RS_Header[4] << 8) | rs_arr->RS_Header[5]; Data_MB = (rs_arr->RS_Header[4] << 8) | rs_arr->RS_Header[5];
if (Address_MB >= FIRMWARE_INFO_ADDRESS && Address_MB < FIRMWARE_INFO_END) { modbus_exception(rs_arr, CMD_MODBUS_6, 2); return; } /* Как в контракте 167, запись в паспорт запрещена с Illegal Data Address и не достигает параметров или логгера. */
if (Address_MB >= UMP_LOG_BASE) { if (Address_MB >= UMP_LOG_BASE) {
if (!ump_log_write(Address_MB, Data_MB)) { if (!ump_log_write(Address_MB, Data_MB)) {
modbus_exception(rs_arr, CMD_MODBUS_6, 3); return; modbus_exception(rs_arr, CMD_MODBUS_6, 3); return;
} }
} else if (Address_MB < ANSWER_LEN) { } else if (Address_MB < ANSWER_LEN) {
/* RS и CAN используют одну историю фронтов. Чередование каналов /* RS и CAN используют одну историю фронтов. Чередование каналов
* не создаёт двух независимых повторных запусков. */ * не создаёт двух независимых повторных запусков. */
if (Address_MB == 127) { if (Address_MB == 127) {
UMP_commands_write(Data_MB); UMP_commands_write(Data_MB);
ump_log_rs(); ump_log_rs();

View File

@@ -1,8 +1,8 @@
/* Выбор типа платы, направления GPIO и чтение входов. get_Mode /* Выбор типа платы, направления GPIO и чтение входов. get_Mode
* читает аппаратный адрес и выбирает Desk. Один вывод в разных * читает аппаратный адрес и выбирает Desk. Один вывод в разных
* режимах может иметь разное назначение. Для нагрузки START=GPIO62, * режимах может иметь разное назначение. Для нагрузки START=GPIO62,
* STOP=GPIO58, RES_OUT_2=GPIO3 (активный ноль). Направления заданы * STOP=GPIO58, RES_OUT_2=GPIO3 (активный ноль). Направления заданы
* в GPIO_table.h; изменение распиновки требует сверки со схемой. * в GPIO_table.h; изменение распиновки требует сверки со схемой.
*/ */
#include "DSP2833x_Device.h" // DSP281x Headerfile Include File #include "DSP2833x_Device.h" // DSP281x Headerfile Include File
#include "filter_bat2.h" #include "filter_bat2.h"
@@ -51,10 +51,10 @@ void get_Mode()
{ {
EALLOW; EALLOW;
GpioCtrlRegs.GPAMUX1.all &= 0xFF000000; // 00—11 GpioCtrlRegs.GPAMUX1.all &= 0xFF000000; // 00—11
GpioCtrlRegs.GPAMUX2.all &= 0xFF00003F; // 19—27 GpioCtrlRegs.GPAMUX2.all &= 0xFF00003F; // 19—27
GpioCtrlRegs.GPBMUX1.all &= 0xFFFFFFC0; // 32—34 GpioCtrlRegs.GPBMUX1.all &= 0xFFFFFFC0; // 32—34
GpioCtrlRegs.GPBMUX2.all &= 0x000FF000; // 48—53, 58—63 GpioCtrlRegs.GPBMUX2.all &= 0x000FF000; // 48—53, 58—63
GpioCtrlRegs.GPADIR.bit.GPIO20 = 0; GpioCtrlRegs.GPADIR.bit.GPIO20 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO21 = 0; GpioCtrlRegs.GPADIR.bit.GPIO21 = 0;
@@ -187,7 +187,7 @@ void get_Buttons()
Inputs.all = butt; Inputs.all = butt;
} }
/* Ничего такого в действительности нет /* Ничего такого в действительности нет
if(Desk==dsk_BKST) if(Desk==dsk_BKST)
{ bSecretBt = !GpioDataRegs.GPBDAT.bit.GPIO63; { bSecretBt = !GpioDataRegs.GPBDAT.bit.GPIO63;
InputRep1 = bSecretBt; InputRep1 = bSecretBt;
@@ -205,14 +205,14 @@ void get_Buttons()
if(Desk==dsk_EPLT) if(Desk==dsk_EPLT)
{ {
bTestLamp = er_anal(GpioDataRegs.GPADAT.bit.GPIO26, &INcount0, 1000, 0); /* Таймер пульта включает местный тест после непрерывного удержания TESTLAMP в течение 2 с; число проходов main не влияет на задержку. */
if(GpioDataRegs.GPADAT.bit.GPIO27) butt +=0x0001; if(GpioDataRegs.GPADAT.bit.GPIO27) butt +=0x0001;
if(GpioDataRegs.GPADAT.bit.GPIO24) butt +=0x0002; if(GpioDataRegs.GPADAT.bit.GPIO24) butt +=0x0002;
if(GpioDataRegs.GPBDAT.bit.GPIO53) butt +=0x0004; if(GpioDataRegs.GPBDAT.bit.GPIO53) butt +=0x0004;
if(GpioDataRegs.GPBDAT.bit.GPIO50) butt +=0x0008; if(GpioDataRegs.GPBDAT.bit.GPIO50) butt +=0x0008;
if(GpioDataRegs.GPADAT.bit.GPIO26) butt +=0x0010; if(GpioDataRegs.GPADAT.bit.GPIO26) butt +=0x0010; // Передаёт исходное состояние TESTLAMP в бите 4 слова Inputs (0x10), по которому основной контроллер вызывает сброс ошибок при коротком нажатии.
if(GpioDataRegs.GPADAT.bit.GPIO23) butt +=0x0020; if(GpioDataRegs.GPADAT.bit.GPIO23) butt +=0x0020;
if(GpioDataRegs.GPBDAT.bit.GPIO52) butt +=0x0040; if(GpioDataRegs.GPBDAT.bit.GPIO52) butt +=0x0040;
if(GpioDataRegs.GPADAT.bit.GPIO4 ) butt +=0x0080; if(GpioDataRegs.GPADAT.bit.GPIO4 ) butt +=0x0080;
@@ -223,7 +223,7 @@ void get_Buttons()
if(GpioDataRegs.GPADAT.bit.GPIO5 ) butt +=0x0800; if(GpioDataRegs.GPADAT.bit.GPIO5 ) butt +=0x0800;
if(GpioDataRegs.GPBDAT.bit.GPIO48) butt +=0x1000; if(GpioDataRegs.GPBDAT.bit.GPIO48) butt +=0x1000;
if(GpioDataRegs.GPADAT.bit.GPIO10) butt +=0x2000; // Секретный вход if(GpioDataRegs.GPADAT.bit.GPIO10) butt +=0x2000; // Секретный вход
Inputs.all = butt; Inputs.all = butt;
} }
@@ -267,4 +267,4 @@ void get_Buttons()
butt += 8 * !GpioDataRegs.GPBDAT.bit.GPIO51; butt += 8 * !GpioDataRegs.GPBDAT.bit.GPIO51;
Jumpers = butt; Jumpers = butt;
} }

View File

@@ -1,7 +1,7 @@
/* Логика пульта и индикации. cpu_timer1_isr_PULT выбирается /* Логика пульта и индикации. cpu_timer1_isr_PULT выбирается
* только для dsk_EPLT; для нагрузки работает обработчик из measure.c. * только для dsk_EPLT; для нагрузки работает обработчик из measure.c.
* Lonely относится к активности обмена, не к задержке пуска СИФУ. * Lonely относится к активности обмена, не к задержке пуска СИФУ.
* Не смешивать функции двух режимов при изменении общего таймера. * Не смешивать функции двух режимов при изменении общего таймера.
*/ */
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_SWPrioritizedIsrLevels.h" #include "DSP2833x_SWPrioritizedIsrLevels.h"
@@ -43,6 +43,7 @@ interrupt void cpu_timer1_isr_PULT(void)
static int cownt=0,count_bright; static int cownt=0,count_bright;
unsigned int light=0, i; unsigned int light=0, i;
unsigned int Alone = 20*READY_FREQ; unsigned int Alone = 20*READY_FREQ;
static unsigned int test_lamp_hold_ticks = 0; // Считает длительность непрерывного нажатия GPIO26 в тиках READY_FREQ; насыщение на пороге исключает переполнение при долгом удержании.
EALLOW; EALLOW;
CpuTimer1.InterruptCount++; CpuTimer1.InterruptCount++;
@@ -60,8 +61,8 @@ interrupt void cpu_timer1_isr_PULT(void)
toggle_ONLINE(); toggle_ONLINE();
toggle_RES_OUT_1(); // типа это готовность toggle_RES_OUT_1(); // Формирует на резервном выходе 1 меандр с частотой READY_FREQ/2 (500 Гц) для контроля работы таймера пульта.
toggle_RES_OUT_2(); // на всакий toggle_RES_OUT_2(); // Дублирует переключения таймера на резервном выходе 2 с частотой READY_FREQ/2 (500 Гц) для контроля активности пульта.
if(++Lonely > Alone) Lonely = Alone; if(++Lonely > Alone) Lonely = Alone;
@@ -74,6 +75,14 @@ interrupt void cpu_timer1_isr_PULT(void)
if(++cownt>2) cownt=0; if(++cownt>2) cownt=0;
if(GpioDataRegs.GPADAT.bit.GPIO26) // Единица GPIO26 означает нажатие TESTLAMP, как и бит 4 Inputs; таймер измеряет удержание независимо от загрузки main.
{ // Накапливает время текущего нажатия перед включением местного теста ламп.
if(test_lamp_hold_ticks < 2U * (unsigned int)READY_FREQ) // Две секунды при частоте READY_FREQ Гц соответствуют 2000 тикам текущего таймера 1000 Гц.
test_lamp_hold_ticks++; // Добавляет один период таймера (1 мс); после достижения порога счётчик сохраняет значение до отпускания.
} // Завершает обработку удерживаемой кнопки.
else test_lamp_hold_ticks = 0; // При отпускании обнуляет время, чтобы отдельные короткие нажатия не складывались в длинное.
bTestLamp = (test_lamp_hold_ticks >= 2U * (unsigned int)READY_FREQ); // Включает местный тест после 2 с удержания и выключает при отпускании; короткое нажатие остаётся сигналом сброса для основного контроллера.
if(cTestLamp|bTestLamp) if(cTestLamp|bTestLamp)
{ {
what_is(); what_is();

View File

@@ -1,8 +1,8 @@
/* SPI EEPROM. Seeprom_read/write разбивают запрос на страницы /* SPI EEPROM. Seeprom_read/write разбивают запрос на страницы
* и синхронно ждут spiSe2pFree. SPI-автомат продвигает таймер 2 * и синхронно ждут spiSe2pFree. SPI-автомат продвигает таймер 2
* каждые 100 мкс. При запрете этого IRQ ожидание не завершится. * каждые 100 мкс. При запрете этого IRQ ожидание не завершится.
* Тайм-аут в старом драйвере отсутствует. Дискреты СИФУ теперь * Тайм-аут в старом драйвере отсутствует. Дискреты СИФУ теперь
* не зависят от того, завершилось ли это ожидание в main. * не зависят от того, завершилось ли это ожидание в main.
*/ */
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
@@ -25,8 +25,8 @@ int ccc=0;
/******* SPI bus Serial EEPROM driver Initialization routine ********/ /******* SPI bus Serial EEPROM driver Initialization routine ********/
/********************************************************************/ /********************************************************************/
/* Блокирует main до завершения страниц. Запрет IRQ остановит /* Блокирует main до завершения страниц. Запрет IRQ остановит
* SPI-автомат. CAN и таймер СИФУ должны прерывать это ожидание. * SPI-автомат. CAN и таймер СИФУ должны прерывать это ожидание.
*/ */
void Seeprom_write( unsigned int adres, void Seeprom_write( unsigned int adres,
unsigned int buf[], unsigned int buf[],
@@ -59,8 +59,8 @@ void Seeprom_write( unsigned int adres,
CpuTimer2Regs.TCR.all = 0x4010; // Use write-only instruction to set TSS bit = 1 CpuTimer2Regs.TCR.all = 0x4010; // Use write-only instruction to set TSS bit = 1
} }
/* Чтение также синхронное для main, тайм-аут не реализован. /* Чтение также синхронное для main, тайм-аут не реализован.
* При зависании проверить step/SPI и работу таймера 2. * При зависании проверить step/SPI и работу таймера 2.
*/ */
void Seeprom_read( unsigned int adres, void Seeprom_read( unsigned int adres,
unsigned int buf[], unsigned int buf[],

View File

@@ -1,7 +1,7 @@
/* Внешняя память и программные задержки. init_zone7 готовит XINTF /* Внешняя память и программные задержки. init_zone7 готовит XINTF
* до первого обращения к .logg; времена шины зависят от частоты DSP * до первого обращения к .logg; времена шины зависят от частоты DSP
* и аппаратной памяти. pause_us занимает CPU циклом и используется * и аппаратной памяти. pause_us занимает CPU циклом и используется
* при инициализации. Длительность СИФУ должна задаваться таймером. * при инициализации. Длительность СИФУ должна задаваться таймером.
*/ */
#include "DSP2833x_Device.h" // DSP281x Headerfile Include File #include "DSP2833x_Device.h" // DSP281x Headerfile Include File

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<projectDescription> <projectDescription>
<name>Balsam_166</name> <name>28335_periph</name>
<comment></comment> <comment></comment>
<projects> <projects>
</projects> </projects>
@@ -28,162 +28,177 @@
<link> <link>
<name>F28335.cmd</name> <name>F28335.cmd</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/F28335.cmd</locationURI> <locationURI>SRC_ROOT12/F28335.cmd</locationURI>
</link> </link>
<link> <link>
<name>UKSSTMS320F28335.pjt</name> <name>UKSSTMS320F28335.pjt</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/UKSSTMS320F28335.pjt</locationURI> <locationURI>SRC_ROOT12/UKSSTMS320F28335.pjt</locationURI>
</link> </link>
<link> <link>
<name>Debug/UKSSTMS320F28335.out</name> <name>Debug/UKSSTMS320F28335.out</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT/Bin/UKSSTMS320F28335.out</locationURI> <locationURI>SRC_ROOT12/Bin/UKSSTMS320F28335.out</locationURI>
</link> </link>
<link> <link>
<name>Libraries/rts2800_fpu32.lib</name> <name>Libraries/rts2800_fpu32.lib</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Libraries/rts2800_fpu32.lib</locationURI> <locationURI>SRC_ROOT12/Libraries/rts2800_fpu32.lib</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/ADC.c</name> <name>Source/Internal/ADC.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/ADC.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/ADC.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/DAC.c</name> <name>Source/Internal/DAC.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/DAC.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/DAC.c</locationURI>
</link>
<link>
<name>Source/Internal/Include</name>
<type>2</type>
<locationURI>SRC_ROOT12/Source/Internal/Include</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/RS485.c</name> <name>Source/Internal/RS485.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/RS485.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/RS485.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/bios.c</name> <name>Source/Internal/bios.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/bios.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/bios.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/cntrl_adr.c</name> <name>Source/Internal/cntrl_adr.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/cntrl_adr.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/cntrl_adr.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/crc16.c</name> <name>Source/Internal/crc16.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/crc16.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/crc16.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/ecan.c</name> <name>Source/Internal/ecan.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/ecan.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/ecan.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/filter_bat2.c</name> <name>Source/Internal/filter_bat2.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/filter_bat2.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/filter_bat2.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/kanal.c</name> <name>Source/Internal/kanal.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/kanal.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/kanal.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/log_to_mem.c</name> <name>Source/Internal/log_to_mem.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/log_to_mem.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/log_to_mem.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/main.c</name> <name>Source/Internal/main.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/main.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/main.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/measure.c</name> <name>Source/Internal/measure.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/measure.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/measure.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/message.c</name> <name>Source/Internal/message.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/message.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/message.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/peripher.c</name> <name>Source/Internal/peripher.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/peripher.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/peripher.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/pulto.c</name> <name>Source/Internal/pulto.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/pulto.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/pulto.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/spise2p.c</name> <name>Source/Internal/spise2p.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/spise2p.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/spise2p.c</locationURI>
</link> </link>
<link> <link>
<name>Source/Internal/tools.c</name> <name>Source/Internal/tools.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/tools.c</locationURI> <locationURI>SRC_ROOT12/Source/Internal/tools.c</locationURI>
</link>
<link>
<name>Source/External/v120/DSP2833x_common/include</name>
<type>2</type>
<locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_common/include</locationURI>
</link>
<link>
<name>Source/External/v120/DSP2833x_headers/include</name>
<type>2</type>
<locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_headers/include</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_ADC_cal.asm</name> <name>Source/External/v120/DSP2833x_common/source/DSP2833x_ADC_cal.asm</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_common/source/DSP2833x_ADC_cal.asm</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_common/source/DSP2833x_ADC_cal.asm</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_Adc.c</name> <name>Source/External/v120/DSP2833x_common/source/DSP2833x_Adc.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_common/source/DSP2833x_Adc.c</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_common/source/DSP2833x_Adc.c</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_CpuTimers.c</name> <name>Source/External/v120/DSP2833x_common/source/DSP2833x_CpuTimers.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_common/source/DSP2833x_CpuTimers.c</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_common/source/DSP2833x_CpuTimers.c</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_PieCtrl.c</name> <name>Source/External/v120/DSP2833x_common/source/DSP2833x_PieCtrl.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_common/source/DSP2833x_PieCtrl.c</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_common/source/DSP2833x_PieCtrl.c</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_SWPrioritizedDefaultIsr.c</name> <name>Source/External/v120/DSP2833x_common/source/DSP2833x_SWPrioritizedDefaultIsr.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_common/source/DSP2833x_SWPrioritizedDefaultIsr.c</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_common/source/DSP2833x_SWPrioritizedDefaultIsr.c</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_SWPrioritizedPieVect.c</name> <name>Source/External/v120/DSP2833x_common/source/DSP2833x_SWPrioritizedPieVect.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_common/source/DSP2833x_SWPrioritizedPieVect.c</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_common/source/DSP2833x_SWPrioritizedPieVect.c</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_SysCtrl.c</name> <name>Source/External/v120/DSP2833x_common/source/DSP2833x_SysCtrl.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_common/source/DSP2833x_SysCtrl.c</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_common/source/DSP2833x_SysCtrl.c</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_Xintf.c</name> <name>Source/External/v120/DSP2833x_common/source/DSP2833x_Xintf.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_common/source/DSP2833x_Xintf.c</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_common/source/DSP2833x_Xintf.c</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_usDelay.asm</name> <name>Source/External/v120/DSP2833x_common/source/DSP2833x_usDelay.asm</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_common/source/DSP2833x_usDelay.asm</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_common/source/DSP2833x_usDelay.asm</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_headers/cmd/DSP2833x_Headers_nonBIOS.cmd</name> <name>Source/External/v120/DSP2833x_headers/cmd/DSP2833x_Headers_nonBIOS.cmd</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_headers/cmd/DSP2833x_Headers_nonBIOS.cmd</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_headers/cmd/DSP2833x_Headers_nonBIOS.cmd</locationURI>
</link> </link>
<link> <link>
<name>Source/External/v120/DSP2833x_headers/source/DSP2833x_GlobalVariableDefs.c</name> <name>Source/External/v120/DSP2833x_headers/source/DSP2833x_GlobalVariableDefs.c</name>
<type>1</type> <type>1</type>
<locationURI>SRC_ROOT1/Source/External/v120/DSP2833x_headers/source/DSP2833x_GlobalVariableDefs.c</locationURI> <locationURI>SRC_ROOT12/Source/External/v120/DSP2833x_headers/source/DSP2833x_GlobalVariableDefs.c</locationURI>
</link> </link>
</linkedResources> </linkedResources>
<variableList> <variableList>
@@ -195,5 +210,9 @@
<name>SRC_ROOT1</name> <name>SRC_ROOT1</name>
<value>$%7BPARENT-1-PROJECT_LOC%7D</value> <value>$%7BPARENT-1-PROJECT_LOC%7D</value>
</variable> </variable>
<variable>
<name>SRC_ROOT12</name>
<value>file:/K:/git_project/28335_periph</value>
</variable>
</variableList> </variableList>
</projectDescription> </projectDescription>

View File

@@ -1,4 +0,0 @@
ccsVersionValidationPolicy=warning
compilerVersionValidationPolicy=flexible
eclipse.preferences.version=1
productVersionsValidationPolicy=flexible

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