14 Commits

Author SHA1 Message Date
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
69 changed files with 2131 additions and 1100 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.sbl
/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>
OUTPUT FORMAT: Binary
INPUT FILE NAME: <K:\git_project\28335_periph\Bin\UKSSTMS320F28335.out>
OUTPUT FORMAT: Intel
PHYSICAL MEMORY PARAMETERS
Default data width : 16
@@ -12,22 +12,22 @@ PHYSICAL MEMORY PARAMETERS
BOOT LOADER PARAMETERS
Table Type: SERIAL PORT (SCI 8 bit Mode)
Entry Point: 0x0000b56a
Entry Point: 0x0000b7bc
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
.cinit : dest=0000b717 size=00000262 width=00000002
.text : dest=00008000 size=00003717 width=00000002
.econst : dest=0000c000 size=00000112 width=00000002
.switch : dest=0000c112 size=00000048 width=00000002
CONTENTS: 00000000..00007aa3 BOOT TABLE
.cinit : dest=0000b969 size=0x26b width=00000002
.text : dest=00008000 size=0x3969 width=00000002
.econst : dest=0000c000 size=0x11e 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

Binary file not shown.

View File

@@ -2,7 +2,7 @@
Текущая логика дискретов описана в [SIFU_START_STOP.md](SIFU_START_STOP.md):
CAN-фронты обрабатываются при приёме, импульсы снимаются таймером, STOP
имеет приоритет. Формат записи v2 и интерфейс SetGUI сохранены.
имеет приоритет. Компактный формат записи v4 совпадает с исполнением 167.
## Назначение и работа оператора
@@ -13,8 +13,9 @@ CAN-фронты обрабатываются при приёме, импуль
Общий RS-адрес 16 здесь не рекомендуется: ответ содержит собственный адрес,
и SetGUI проверяет совпадение адресов. CAN-настройки: [PERIPH28335_CAN.md](PERIPH28335_CAN.md).
Перенесён протокол v2 из 167: 40 слов на запись, два банка по 800 записей.
Существующий SetGUI понимает эту прошивку без изменений программы.
Используется формат v4 из 167: 12 слов на запись вместо прежних 40;
ёмкость исполнения 166 сохранена — два банка по 800 записей.
Для чтения нужен SetGUI с поддержкой компактного формата v4, как для 167.
Кнопки записи управляют регистратором; команду запуска УМП подаёт контроллер.
1. **Начать запись** включает только регистратор, не пуск УМП.
@@ -45,7 +46,8 @@ EEPROM не используется: под отключением в этой
## Память и точность
Использована существующая секция `.logg` по адресу 0x200000: 64000
16-битных слов. Два банка по 800 записей × 40 слов занимают её целиком.
16-битных слов. Два банка по 800 записей × 12 слов используют 19200 слов;
размер выделенной секции сохранён. Одна запись занимает 24 байта вместо 80.
Текущий банк кольцевой. При триггере сохраняются последние до 399 записей,
добавляется событие отключения, оставшаяся половина банка отведена
постинтервалу. При 20 мс это до примерно 8 секунд до отключения и 1 секунды
@@ -61,7 +63,7 @@ EEPROM не используется: под отключением в этой
одинаковую отметку; порядок сохраняется порядком записей. На перезапуске
регистратора счётчик продолжает прежнюю шкалу, при перезагрузке платы — 0.
Онлайн-опрос возвращает три последних записи каждые 40 мс. Он не гарантирует
Онлайн-опрос возвращает до десяти последних записей каждые 40 мс. Он не гарантирует
передачу каждого события при высоком CAN-трафике, медленном UART или паузах
GUI. Номера записей позволяют убрать дубликаты и явно показать пропуски.
Полный сохранившийся фрагмент следует читать кнопкой архива. Частота 20 мс
@@ -73,7 +75,12 @@ GUI. Номера записей позволяют убрать дублика
EEPROM, выделения памяти или копирования целого банка. Реальную задержку
прерываний и длительность критических секций нужно измерить на F28335.
## Состав записи: 40 слов
## Состав записи v4: 12 слов
Состав и позиции полей совпадают с компактным логгером 167. Убраны сырые
данные АЦП и CAN, ошибки, счётчики, код и калибровки ЦАП, состояние разгона
и прочие дополнительные диагностические поля. Управление нагрузкой 166,
ёмкость банка и секундный постинтервал отключения сохранены.
| Слова | Данные | Единицы/смысл |
|---|---|---|
@@ -81,33 +88,21 @@ EEPROM, выделения памяти или копирования целог
| 2 | Событие | 1 период, 2 CAN RX, 3 изменение I/O, 4 RS-команда, 5 конец постинтервала |
| 2, бит 8 | Триггер отключения | флаг поверх причины события |
| 2, бит 9 | Усечён постинтервал | установлен в конечном снимке |
| 3 | Commands / modbus[0x7F] | все 16 бит, в том числе пуск, сброс, инициализация и калибровка ЦАП |
| 3 | Commands & 0xC0 | только пуск УМП (бит 7) и сброс УМП (бит 6) |
| 4 | Входы OMEGA, Start_1, Res_in | биты 0,1,2, активный уровень приведён к 1 |
| 5 | START_DPTB, STOP_DPTB, RES_OUT_2 | биты 0,1,2, активный уровень приведён к 1 |
| 6 | IMPowse | остаток импульса, мс |
| 7 | WAKEpowse | остаток инициализации, тики DAC_FREQ |
| 8 | modbus[0x7B] | 12-битный код, переданный функцией dSEND в ЦАП |
| 9 | modbus[0x1C] | расчётное задание в 0.1 мА; GUI/CSV переводит в мА |
| 10–13 | sens_data[0..3] | измеренные сигналы, знаковое 16-битное значение в исходном масштабе |
| 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 |
| 6 | modbus[0x1C] | расчётное задание в 0.1 мА; GUI/CSV переводит в мА |
| 7–8 | Фиксированные начальная и конечная уставки 166 | 6 и 16 мА; это не регистры настройки |
| 9 | ЗПТ1: U1 + U2 | ПМ67, регистр 306 / нулевой CAN-индекс 305, В |
| 10 | ЗПТ2: U3 + U4 | ПМ67, регистр 9 / нулевой CAN-индекс 8, В |
| 11 | Резерв | всегда ноль; чётная длина нужна для парной передачи CAN |
**Отправленный код ЦАП не является измеренным током выхода.** В этом проекте
не установлено, какой вход аппаратно измеряет ток ЦАП. При включённом
**Расчётное задание тока не является измеренным током выхода.** При включённом
`cCalibrDac` отправляется `DAC_cal()`, а расчётное задание 0x1C остаётся
результатом алгоритма разгона. Для диагностики это различие сохранено.
В 166 каналы «АЦП 0..3» берутся из `adc_table_lem`, обновляемой в режиме
нагрузки. Таблица `adc_table_tpl` в этом режиме не обновляется и не используется.
результатом алгоритма разгона. Сырой код ЦАП и каналы АЦП в запись v4 не входят.
Напряжения обновляются по подтверждённым маской словам CAN даже при остановленной
записи: первый снимок содержит последние принятые значения. До первого приёма
они равны нулю; отдельного флага свежести в формате v4 нет.
Управляющая формула 166 сохранена: `sinus = 10/16 * count_load + 2/16 * time_dac`.
Регулируемый разгон и ограничители 167 не переносились. Поля границ показывают
@@ -128,9 +123,9 @@ FC03, 0x1000, 16 слов:
| Смещение | Значение |
|---|---|
| 0,1 | 0x554D, версия 2 |
| 0,1 | 0x554D, версия 4 |
| 2,3 | состояние и число записей выбранного источника |
| 4,5 | 40 слов в записи, 800 записей в банке |
| 4,5 | 12 слов в записи, 800 записей в банке |
| 6 | период периодических снимков, мс |
| 7,8 | счётчик времени, младшее/старшее слово |
| 9,10 | Desk (требуется 6 / dsk_LOAD), Mode |
@@ -148,15 +143,17 @@ FC06:
- 0x1002: хронологический индекс первой записи окна 0..799;
- 0x1003: источник окна, 0 — текущий остановленный банк, 1 — архив отключения.
FC03, 0x1010, до 120 слов: окно до трёх записей от установленного индекса.
FC03, 0x1010, до 120 слов: окно до десяти записей от установленного индекса.
Для CAN длина должна быть кратна 12 словам: 12, 24, ..., 120; прежние
блоки v2 по 40 или 80 слов отклоняются как обрывающие компактную запись.
Чтение текущего банка этим окном во время записи не выдаёт изменяющиеся
данные. GUI сначала останавливает его; архив можно читать при работающем
текущем банке. После всех блоков GUI повторно проверяет поколение архива;
при замене во время чтения результат не подменяет предыдущий график.
FC03, 0x1100, ровно 124 слова: онлайн-блок. Слова 0,1 — 32-битный номер
первой записи, 2 — число записей 0..3, 3 — поколение архива, далее до трёх
записей по 40 слов. Неиспользованные слова равны нулю. Окно онлайн не
первой записи, 2 — число записей 0..10, 3 — поколение архива, далее до десяти
записей по 12 слов. Неиспользованные слова равны нулю. Окно онлайн не
зависит от курсора/выбора архива. Разделение 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,
FPU32, O1) прошли. Остались шесть прежних предупреждений в measure.c/peripher.c.
В MAP: RAML0 занято 0x38D1 из 0x4000 слов, .ebss — 0xFA9 из 0x3000,
@@ -176,8 +185,10 @@ FPU32, O1) прошли. Остались шесть прежних предуп
Сборка проверки лежит вне репозитория, штатные файлы Bin не заменены.
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
в PATH); при необходимости передать `--compiler "полный путь к cl.exe"`.
Тест не проверяет физические GPIO, тайминги прерываний и 16-битную ABI TI.
@@ -186,7 +197,7 @@ Host-тест компилирует настоящий log_to_mem.c с подм
начать запись → подать CAN-пуск → подать отключение → через секунду прочитать
архив. Сверить START/STOP с физическими выходами и измерениями, повторить с
разрывом 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**. Проверены протокол,
онлайн/архив, CAN-фрагменты, графики, курсоры и CSV.
Проверка на устройстве не выполнялась.

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* Íàïðàâëåíèÿ GPIO äëÿ àïïàðàòíûõ èñïîëíåíèé. Åäèíèöà îçíà÷àåò
* âûõîä; àêòèâíóþ ïîëÿðíîñòü çàäàþò peripher.h è ñõåìà ïëàòû.
/* Направления GPIO для аппаратных исполнений. Единица означает
* выход; активную полярность задают peripher.h и схема платы.
*/
#define COMM_gpio00_dir 0L
#define COMM_gpio01_dir 0L
@@ -14,7 +14,7 @@
#define COMM_gpio10_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_gpio21_dir 0L // 65 2:9A mode 4
#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_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_gpio49_dir 1L // 89 2:14B select
@@ -57,7 +57,7 @@
#define BKSD_gpio10_dir 0L // 19 2:6C oil
#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_gpio21_dir 0L // 65 2:9A mode 4
#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_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_gpio49_dir 0L // 89 2:14B input 2
@@ -100,7 +100,7 @@
#define BKST_gpio10_dir 0L
#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_gpio21_dir 0L // 65 2:9A mode 4
#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_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_gpio49_dir 0L
@@ -143,7 +143,7 @@
#define PULT_gpio10_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_gpio21_dir 0L // 65 2:9A mode 4
#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_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_gpio49_dir 0L // 89 2:14B button
@@ -186,7 +186,7 @@
#define PLT2_gpio10_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_gpio21_dir 0L // 65 2:9A mode 4
#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_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_gpio49_dir 0L // 89 2:14B button
@@ -229,7 +229,7 @@
#define SHKF_gpio10_dir 0L // 19 2:6C 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_gpio21_dir 0L // 65 2:9A mode 4
#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_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_gpio49_dir 0L // 89 2:14B input
@@ -272,7 +272,7 @@
#define LOAD_gpio10_dir 0L
#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_gpio21_dir 0L // 65 2:9A mode 4
#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_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_gpio49_dir 0L

View File

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

View File

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

View File

@@ -1,48 +1,48 @@
/* Заводские калибровки по версии BALSAM и типу платы. Здесь
* определяются массивы, а не только extern; не дублировать подключение.
/* Заводские калибровки по версии BALSAM и типу платы. Здесь
* определяются массивы, а не только extern; не дублировать подключение.
*/
#if BALSAM == 166 //-------------------------------------------------------------
int def_cal[][8] = {
// Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2
4936, 4877, 4972, 4857, 1960, 1920, 2610, 2570, // Борт 0
4876, 5005, 4876, 4847, 1950, 1965, 2600, 2615, // Борт 1
// Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2
4936, 4877, 4972, 4857, 1960, 1920, 2610, 2570, // Борт 0
4876, 5005, 4876, 4847, 1950, 1965, 2600, 2615, // Борт 1
// УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I
3820, 3790, 3505, 3380, 1718, 673, 854, 14, // Борт 0
3835, 3785, 3522, 3332, 1697, 653, 860, 17, // Борт 1
// УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I
3820, 3790, 3505, 3380, 1718, 673, 854, 14, // Борт 0
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 };
#endif //---------------------------------------------------------------------
#if BALSAM == 165 //-------------------------------------------------------------
int def_cal[][8] = {
// Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2
5130, 4960, 4925, 5070, 1881, 1881, 2506, 2516, // Борт 0
5020, 5040, 4950, 5030, 1871, 1879, 2507, 2514, // Борт 1
// Силовой UA1 UB1 UA2 UB2 300 1 300 2 400 1 400 2
5130, 4960, 4925, 5070, 1881, 1881, 2506, 2516, // Борт 0
5020, 5040, 4950, 5030, 1871, 1879, 2507, 2514, // Борт 1
// УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I
3890, 3865, 5100, 4850, 1730, 675, 854, 14, // Борт 0
3845, 3800, 3250, 3100, 1044, 0, 860, 17, // Борт 1
// УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I
3890, 3865, 5100, 4850, 1730, 675, 854, 14, // Борт 0
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 };
#endif //---------------------------------------------------------------------
#if BALSAM == 164 //-------------------------------------------------------------
int def_cal[][8] = {
// Силовой 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, 1970, 1907, 2584, 2558, // Борт 1
// Силовой 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, 1970, 1907, 2584, 2558, // Борт 1
// УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I
3920, 3905, 3300, 3220, 1015, 0, 854, 14, // Борт 0
3835, 3785, 5100, 4600, 1750, 680, 860, 17, // Борт 1
// УМП UA UC IA IC 20mA O 4mA O 20mA I 4mA I
3920, 3905, 3300, 3220, 1015, 0, 854, 14, // Борт 0
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 };
#endif //---------------------------------------------------------------------
@@ -51,15 +51,15 @@
#if PXXXXX == 1 //-------------------------------------------------------------
int def_cal[][6] = {
// Силовой 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, // Борт 1
// Силовой 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, // Борт 1
// УМП UA UC IA IC 20mA 4mA
0400, 0400, 4800, 4800, 0, 0, 0, 0, // Борт 0
0400, 0400, 4800, 4800, 0, 0, 0, 0, // Борт 1
// УМП UA UC IA IC 20mA 4mA
0400, 0400, 4800, 4800, 0, 0, 0, 0, // Борт 0
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 };
#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
#define _CNTRL_ADR
@@ -8,22 +8,22 @@
extern "C" {
#endif
/** адрес контроллера дла посылки всем АИНам */
/** адрес контроллера дла посылки всем АИНам */
extern int ADDR_FOR_ALL;
/** адрес контроллера дла посылки ответа */
/** адрес контроллера дла посылки ответа */
extern const int ADDR_ANSWER;
/** адреса терминала дла посылки ответа */
/** адреса терминала дла посылки ответа */
extern const int ADDR_TERMINAL;
/* Адрес контроллера */
/* Адрес контроллера */
extern int CNTRL_ADDR;
/* Универсальный адрес контроллера */
/* Универсальный адрес контроллера */
extern const int CNTRL_ADDR_UNIVERSAL;
/** Установка адреса контроллера дла прошивки */
/** Установка адреса контроллера дла прошивки */
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 char byte;

View File

@@ -1,9 +1,11 @@
/* Телеметрия eCAN и фоновая выдача ответов логгера.
* UMP_CAN_service вызывается из main, не из приёмного IRQ.
/* Телеметрия eCAN и фоновая выдача ответов логгера.
* UMP_CAN_service вызывается из main, не из приёмного IRQ.
*/
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[];
/* Неблокирующая передача ответов логгера отдельным CAN mailbox. */
/* Неблокирующая передача ответов логгера отдельным CAN mailbox. */
void UMP_CAN_service(void);

View File

@@ -1,5 +1,5 @@
/* Коэффициенты и изменяемая история фильтра. Каждый независимый
* канал должен иметь отдельный экземпляр FILTERBAT.
/* Коэффициенты и изменяемая история фильтра. Каждый независимый
* канал должен иметь отдельный экземпляр FILTERBAT.
*/
#ifndef _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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 long ump_can_sent_at;
#include "can_telemetry_impl.h" /* Определяет heartbeat, подтверждённый кэш и повтор данных через 1,3 с после объявления состояния штатного TX. */
void InitCan(int Port, int DevNum)
{
struct ECAN_REGS ECanShadow;
@@ -59,6 +61,7 @@ void InitCan(int Port, int DevNum)
long id = 0x80BA0000;
CAN_telemetry_init(); /* Сбрасывает кэш, очередь и секундный heartbeat до разрешения аппаратных прерываний. */
DevNum--;
if(DevNum<0)DevNum=0;
if(DevNum>15)DevNum=15;
@@ -138,8 +141,8 @@ void InitCan(int Port, int DevNum)
ECanMOTORegs->MOTO0 = 550000;
ECanMOTORegs->MOTO1 = 550000;
/* До первой передачи отключает тайм-ауты всех mailbox; по SPRUI07, 13.8.18.3, сброс TOC снимает TOS и MTOF. */
ECanRegs->CANTOC.all = 0;
ECanRegs->CANTOC.all = 1;
ECanRegs->CANTOS.all = 0; // clear all time-out flags
ECanRegs->CANTSC = 0; // clear time-out counter
ECanShadow.CANGIM.all = 0;
@@ -172,49 +175,7 @@ void InitCan(int Port, int DevNum)
/* При занятом MBOX0 возвращается без ожидания ACK в цикле.
* Это отличается от блокирующих UART/EEPROM операций main.
*/
void CAN_send(int Port, int data[], int Addr)
{
unsigned long hiword,loword;
volatile struct ECAN_REGS * ECanRegs;
volatile struct ECAN_MBOXES * ECanMboxes;
ECanRegs = &ECanaRegs;
ECanMboxes = &ECanaMboxes;
/* Не меняет данные mailbox 0, пока передача либо её аппаратная отмена ещё выполняется; бит 0 соответствует штатному TX. */
if ((ECanRegs->CANTRS.all | ECanRegs->CANTRR.all) & 1UL)
return; /* Сохраняет текущий кадр до завершения CANTRS/CANTRR, не ожидая аппаратного ответа в главном цикле. */
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;
/* Отключает старый контроль mailbox 0 перед перезапуском счётчика; остальные mailbox используют собственный контроль. */
ECanRegs->CANTOC.all = 0;
/* Записывает ECanRegs->CANTSC значением 0; E CAN Regs CANTSC. */
ECanRegs->CANTSC = 0; // clear time-out counter
/* Заново разрешает тайм-аут штатного TX с порогом MOTO0, установленным в InitCan, только для следующего кадра. */
ECanRegs->CANTOC.all = 1UL;
EDIS;
ECanRegs->CANTRS.all = 1; // запустить передачу
wait=1;
led1_toggle();
}
/* CAN_send определён общим для этой единицы трансляции блоком can_telemetry_impl.h выше. */
void Handlai(volatile struct ECAN_MBOXES * ECanMboxes)
@@ -305,10 +266,11 @@ interrupt void CANa_reset_err(void)
if (ECanaRegs.CANTOS.all & 1UL)
{ /* Обрабатывает только штатный передатчик; служебный mailbox 2 контролируется отдельно в UMP_CAN_service. */
EALLOW; /* Разрешает изменение управляющего регистра eCAN перед снятием источника прерывания. */
ECanaRegs.CANTOC.all = 0; /* Сброс TOC снимает TOS и MTOF согласно SPRUI07, 13.8.18.3; одной отмены TX недостаточно. */
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 после сброса временного счётчика. */

View File

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

View File

@@ -20,27 +20,6 @@
int digits[16] = {63,6,91,79,102,109,125,7,127,111,64,0,0,0,121,0};
int readr[5] = {0x08,0x0C,0x10,0x00,0x04};
/* Ограничивает настройки таймингов компилятором TI C2000; модель на ПК не использует эти директивы. */
#if defined(__TI_COMPILER_VERSION__)
/* Сохраняет отдельный вызов переключения CLOCK: встраивание при -O3 сокращало удержание DATA после фронта. */
#pragma FUNC_CANNOT_INLINE(DCLK)
/* Возвращает генерацию DCLK как в образе от 06.10.2026: уровень 1 и приоритет скорости 3 сохраняют прежнюю последовательность инструкций GPIO. */
#pragma FUNCTION_OPTIONS(DCLK, "--opt_level=1 --opt_for_speed=3")
/* Сохраняет отдельный вызов переключения DATA, чтобы длительность импульсов не зависела от встраивания в передатчик. */
#pragma FUNC_CANNOT_INLINE(DOUT)
/* Возвращает генерацию DOUT с прежними параметрами -O1 и --opt_for_speed=3; значения взяты из старой конфигурации CCS. */
#pragma FUNCTION_OPTIONS(DOUT, "--opt_level=1 --opt_for_speed=3")
/* Не позволяет встроить разделитель пакетов в цикл передачи и изменить интервалы между переключениями линий. */
#pragma FUNC_CANNOT_INLINE(RESET)
/* Сохраняет прежнюю последовательность вызовов GPIO и задержек разделителя, используя настройки старого образа. */
#pragma FUNCTION_OPTIONS(RESET, "--opt_level=1 --opt_for_speed=3")
/* Сохраняет отдельный вызов передачи бита; протокол использует порядок и интервалы фронтов CLOCK и DATA. */
#pragma FUNC_CANNOT_INLINE(SENDBIT)
/* Закрепляет для передачи бита настройки из 167: -O1 и --opt_for_speed=3 сохраняют интервалы GPIO независимо от общего уровня оптимизации проекта. */
#pragma FUNCTION_OPTIONS(SENDBIT, "--opt_level=1 --opt_for_speed=3")
/* Завершает блок настроек TI, не изменяя формат пакетов и существующие счётчики задержек. */
#endif
void DCLK(int x)
{
if(x) GpioDataRegs.GPASET.bit.GPIO6=1;
@@ -109,7 +88,7 @@ void kanal_Send(int adr, long dat, int dot)
long Word,data,aliq_part,dg[4];
int i,j,bit,byt,addr,sgn=0,punkt=0,aliq_len=0,full_len, isdot=0;
if(adr>1) // Адреса каналов выше 1 передают готовую битовую маску ламп; каналы 0 и 1 требуют преобразования числа в сегменты.
if(adr>1) // Лампочки
{
Word =dat;
}
@@ -160,7 +139,7 @@ void kanal_Send(int adr, long dat, int dot)
for(i=3;i>0;i--)
{
if((dg[i]==0)&&(i!=dot))
dg[i]=0xF; // Индекс 0xF таблицы digits задаёт пустой символ, скрывая ведущий ноль вне позиции десятичной точки.
dg[i]=0xF; // Это значит пусто
else break;
}
@@ -169,7 +148,7 @@ void kanal_Send(int adr, long dat, int dot)
{
if( (dg[i]==0xF)||(i==3))
{
dg[i]=0xA; // Индекс 0xA таблицы digits задаёт знак минуса в свободном разряде отрицательного числа.
dg[i]=0xA; // Это значит минус
break;
} }

View File

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

View File

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

View File

@@ -26,7 +26,7 @@ unsigned int CanPowse=CANPOWSE,CanGO=0;
unsigned int Maska[2][8];
int TPL_CANS=0; // Количество температурных каналов
int TPL_CANS=0; // Количество температурных каналов
int tpl_cans=0;
int cal_addr=0;
@@ -79,7 +79,7 @@ float K_T1,K_T2;
interrupt void cpu_timer1_isr_SENS(void);
/********************************************************************/
/* Расчет модула тока из показаний двух фаз */
/* Расчет модула тока из показаний двух фаз */
/********************************************************************/
float im_calc(float ia,float ib)
{
@@ -360,7 +360,7 @@ void Init_packMask()
switch(Desk)
{
case dsk_EPLT:
Maska[m_FAST][0]|= 0x000F; // Возвращает R0–R3 задатчика в быстром потоке: маска 0x000F выбирает четыре младших регистра, чтобы подтверждение R3 для ПМ67 не ожидало медленного обхода параметров.
Maska[m_FAST][0]|= 0x000F; // Включает R0–R3 в быструю обратную связь VPU для ПМ67; четыре младших бита маски исключают ожидание медленного обхода параметров.
Maska[m_SLOW][6]|= 0x01FC; // Яркость ламп и одиночество
break;

View File

@@ -1,8 +1,8 @@
/* Параметры и обработчики Modbus после проверки CRC. Массив modbus
* содержит обычные адреса 0..127, область 0x1000 обслуживает логгер.
* EEPROM хранит параметры, но не является источником START/STOP:
* при загрузке сохраняется последняя живая команда нагрузки.
* Функции вызываются из main; EEPROM блокирует этот контекст.
/* Параметры и обработчики Modbus после проверки CRC. Массив modbus
* содержит обычные адреса 0..127, область 0x1000 обслуживает логгер.
* EEPROM хранит параметры, но не является источником START/STOP:
* при загрузке сохраняется последняя живая команда нагрузки.
* Функции вызываются из main; EEPROM блокирует этот контекст.
*/
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "package.h"
@@ -21,9 +21,12 @@
#include "ecan.h"
#include "pulto.h"
#include "spise2p.h"
#include "include/balsam167_eeprom_block.h" /* Использует общий с 167 контракт FC03: окно 0x8000..0xBFFF, до 120 слов AT25256B за запрос. */
#include "caliber.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"
int modbus[ANSWER_LEN+1];
@@ -47,7 +50,7 @@ void Default_params()
for(i=0;i<ANSWER_LEN;i++)
{
/* Команда нагрузки не является параметром по умолчанию. */
/* Команда нагрузки не является параметром по умолчанию. */
if (Desk != dsk_LOAD || i != 127) Modbus[i].all = 0;
}
@@ -56,17 +59,17 @@ void Default_params()
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];
}
else
{
Cancount[m_FAST] = 10; // пауза между посылками CAN
Cancount[m_FAST] = 12; // пауза между посылками CAN
Brightness = 8;
}
Cancount[m_SLOW] = 101; // пауза между посылками CAN
Cancount[m_SLOW] = 50; // Задаёт медленную CAN-рассылку раз в 50 базовых интервалов CANPOWSE по 20 мс, то есть примерно раз в секунду; это значение по умолчанию могут заменить параметры EEPROM.
if(Kalibro)
{
@@ -126,9 +129,9 @@ void Default_params()
DAC_20 = Caliber[6];
DAC_04 = Caliber[7];
/* Не врема!
DAC_go = 6; // начало зарада
DAC_stop= 15; // конец зарада
/* Не врема!
DAC_go = 6; // начало зарада
DAC_stop= 15; // конец зарада
*/
}
@@ -139,9 +142,9 @@ void Default_params()
Init_sensors_more();
}
/* CRC и Mode проверяются до применения EEPROM. Слово 127
* нагрузки не копируется даже временно: ISR не должен увидеть
* старый START из EEPROM либо потерять текущую CAN-команду.
/* CRC и Mode проверяются до применения EEPROM. Слово 127
* нагрузки не копируется даже временно: ISR не должен увидеть
* старый START из EEPROM либо потерять текущую CAN-команду.
*/
void Load_params()
{
@@ -153,7 +156,7 @@ void Load_params()
(crc !=0xFFFF) &&
(Mode == param[126]))
{
/* Не восстанавливать START/STOP из EEPROM даже на один тик ISR. */
/* Не восстанавливать START/STOP из EEPROM даже на один тик ISR. */
for(i=0;i<ANSWER_LEN;i++)
if (Desk != dsk_LOAD || i != 127) modbus[i] = param[i];
UMP_reset_parameter_commands();
@@ -169,9 +172,9 @@ void Load_params()
Caliber_time = 0xFFFF;
} } }
/* ISR продолжает менять измерения во время сбора param. CRC
* относится к собранному массиву, а не атомарному снимку всей платы.
* Не вызывать сохранение из критического пути дискретов.
/* ISR продолжает менять измерения во время сбора param. CRC
* относится к собранному массиву, а не атомарному снимку всей платы.
* Не вызывать сохранение из критического пути дискретов.
*/
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;
// получили начальный адрес чтениа
// получили начальный адрес чтениа
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];
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 ||
!((Address_MB < ANSWER_LEN && Length_MB <= ANSWER_LEN-Address_MB) ||
(Address_MB >= UMP_LOG_BASE && Address_MB <= UMP_LOG_BASE+15 &&
Length_MB <= UMP_LOG_BASE+16-Address_MB) ||
(Address_MB >= UMP_LOG_DATA && Address_MB < UMP_LOG_DATA+120 &&
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;
}
/////////////////////////////////////////////////
// Отсылка
/* Посчитали контрольную сумму перед самой посылкой */
// Отсылка
/* Посчитали контрольную сумму перед самой посылкой */
rs_arr->buffer[0] = CNTRL_ADDR;
rs_arr->buffer[1] = CMD_MODBUS_3;
rs_arr->buffer[2] = Length_MB*2;
/* Защищаем целостность одного снимка/блока; передача UART идёт уже
* с разрешёнными прерываниями и не задерживает измерение/управление. */
if (Address_MB >= UMP_LOG_BASE) saved = __disable_interrupts();
/* Защищаем целостность одного снимка/блока; передача UART идёт уже
* с разрешёнными прерываниями и не задерживает измерение/управление. */
if (Address_MB >= UMP_LOG_BASE && Address_MB < FIRMWARE_INFO_ADDRESS) saved = __disable_interrupts(); /* Неизменяемый паспорт не требует блокировки IRQ; целостность прежних снимков логгера сохраняется. */
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+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 = 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->flag_TIMEOUT_to_Send=true;
/* Расширение логгера отвечает точным кадром Modbus без хвостовых
* нулей: они иначе попали бы в начало ответа следующего блока GUI.
* Исторический формат технологических регистров оставлен прежним. */
/* Расширение логгера отвечает точным кадром Modbus без хвостовых
* нулей: они иначе попали бы в начало ответа следующего блока GUI.
* Исторический формат технологических регистров оставлен прежним. */
RS_Send(rs_arr, rs_arr->buffer, Length_MB*2+(Address_MB >= UMP_LOG_BASE ? 5 : 8));
return;
@@ -271,26 +297,27 @@ void ReceiveCommandModbus6(RS_DATA *rs_arr)
unsigned int Address_MB, Data_MB, i;
/////////////////////////////////////////////////
// Отсылка
/* Отправлаем назад то же самое */
// Отсылка
/* Отправлаем назад то же самое */
for (i=0;i<8;i++)
rs_arr->buffer[i] = rs_arr->RS_Header[i];
// получили начальный адрес записи
// получили начальный адрес записи
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];
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 (!ump_log_write(Address_MB, Data_MB)) {
modbus_exception(rs_arr, CMD_MODBUS_6, 3); return;
}
} else if (Address_MB < ANSWER_LEN) {
/* RS и CAN используют одну историю фронтов. Чередование каналов
* не создаёт двух независимых повторных запусков. */
/* RS и CAN используют одну историю фронтов. Чередование каналов
* не создаёт двух независимых повторных запусков. */
if (Address_MB == 127) {
UMP_commands_write(Data_MB);
ump_log_rs();

View File

@@ -51,10 +51,10 @@ void get_Mode()
{
EALLOW;
GpioCtrlRegs.GPAMUX1.all &= 0xFF000000; // Обнуляет двухбитовые поля MUX для GPIO0–11 по карте регистров TMS320F28335, выбирая обычный GPIO и сохраняя назначение GPIO12–15.
GpioCtrlRegs.GPAMUX2.all &= 0xFF00003F; // Выбирает обычный GPIO для выводов 19–27: маска сохраняет поля GPIO16–18 и GPIO28–31 в двухбитовой таблице MUX.
GpioCtrlRegs.GPBMUX1.all &= 0xFFFFFFC0; // Обнуляет младшие шесть битов MUX, переводя GPIO32–34 в режим обычных входов или выходов без изменения остальных выводов банка.
GpioCtrlRegs.GPBMUX2.all &= 0x000FF000; // Сохраняет поля GPIO54–57 и переводит GPIO48–53 и GPIO58–63 в обычный GPIO согласно двухбитовой раскладке GPBMUX2.
GpioCtrlRegs.GPAMUX1.all &= 0xFF000000; // 00—11
GpioCtrlRegs.GPAMUX2.all &= 0xFF00003F; // 19—27
GpioCtrlRegs.GPBMUX1.all &= 0xFFFFFFC0; // 32—34
GpioCtrlRegs.GPBMUX2.all &= 0x000FF000; // 48—53, 58—63
GpioCtrlRegs.GPADIR.bit.GPIO20 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO21 = 0;
@@ -205,15 +205,14 @@ void get_Buttons()
if(Desk==dsk_EPLT)
{
/* Сохраняет TESTLAMP до достижения порога фильтра: 1000 означает число опросов главного цикла, а bTestLamp удерживает прежний режим при кратком провале GPIO26, чтобы рабочие маски не прерывали тест индикации. */
bTestLamp = er_anal(GpioDataRegs.GPADAT.bit.GPIO26, &INcount0, 1000, bTestLamp);
/* Таймер пульта включает местный тест после непрерывного удержания TESTLAMP в течение 2 с; число проходов main не влияет на задержку. */
if(GpioDataRegs.GPADAT.bit.GPIO27) butt +=0x0001;
if(GpioDataRegs.GPADAT.bit.GPIO24) butt +=0x0002;
if(GpioDataRegs.GPBDAT.bit.GPIO53) butt +=0x0004;
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.GPBDAT.bit.GPIO52) butt +=0x0040;
if(GpioDataRegs.GPADAT.bit.GPIO4 ) butt +=0x0080;
@@ -224,7 +223,7 @@ void get_Buttons()
if(GpioDataRegs.GPADAT.bit.GPIO5 ) butt +=0x0800;
if(GpioDataRegs.GPBDAT.bit.GPIO48) butt +=0x1000;
if(GpioDataRegs.GPADAT.bit.GPIO10) butt +=0x2000; // Публикует активный секретный вход GPIO10 в бите 13 слова Inputs; маска 0x2000 задаёт назначенную ему позицию протокола.
if(GpioDataRegs.GPADAT.bit.GPIO10) butt +=0x2000; // Секретный вход
Inputs.all = butt;
}

View File

@@ -43,11 +43,11 @@ interrupt void cpu_timer1_isr_PULT(void)
static int cownt=0,count_bright;
unsigned int light=0, i;
unsigned int Alone = 20*READY_FREQ;
static unsigned int test_lamp_hold_ticks = 0; // Считает длительность непрерывного нажатия GPIO26 в тиках READY_FREQ; насыщение на пороге исключает переполнение при долгом удержании.
EALLOW;
CpuTimer1.InterruptCount++;
/* Оставляет только ранее разрешённые источники по таблице приоритетов TI MINT13 и сбрасывает M_INT13 — бит 12 регистра IER, запрещая повторный Timer1 и перемешивание стробов DATA/CLOCK; исходную маску восстановит IRET. */
IER &= (MINT13 & ~M_INT13);
IER |= MINT13; // Set "global" priority
EINT;
EDIS; // This is needed to disable write to EALLOW protected registers
@@ -61,8 +61,8 @@ interrupt void cpu_timer1_isr_PULT(void)
toggle_ONLINE();
toggle_RES_OUT_1(); // Переключает резервный выход RES_OUT_1 в каждом такте пульта, сохраняя существующую выдачу признака активности обработчика.
toggle_RES_OUT_2(); // Переключает второй резервный выход RES_OUT_2 синхронно с тактом пульта, сохраняя существующее поведение этого режима платы.
toggle_RES_OUT_1(); // Формирует на резервном выходе 1 меандр с частотой READY_FREQ/2 (500 Гц) для контроля работы таймера пульта.
toggle_RES_OUT_2(); // Дублирует переключения таймера на резервном выходе 2 с частотой READY_FREQ/2 (500 Гц) для контроля активности пульта.
if(++Lonely > Alone) Lonely = Alone;
@@ -75,6 +75,14 @@ interrupt void cpu_timer1_isr_PULT(void)
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)
{
what_is();

View File

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

View File

@@ -1,7 +1,7 @@
/* Внешняя память и программные задержки. init_zone7 готовит XINTF
* до первого обращения к .logg; времена шины зависят от частоты DSP
* и аппаратной памяти. pause_us занимает CPU циклом и используется
* при инициализации. Длительность СИФУ должна задаваться таймером.
/* Внешняя память и программные задержки. init_zone7 готовит XINTF
* до первого обращения к .logg; времена шины зависят от частоты DSP
* и аппаратной памяти. pause_us занимает CPU циклом и используется
* при инициализации. Длительность СИФУ должна задаваться таймером.
*/
#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"?>
<projectDescription>
<name>Balsam_166</name>
<name>28335_periph</name>
<comment></comment>
<projects>
</projects>
@@ -28,162 +28,177 @@
<link>
<name>F28335.cmd</name>
<type>1</type>
<locationURI>SRC_ROOT1/F28335.cmd</locationURI>
<locationURI>SRC_ROOT12/F28335.cmd</locationURI>
</link>
<link>
<name>UKSSTMS320F28335.pjt</name>
<type>1</type>
<locationURI>SRC_ROOT1/UKSSTMS320F28335.pjt</locationURI>
<locationURI>SRC_ROOT12/UKSSTMS320F28335.pjt</locationURI>
</link>
<link>
<name>Debug/UKSSTMS320F28335.out</name>
<type>1</type>
<locationURI>SRC_ROOT/Bin/UKSSTMS320F28335.out</locationURI>
<locationURI>SRC_ROOT12/Bin/UKSSTMS320F28335.out</locationURI>
</link>
<link>
<name>Libraries/rts2800_fpu32.lib</name>
<type>1</type>
<locationURI>SRC_ROOT1/Libraries/rts2800_fpu32.lib</locationURI>
<locationURI>SRC_ROOT12/Libraries/rts2800_fpu32.lib</locationURI>
</link>
<link>
<name>Source/Internal/ADC.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/ADC.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/ADC.c</locationURI>
</link>
<link>
<name>Source/Internal/DAC.c</name>
<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>
<name>Source/Internal/RS485.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/RS485.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/RS485.c</locationURI>
</link>
<link>
<name>Source/Internal/bios.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/bios.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/bios.c</locationURI>
</link>
<link>
<name>Source/Internal/cntrl_adr.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/cntrl_adr.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/cntrl_adr.c</locationURI>
</link>
<link>
<name>Source/Internal/crc16.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/crc16.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/crc16.c</locationURI>
</link>
<link>
<name>Source/Internal/ecan.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/ecan.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/ecan.c</locationURI>
</link>
<link>
<name>Source/Internal/filter_bat2.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/filter_bat2.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/filter_bat2.c</locationURI>
</link>
<link>
<name>Source/Internal/kanal.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/kanal.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/kanal.c</locationURI>
</link>
<link>
<name>Source/Internal/log_to_mem.c</name>
<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>
<name>Source/Internal/main.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/main.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/main.c</locationURI>
</link>
<link>
<name>Source/Internal/measure.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/measure.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/measure.c</locationURI>
</link>
<link>
<name>Source/Internal/message.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/message.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/message.c</locationURI>
</link>
<link>
<name>Source/Internal/peripher.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/peripher.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/peripher.c</locationURI>
</link>
<link>
<name>Source/Internal/pulto.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/pulto.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/pulto.c</locationURI>
</link>
<link>
<name>Source/Internal/spise2p.c</name>
<type>1</type>
<locationURI>SRC_ROOT1/Source/Internal/spise2p.c</locationURI>
<locationURI>SRC_ROOT12/Source/Internal/spise2p.c</locationURI>
</link>
<link>
<name>Source/Internal/tools.c</name>
<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>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_ADC_cal.asm</name>
<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>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_Adc.c</name>
<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>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_CpuTimers.c</name>
<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>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_PieCtrl.c</name>
<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>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_SWPrioritizedDefaultIsr.c</name>
<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>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_SWPrioritizedPieVect.c</name>
<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>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_SysCtrl.c</name>
<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>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_Xintf.c</name>
<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>
<name>Source/External/v120/DSP2833x_common/source/DSP2833x_usDelay.asm</name>
<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>
<name>Source/External/v120/DSP2833x_headers/cmd/DSP2833x_Headers_nonBIOS.cmd</name>
<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>
<name>Source/External/v120/DSP2833x_headers/source/DSP2833x_GlobalVariableDefs.c</name>
<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>
</linkedResources>
<variableList>
@@ -195,5 +210,9 @@
<name>SRC_ROOT1</name>
<value>$%7BPARENT-1-PROJECT_LOC%7D</value>
</variable>
<variable>
<name>SRC_ROOT12</name>
<value>file:/K:/git_project/28335_periph</value>
</variable>
</variableList>
</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