- mdview2_status.c: вынести статус-бар/меню/спиннер из ядра - mdview2.c: убрать retry-цикл в alloc_set_storage (fail-fast вместо ложной устойчивости — при нехватке EMM под индекс контент тоже не влезет) - mdview2.h: дополнить экспортами статус-модуля - mdview2_md.c / mdview2_raw.c: зачистка после расщепления - mdview/mdview.c: переименовать scroll_* → md_scroll_* (симметрия) - docs/fast_ram.md, docs/turboc.txt: добавить справочные доки - examples/mdview2/README.MD, READMEBG.MD: обновить описание Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
12 KiB
Fast RAM (Быстрое ОЗУ / «КЭШ-ОЗУ») на Sprinter
Сводка по результатам изучения документации платформы. Источники:
docs/converted/Architecture.txt— официальное «Описание архитектуры» (раздел «Распределение основной памяти»).docs/converted/ARHITECT.txt— ранняя редакция того же документа (про загрузку конфигураций ППЛМ).docs/converted/IvanMak.txt/docs/converted/Parinov.txt/docs/converted/Forum.txtиdocs/part2/forum.txt— форумные ответы Дениса Паринова (Sprinter Team) и руководство Ивана Мака (раздел «7 КЭШ-ОЗУ»).docs/part2/accelerator_doc.txt— ограничение акселератора.docs/samples/sprinterIntLib.asm— практический пример temporary-off / restore.
Терминология. В документации одно и то же ОЗУ называется тремя именами: Fast RAM, Быстрое ОЗУ и «КЭШ-ОЗУ». Это не кэш в формальном смысле (нет автоматического заполнения/вытеснения) — это отдельный массив статической памяти, в котором процессор работает на полной частоте без тактов ожидания. Имя «КЭШ» — историческое, по аналогии с кэшем на КР537РУ10 в Pentagon-128.
1. Что это и зачем
- Объём: 64 КБ статической памяти (SRAM), отдельной от основного DRAM-SIMM (4 МБ) и от видео-ОЗУ (256 КБ).
- Скорость: процессор обращается к Fast RAM на полной тактовой частоте (21 МГц) без wait-state'ов. Основное ОЗУ (DRAM) требует тактов ожидания, поэтому код и данные в Fast RAM исполняются/читаются заметно быстрее.
- Назначение: разместить «горячий» код или данные (внутренние циклы, таблицы, буферы), которые критичны по скорости.
- Системная роль: Fast RAM также используется механизмом
переконфигурирования ППЛМ — именно в неё BIOS грузит данные новой
конфигурации и флаг
ACEX_30K_LOADING(старое имяFLEX_10K_LOADING) перед программным сбросом. Поэтому к Fast RAM нельзя относиться как к «своей» памяти, которая всегда сохраняется (см. §5).
2. Карта физических страниц
Память делится на 16 КБ-блоки с однобайтовым физическим номером:
| Тип памяти | Физические номера страниц |
|---|---|
| Основное ОЗУ | #00..#4F, видео-область #50..#5F, ... |
| ПЗУ (ROM) | #E0..#EF |
| Fast RAM | #F0..#FF |
Хотя диапазон номеров Fast RAM —
#F0..#FF(16 значений), реально используются только биты 1 и 2 номера страницы. То есть адресуются 4 страницы × 16 КБ = 64 КБ:#F0,#F2,#F4,#F6.
3. Как включать Fast RAM
Есть два способа подключить Fast RAM в адресное пространство Z80.
Способ A. Pentagon-style через порт #FB / #7B (в окно 0)
Включается «как кэш в Pentagon»: подключает 16 КБ Fast RAM в окно 0
(#0000..#3FFF) вместо ПЗУ. Переключение — побочный эффект чтения порта
(значение в A после IN — мусор, важен сам факт обращения):
DI
IN A,(#FB) ; включить Fast-RAM — 16 КБ в окно 0 (#0000..#3FFF)
; ... ваш код / работа с Fast RAM ...
IN A,(#7B) ; выключить Fast-RAM (вернуть ПЗУ в окно 0)
EI
IN A,(#FB)— включить.IN A,(#7B)— выключить.
Конфликт портов. Порт
#FB(и#4F) — это также порт COVOX/Blaster-а. Вывод (OUT) в#FBуправляет звуком, а чтение (IN) — переключает Fast RAM. Не путать направления обращения.
Способ B. Как ПЗУ — через PAGE0 (#82) + порт #1FFD
Fast RAM-страница (#F0..#FF) выбирается в PAGE0 и подключается на место ПЗУ
в окно 0 через спец-порт #1FFD:
; выбрать физическую страницу Fast RAM в PAGE0
LD A, #F0 ; номер страницы Fast RAM
OUT (#82), A ; PAGE0 = страница в окно 0
LD A,1 ; 1 → ОЗУ (выбранная страница) в #0000..#3FFF
LD BC,#1FFD
OUT (C),A
; ...
LD A,0 ; 0 → вернуть ПЗУ в #0000..#3FFF
LD BC,#1FFD
OUT (C),A
- Порты PAGE:
PAGE0=#82,PAGE1=#A2,PAGE2=#C2,PAGE3=#E2. Чтение порта PAGE возвращает текущий номер страницы. - Эти адреса портов формально могут отличаться в других конфигурациях ППЛМ —
правильнее запрашивать их у BIOS и сверять (см.
docs/part2/bios_doc.txt, ~строка 1033).
4. Преимущества
- Скорость без wait-state. Главное и единственное предназначение — код и данные исполняются на полной частоте 21 МГц без тактов ожидания, в отличие от основного DRAM.
- Идеально для горячих участков. Внутренние циклы, lookup-таблицы, временные буферы рендера — то, к чему обращаются интенсивно и многократно.
- Отдельный массив. Не отнимает страницы основного 4 МБ ОЗУ и не пересекается с видео-областью.
5. Ограничения и подводные камни ⚠️
Это самая важная часть — Fast RAM небезопасна в обращении и легко даёт «молча не работает».
-
Акселератор НЕ работает с Fast RAM. Акселератор поддерживает пересылку блоков только для основного ОЗУ и видео-ОЗУ. Пересылку ROM и FastRAM он не поддерживает. То есть нельзя использовать accel-Fill/Copy для заполнения или копирования в/из Fast RAM — только обычные
LD-циклы процессора. -
Содержимое не сохраняется между процессами. Fast RAM может быть использована другими программами. При запуске любого процесса через DSS (а также самим механизмом переконфигурирования ППЛМ) содержимое Fast RAM может быть затёрто. Нельзя рассчитывать на персистентность данных между вызовами системы.
-
Перед вызовами DSS и BIOS Fast RAM надо ОТКЛЮЧАТЬ. Системные функции рассчитывают на стандартную карту памяти (ПЗУ в окне 0). Вызывать
RST 10h(ESTEX/DSS) илиRST 8(BIOS) при включённой Fast RAM в окне 0 — нельзя. -
Прерывания. Fast RAM (способ A) подключается в окно 0, перекрывая ПЗУ и системный вектор. Если используются прерывания, программа обязана установить свой обработчик по адресу
#0038. На практике работу с Fast RAM ведут сDI, а на время ожидания кадра/haltFast RAM временно выключают и восстанавливают (см. §6). -
Окно 0 занято под DSS. В нашем C-toolchain'е окно 0 (
#0000..#3FFF) — это ESTEX/DSS система (см.release_docs/ru/platform_reference.md). Подключение Fast RAM в окно 0 вытесняет именно её, что усиливает требование п.3. -
Конфликт
#FBс COVOX. См. §3, способ A.
6. Канонический паттерн temporary-off / restore
Из реального резидента (docs/samples/sprinterIntLib.asm): перед ei: halt
(ожидание кадрового прерывания) Fast RAM временно выключается, после —
восстанавливается прежнее состояние:
_intWaitVsyncSys
call memCacheOffTemporary ; временно выключаем Fast RAM
ei
halt
jp memCacheRestoryState ; восстанавливаем прежнее состояние подключения
Идея паттерна: библиотека хранит флаг «было ли Fast RAM включено», умеет
безопасно его снять на время системных операций (прерывания, DSS/BIOS) и вернуть
обратно. При интеграции в C-toolchain эту логику следует обернуть так же:
сохранять состояние, отключать вокруг любого RST/halt, восстанавливать.
7. Выводы для нашего C-toolchain (SDCC + target-слой)
- Из коробки сейчас не используется. В
runtime/,lib/,libc/обращений к Fast RAM нет (порт#FB/#7Bнигде не задействован под эту задачу). - Где могло бы пригодиться: разместить «горячую» функцию или таблицу в Fast RAM для ускорения. Но 64 КБ перекрывают окно 0, конфликтуют с DSS и не переживают системные вызовы — это узкоспециализированный, ручной режим, не кандидат на общий механизм линковки.
- Реалистичный сценарий: короткий самодостаточный inner-loop без вызовов
системы, с
DI, со своим вектором#0038, скопированный в Fast RAM обычнымLD-циклом (не акселератором), исполняемый из окна 0, с гарантированным восстановлением карты памяти перед любымRST. - Несовместимость с акселератором означает, что для графики/блочных операций Fast RAM бесполезна — там выигрывает accel по основному/видео-ОЗУ.
Если будем добавлять поддержку — делать это отдельным opt-in механизмом (по аналогии с banked-режимами), с обязательной обёрткой off/restore вокруг всех точек входа в систему.