9.9 KiB
Работа с parallel NAND через GAS
Архитектура
Внешняя NAND значительно больше общего адресного пространства GAS. Например,
MT29F1G08ABADA содержит 128 МиБ main area, а GAS имеет только 65536
16-битных регистров. Поэтому NAND представлена не линейным диапазоном, а
банковым окном одной физической страницы.
SETGUI
│ GUI protocol v1: READ_REGISTERS / WRITE_REGISTERS
▼
карта GAS 0x0000..0xFFFF
│ 0xE000: управление, 0xE100: main, 0xE500: OOB
▼
parallel_nand_gas
▼
общее ядро parallel_nand
├─ TMS320F2812: XINTF
├─ STM32F407VE: FSMC
└─ STM32G474CE: GPIO
GUI работает одинаково со всеми МК. Тип процессора влияет только на выбранный
файл из ports/.
Встроенный проект должен направлять весь диапазон 0xE000..0xE51F в
parallel_nand_gas_read() и parallel_nand_gas_write(). Их аргументы имеют
тип unsigned int: на C28x это нативное 16-битное слово, а на ARM функции
явно оставляют только младшие 16 бит. Так карта и wire-формат совпадают без
предположения, что C char всегда восьмибитный.
Для STM32, использующего карту pcan_gas, готов адаптер:
#include "parallel_nand_pcan_gas.h"
static pcan_gas_region_t nand_region;
parallel_nand_pcan_gas_region_init(&nand_region, &nand_gas);
Для TMS320F2812 переносимый обработчик вызывается прямо из существующего GAS диспетчера:
if (address >= nand_gas.base &&
address < nand_gas.base + PNAND_GAS_REGION_REGS) {
return parallel_nand_gas_read(&nand_gas, address, value);
}
Если тип результата диспетчера отличается, статусы PNAND_GAS_OK,
PNAND_GAS_NO_REG, PNAND_GAS_READ_ONLY и PNAND_GAS_REJECTED
преобразуются в его локальные статусы так же, как это сделано в
parallel_nand_pcan_gas.c.
Транспорт до GUI
Карта GAS не привязана к физическому каналу. Рекомендуемый путь для полного
дампа — используемые SETGUI сообщения WRITE_REGISTERS (0x0A) и
READ_REGISTERS (0x09): они позволяют передавать крупные блоки поверх USB,
UART, RS-485 или Ethernet. Адаптер pcan_gas нужен, когда теми же регистрами
обмениваются по classic CAN; там один кадр несёт только четыре регистра, и
полный 128-MiB дамп будет значительно медленнее.
Устройство не должно собирать весь дамп в RAM. Буферизуется только одна
страница. Из-за переносимости на C28x каждый octet хранится в unsigned short,
поэтому статические буферы GAS занимают примерно 4,2 KiB RAM и на TMS, и на
ARM.
Карта GAS
Базовый адрес по умолчанию — 0xE000. Его можно изменить при вызове
parallel_nand_gas_init(); все смещения ниже останутся прежними.
| Адрес | Доступ | Название | Значение |
|---|---|---|---|
E000 |
R | SIGNATURE |
0x4E44 (ND) |
E001 |
R | VERSION |
версия окна, сейчас 1 |
E002 |
R | STATUS |
состояние операции |
E003 |
R | ERROR |
код PNAND_*, 0 = нет ошибки |
E004 |
W | COMMAND |
команда окна |
E005 |
R/W | PAGE_LO |
младшие 16 бит физической страницы |
E006 |
R/W | PAGE_HI |
старшие 16 бит физической страницы |
E007 |
R | PAGE_MAIN |
main bytes, для MT29 = 2048 |
E008 |
R | PAGE_OOB |
OOB bytes, для MT29 = 64 |
E009 |
R | PAGES_PER_BLOCK |
для MT29 = 64 |
E00A |
R | BLOCKS |
для MT29 = 1024 |
E00B |
R | MANUFACTURER_ID |
ожидается 0x2C |
E00C |
R | DEVICE_ID |
ожидается 0xF1 |
E00D |
R | BAD_BLOCK |
1 для физически плохого блока |
E00E |
R | GENERATION_LO |
счётчик загруженных страниц, low |
E00F |
R | GENERATION_HI |
счётчик загруженных страниц, high |
E100..E4FF |
R | PAGE_DATA |
1024 регистра main, два байта LE |
E500..E51F |
R | PAGE_OOB |
32 регистра OOB, два байта LE |
Между управляющими регистрами и окнами данных есть зарезервированные адреса. Чтение блока через них не выполняется: каждый запрос должен начинаться внутри существующего участка.
STATUS
| Бит | Маска | Смысл |
|---|---|---|
| 0 | 0x0001 |
READY |
| 1 | 0x0002 |
BUSY |
| 2 | 0x0004 |
PAGE_VALID |
| 3 | 0x0008 |
BAD_BLOCK |
| 15 | 0x8000 |
ERROR, подробность в E003 |
GUI читает окно данных только при READY=1, PAGE_VALID=1, ERROR=0.
COMMAND
| Значение | Команда | Результат |
|---|---|---|
| 1 | RESET |
сброс NAND и ожидание Ready |
| 2 | READ_ID |
обновляет E00B/E00C |
| 3 | READ_PAGE |
загружает main/OOB выбранной страницы |
Запись номера страницы и запуск — две отдельные операции. Сначала GUI пишет
PAGE_LO/PAGE_HI, затем записывает READ_PAGE в COMMAND. Нельзя отправлять
один блок, начинающийся с COMMAND: команда выполнилась бы до обновления номера
страницы.
Последовательность полного дампа
- Прочитать
E000..E00F, проверить подпись, версию и геометрию. - Выполнить
READ_ID; для микросхемы с фотографии проверить2C F1. - Рассчитать
page_count = PAGES_PER_BLOCK * BLOCKS. - Для каждой физической страницы от 0 до
page_count - 1:- записать номер страницы в
E005/E006; - записать
3вE004; - опрашивать
E002, пока не установленREADY; - проверить
ERROR,BAD_BLOCKи изменениеGENERATION; - прочитать
E100..E4FF; - прочитать
E500..E51F; - сразу дописать данные и метаданные в файлы.
- записать номер страницы в
- Не пропускать bad-блоки: иначе файл потеряет соответствие физическим страницам микросхемы.
GUI protocol v1 допускает payload до 512 байт. Ответ READ_REGISTERS содержит
четырёхбайтовый заголовок диапазона, поэтому за один запрос следует читать не
более 254 GAS-регистров. Страница main читается пятью запросами: четыре раза по
254 регистра и последний раз 8 регистров. OOB читается одним запросом на 32
регистра.
Возобновление
GUI хранит номер последней полностью записанной страницы. После разрыва связи он повторно проверяет подпись/ID/геометрию и продолжает со следующей страницы. Страница считается готовой только после записи main, OOB и записи её статуса в метаданные.
Рекомендуемые выходные файлы:
dump.bin— 2048 байт main каждой физической страницы;dump.oob— 64 байта OOB каждой физической страницы;dump.json— ID, геометрия, bad-блоки, ошибки и последняя готовая страница.
Для MT29F1G08ABADA размеры завершённого дампа: dump.bin = 134217728 байт,
dump.oob = 4194304 байта.
ECC
Текущая версия шаблона отдаёт raw main/OOB и не заявляет исправление ошибок.
Статус bad-блока определяется по первому байту OOB первых двух страниц блока.
Перед использованием дампа как рабочего образа нужно добавить ECC-политику для
точного чипа и формата OOB. Само окно GAS при этом менять не требуется: можно
добавить новые флаги состояния в свободные биты STATUS.
PROGRAM/ERASE
Запись и стирание не включены намеренно. Они требуют отдельного разрешения,
проверки ECC, защиты загрузочных блоков и двухфазного подтверждения через GAS.
До добавления этих функций WP# удерживается активным аппаратным портом.