Добавить переносимый драйвер parallel NAND
This commit is contained in:
81
c/parallel-nand/docs/EMPTY_BOARD_PINOUT.md
Normal file
81
c/parallel-nand/docs/EMPTY_BOARD_PINOUT.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Подключение parallel NAND на пустой плате
|
||||
|
||||
Документ рассчитан на асинхронную NAND x8 `MT29F1G08ABADA` 3,3 В в корпусе
|
||||
TSOP-48 (суффикс `WP`). На второй фотографии NAND — длинная микросхема справа
|
||||
с маркировкой `29F1G08ABADA`. Микросхема Micron `D9MDK` сверху — DDR2 SDRAM,
|
||||
не NAND. На первой фотографии `AM29LV800BT` — parallel NOR, а не NAND.
|
||||
|
||||
Уточнение по ёмкости с фотографий:
|
||||
|
||||
- `K6R4008V1D` — SRAM 4 Mbit (512 KiB), не Flash;
|
||||
- `AM29LV800BT` — parallel NOR 8 Mbit (1 MiB);
|
||||
- `MT29F1G08ABADA` — parallel NAND 1 Gbit, то есть 128 MiB main area.
|
||||
|
||||
Поэтому текущий NAND-профиль рассчитан на 1-Gbit чип со второй платы. Для
|
||||
другой плотности меняется `parallel_nand_geometry_t`; GAS и GUI-команды
|
||||
остаются теми же.
|
||||
|
||||
Не переносите номера выводов TSOP-48 на вариант `H4` VFBGA-63. Для BGA нужно
|
||||
использовать ball map конкретного полного part number.
|
||||
|
||||
## TSOP-48, x8
|
||||
|
||||
| NAND | Вывод | Назначение |
|
||||
|---|---:|---|
|
||||
| `R/B#` | 7 | open-drain Ready/Busy, подтяжка 4,7–10 кОм к 3,3 В |
|
||||
| `RE#` | 8 | строб чтения от МК |
|
||||
| `CE#` | 9 | выбор кристалла от МК |
|
||||
| `VCC` | 12, 37 | питание 3,3 В |
|
||||
| `VSS` | 13, 36 | земля |
|
||||
| `CLE` | 16 | фиксация команды |
|
||||
| `ALE` | 17 | фиксация адреса |
|
||||
| `WE#` | 18 | строб команды/адреса от МК |
|
||||
| `WP#` | 19 | для read-only 10 кОм на GND; для записи — GPIO и pull-down |
|
||||
| `I/O0` | 29 | двунаправленная шина, бит 0 |
|
||||
| `I/O1` | 30 | двунаправленная шина, бит 1 |
|
||||
| `I/O2` | 31 | двунаправленная шина, бит 2 |
|
||||
| `I/O3` | 32 | двунаправленная шина, бит 3 |
|
||||
| `I/O4` | 41 | двунаправленная шина, бит 4 |
|
||||
| `I/O5` | 42 | двунаправленная шина, бит 5 |
|
||||
| `I/O6` | 43 | двунаправленная шина, бит 6 |
|
||||
| `I/O7` | 44 | двунаправленная шина, бит 7 |
|
||||
| `VCC1` | 34, 39 | соединить с 3,3 В для совместимости корпуса/ONFI |
|
||||
| `VSS1` | 25, 48 | соединить с GND для совместимости корпуса/ONFI |
|
||||
| `DNU` | 38, 47 | оставить неподключёнными |
|
||||
| `NC` | остальные | не подключать |
|
||||
|
||||
У каждого VCC/VCC1 поставить 100 нФ на ближайший VSS/VSS1; рядом с NAND —
|
||||
общий 1–4,7 мкФ. Сигналы не должны превышать питание NAND. Для трасс длиннее
|
||||
нескольких сантиметров предусмотреть последовательные резисторы 22–47 Ом у
|
||||
источника на `WE#`, `RE#`, `CLE`, `ALE` и при необходимости на данных.
|
||||
|
||||
## Соединение с МК
|
||||
|
||||
| NAND | TMS320F2812 | STM32F407VET6 | STM32G474CEU6 |
|
||||
|---|---|---|---|
|
||||
| `I/O0..7` | `XD0..XD7` | `PD14,PD15,PD0,PD1,PE7..PE10` | `PB0..PB7` |
|
||||
| `CLE` | `XA0` | `PD11/FSMC_A16` | `PA0` |
|
||||
| `ALE` | `XA1` | `PD12/FSMC_A17` | `PA1` |
|
||||
| `WE#` | `XWE` | `PD5/FSMC_NWE` | `PA2` |
|
||||
| `RE#` | `XRD` | `PD4/FSMC_NOE` | `PA3` |
|
||||
| `CE#` | `XZCS6AND7` | `PD7/FSMC_NE2` | `PA4` |
|
||||
| `WP#` | GND через 10 кОм | GND через 10 кОм | `PA5` и pull-down 10 кОм |
|
||||
| `R/B#` | `GPIOE0` | `PD6/FSMC_NWAIT` | `PA6` |
|
||||
|
||||
Подробные номера выводов корпуса МК и ограничения находятся в README каждого
|
||||
каталога `ports/`. Перед изготовлением платы нужно сверить выбранный корпус и
|
||||
полный part number NAND с актуальным datasheet.
|
||||
|
||||
## Первый запуск
|
||||
|
||||
1. Не устанавливать NAND и проверить 3,3 В, отсутствие КЗ и уровни `CE#/WE#/RE#`.
|
||||
2. Установить NAND, оставить `WP#` в нуле и выполнить RESET `FFh`.
|
||||
3. Прочитать ID `90h`: ожидаемые первые байты для профиля — `2C F1`.
|
||||
4. Считать одну страницу два раза и сравнить main/OOB побайтно.
|
||||
5. Только после устойчивого чтения запускать полный дамп через GAS.
|
||||
|
||||
## Источники для проверки footprint
|
||||
|
||||
- [Micron: каталог SLC NAND](https://www.micron.com/products/storage/nand-flash/slc-nand/part-catalog)
|
||||
- [MT29F1G08ABADA: signal assignments и геометрия](https://helpdesk.trx.pl/pliki/SERWER/Micron-MT29F1G08ABADAWP-IT%20D-datasheet.pdf)
|
||||
- [Micron FBGA part decoder](https://in.micron.com/sales-support/design-tools/fbga-parts-decoder)
|
||||
177
c/parallel-nand/docs/MEMORY_GAS.md
Normal file
177
c/parallel-nand/docs/MEMORY_GAS.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# Работа с parallel NAND через GAS
|
||||
|
||||
## Архитектура
|
||||
|
||||
Внешняя NAND значительно больше общего адресного пространства GAS. Например,
|
||||
`MT29F1G08ABADA` содержит 128 МиБ main area, а GAS имеет только 65536
|
||||
16-битных регистров. Поэтому NAND представлена не линейным диапазоном, а
|
||||
банковым окном одной физической страницы.
|
||||
|
||||
```text
|
||||
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`, готов адаптер:
|
||||
|
||||
```c
|
||||
#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
|
||||
диспетчера:
|
||||
|
||||
```c
|
||||
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`: команда выполнилась бы до обновления номера
|
||||
страницы.
|
||||
|
||||
## Последовательность полного дампа
|
||||
|
||||
1. Прочитать `E000..E00F`, проверить подпись, версию и геометрию.
|
||||
2. Выполнить `READ_ID`; для микросхемы с фотографии проверить `2C F1`.
|
||||
3. Рассчитать `page_count = PAGES_PER_BLOCK * BLOCKS`.
|
||||
4. Для каждой физической страницы от 0 до `page_count - 1`:
|
||||
- записать номер страницы в `E005/E006`;
|
||||
- записать `3` в `E004`;
|
||||
- опрашивать `E002`, пока не установлен `READY`;
|
||||
- проверить `ERROR`, `BAD_BLOCK` и изменение `GENERATION`;
|
||||
- прочитать `E100..E4FF`;
|
||||
- прочитать `E500..E51F`;
|
||||
- сразу дописать данные и метаданные в файлы.
|
||||
5. Не пропускать 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#` удерживается активным аппаратным портом.
|
||||
Reference in New Issue
Block a user