# Глобальное время Программные часы с тактом 1 мс, синхронизацией даты и времени через ProtoCAN и атомарным получением метки для логгера. Ядро C99 не требует аппаратного RTC, операционной системы или динамической памяти. Порт TMS320F28335 включает eCAN-A и необязательный CPU Timer2. Все текстовые файлы — UTF-8. ## Обмен при запуске 1. Приложение инициализирует часы до разрешения IRQ и запускает источник 1 мс. 2. После завершения инициализации **всей платы** вызывает `gt_ready()` / `gt_f28335_ready()`. 3. Из main библиотека отправляет `DISCRETE/FLAGS`, `MsgBody=0x3000`, `Route=1`, адрес самой платы, `DLC=1`, `DATA=01`. 4. Верхний уровень распознаёт пакет через `gt_parse_ready()`, берёт свою текущую дату и посылает **один broadcast всем платам**, используя `gt_make_rtc()`. 5. Каждый узел принимает штатный `RTCSETUP`, сравнивает время со своим, сохраняет величину коррекции и немедленно обновляет календарные часы. При отсутствии ответа узел повторяет готовность не чаще раза в секунду. `RTCSETUP` полностью сохраняет действующий формат ProtoCAN. Универсальное сообщение готовности здесь определено как новый профиль `DISCRETE/FLAGS`; ранее такого общего пакета в базовом протоколе не было. Подробный [контракт обмена](../../doc/setcan/protocan/GLOBAL_TIME.md). Код верхнего уровня для автоматической отправки времени подключается в его приложении; библиотека предоставляет кодировщик и распознавание события старта. ## Метка логгера `gt_get()` одним атомарным чтением возвращает: | Поле | Значение | |---|---| | `seconds`, `millisecond` | секунды от 2000-01-01 и доля 0..999 мс | | `synchronized` | 0 до первого корректного RTCSETUP, 1 после | | `uptime_ms` | время работы modulo 2^32, независимое от переводов часов | | `sync_uptime_ms` | момент приёма последнего опорного пакета | | `generation` | номер принятой коррекции | | `correction_ms` | последнее смещение, знаковое 64-битное значение в мс | | `weekday` | фаза недели 0..6, продвигаемая при смене суток | `gt_timestamp_ms()` формирует 64-битную метку от 2000 года. `gt_calendar()` преобразует снимок в календарь и возвращает 0, пока дата неизвестна. Для записей, которые должны различать переводы часов, сохраняйте также `generation`, `synchronized` и/или `uptime_ms`. Календарное время может идти назад после коррекции. Тайм-ауты следует считать по разности `uptime_ms`. Без новых broadcast часы продолжают ход по локальному генератору; возраст синхронизации равен `(uint32_t)(uptime_ms - sync_uptime_ms)`. ```c #include "global_time_f28335.h" /* Подключает общую временную базу F28335. */ gt_stamp stamp; /* Содержит согласованную дату, миллисекунды и качество времени. */ gt_get(gt_f28335_clock(), &stamp); /* Допускается из main и ISR, включая ISR логгера. */ uint64_t time_ms = gt_timestamp_ms(&stamp); /* Перед сохранением календарной метки проверяется stamp.synchronized. */ ``` Это фрагмент для функции потребителя. Формат хранения существующего логгера библиотека не меняет. В частности, старое 32-битное поле `time_ms` в GAS logger и v4 УМП не вмещает календарные миллисекунды: потребителю нужен собственный формат абсолютной метки либо отдельная временная база и номер поколения. ## Подключение TMS320F28335 Добавьте в сборку `src/global_time.c` и `ports/tms320f28335/global_time_f28335.c`. Include-пути: `include`, `ports/tms320f28335`, штатные TI `DSP2833x_headers/include`, `DSP2833x_common/include` и include компилятора. Ресурсы порта: | Ресурс | Назначение | |---|---| | eCAN-A MBOX7 | RX точного RTCSETUP, любой приоритет, IRQ line0 | | eCAN-A MBOX8 | TX готовности, ACK проверяется в main | | CPU Timer2 / INT14 | необязательный собственный такт 1 мс | Mailbox 0..6, скорость CAN, GPIO и глобальные маршруты PIE/CANGIM настраивает приложение. `DBO=0` обязателен; порт отвергает другую раскладку октетов. MBOX7 использует CANOPC: кадр защищён от аппаратной перезаписи до копирования ISR. В программной очереди хранится последний broadcast, поскольку более новый опорный пакет заменяет предыдущий. При запрещённых IRQ, **после** `InitECan` и `InitPieVectTable`: ```c int ok = gt_f28335_init_periph(5U); /* PERIPH5=Type1/ID5, то есть УМП1; номер берётся из конфигурации платы. */ if (ok) ok = gt_f28335_timer2_start(150000000UL); /* Частота CPU задаётся проектом в Гц; пример соответствует 150 МГц. */ ``` `gt_f28335_init()` позволяет передать Type и ID непосредственно. `init_periph()` поддерживает физические PERIPH 0..31: Type1/2 и ID0..15; 5 — УМП1, 6 — УМП2, 8 — задатчик. Порт инициализируется до подключения hooks. Повторный init разрешён только при остановленном собственном Timer2, отсутствующем TX и запрещённых глобальных IRQ. Если Timer2 занят RTOS или приложением, **не вызывайте** `timer2_start()`; в существующем ISR с периодом ровно 1 мс вызывайте `gt_f28335_tick_1ms()`. Используйте один источник такта. Отдельный Timer2 продолжает отсчёт и при медленном main, но длительная блокировка IRQ на несколько миллисекунд приводит к потере тиков: аппаратный флаг прерывания не считает пропущенные периоды. В существующем `ECAN0INTA` ISR перед очисткой общих CAN-флагов и PIEACK: ```c gt_f28335_rx_isr(); /* Копирует только MBOX7 и запоминает uptime при приёме, календарь проверяется позднее. */ ``` Приложение должно разрешить соответствующий CAN IRQ: `CANGIM.I0EN`, PIE group9 `INTx5`, CPU `M_INT9`; оставить свой обработчик остальных mailbox и штатные подтверждения CANGIF/PIEACK. Порт не заменяет общий CAN ISR. Глобальный `EINT` выполняет приложение после полной настройки. После прикладной инициализации и в каждом проходе главного цикла соответственно: ```c gt_f28335_ready(); /* Выполняется один раз после загрузки параметров и запуска прикладных подсистем. */ gt_f28335_service(); /* Выполняется регулярно в main; обработка календаря и CAN не ждёт аппаратного ACK. */ ``` Все атомарные чтения и обновления используют TI `__disable_interrupts()` / `__restore_interrupts()`, сохраняя прежний INTM. Транспорт ждёт подтверждение CANTA асинхронно и не перезаписывает занятый MBOX8. При отсутствии других CAN-узлов передача остаётся аппаратному контроллеру до восстановления шины. CAN ACK не подтверждает обработку пакета мастером; приход корректного RTCSETUP прекращает повторные объявления готовности. ## Точность и календарь Разрешение локальных часов — 1 мс. Действующий RTCSETUP передаёт только целые секунды, поэтому сам формат **не гарантирует синхронизацию плат с точностью 1 мс**. Мастер должен посылать актуальное значение около секундной границы. Арбитраж CAN и задержка до RX ISR остаются погрешностью; задержка после RX ISR до обработки в main компенсируется по монотонному счётчику. Для точности между платами до 1 мс понадобится согласованное расширение проводного протокола. Одна шкала времени выбирается верхним уровнем (рекомендуется UTC); кадр не содержит часовой пояс. Входные годы 2000..2099, дата проверяется по григорианскому календарю. Формат дня недели 0..6 соответствует проверке существующего STM32-порта; профиль обозначает 0 как воскресенье. Для совместимости переданная фаза недели сохраняется без дополнительной проверки соответствия дате. Некоторые старые клиенты отображают неделю как 1..7; перед отправкой им нужен перевод воскресенья 7 → 0. Секундная шкала uint32_t от 2000 года переполнится в феврале 2136 года. Период между захватом RX uptime и `gt_receive()` должен быть меньше 2^32 мс. ## Проверки Из корня templates: ```text python c/global-time/tests/run_tests.py ``` `--cc` задаёт GCC/Clang. Для отдельной TI C28x проверки передайте `--ti-cgt` (каталог компилятора), `--ti-headers` (DSP2833x_headers/include) и при необходимости `--ti-common` (DSP2833x_common/include). Объекты и EXE создаются во временном каталоге. CMake также предоставляет `global_time`, два CTest и опции `GLOBAL_TIME_BUILD_F28335` / `GLOBAL_TIME_BUILD_TESTS`; MCU проект задаёт свои TI include-пути. Проверяются ошибки даты и кадра, високосный февраль, смена года, коррекции в обе стороны, компенсация очереди через переполнение uptime, ранний broadcast, повторы готовности, сохранение IRQ, изоляция eCAN mailbox, аппаратный ACK, значения периода Timer2 и его реальный ISR через назначенный вектор. TI-проверка компилирует исходники с large/COFF ABI и настоящими заголовками проекта 28335_periph. Полная линковка конкретной прошивки и проверка на плате в этот набор не входят.