118 lines
6.0 KiB
Markdown
118 lines
6.0 KiB
Markdown
# parallel-nand
|
||
|
||
Переносимый C99-драйвер асинхронной parallel NAND x8 и окно управления через
|
||
общее адресное пространство GAS. Есть профили Micron `MT29F1G08ABADA` и
|
||
Hynix `HY27UF084G2M` (512 MiB, 2048+64 байта, 64 страницы в блоке,
|
||
4096 блоков, ID `AD DC 80 95`).
|
||
|
||
Подготовлены аппаратные порты:
|
||
|
||
- `TMS320F2812` — XINTF Zone 6;
|
||
- `STM32F407VET6` — аппаратный FSMC NAND Bank 2;
|
||
- `STM32F103RCT6` — GPIO bit-bang, так как в LQFP64 FSMC недоступен;
|
||
- `STM32F103ZET6` — аппаратный FSMC NAND Bank 3;
|
||
- `STM32G474CEU6` — GPIO bit-bang для корпуса UFQFPN-48.
|
||
|
||
Ядро не зависит от HAL и транспорта GUI. STM32 HAL используется только в
|
||
конкретных портах. `parallel_nand_gas` реализует переносимую 16-битную карту
|
||
GAS и компилируется в том числе TI C28x, где `char` имеет 16 бит.
|
||
|
||
## Подключение
|
||
|
||
В проект добавить:
|
||
|
||
```text
|
||
c/parallel-nand/src/parallel_nand.c
|
||
c/parallel-nand/src/parallel_nand_gas.c
|
||
```
|
||
|
||
Пути заголовков:
|
||
|
||
```text
|
||
c/parallel-nand/include
|
||
c/parallel-nand/ports/<нужный-порт>
|
||
```
|
||
|
||
И один аппаратный порт, например:
|
||
|
||
```text
|
||
c/parallel-nand/ports/stm32g474ce/parallel_nand_port_stm32g474ce.c
|
||
```
|
||
|
||
Минимальная инициализация:
|
||
|
||
```c
|
||
static parallel_nand_t nand;
|
||
static parallel_nand_gas_t nand_gas;
|
||
|
||
void memory_init(void)
|
||
{
|
||
int rc = parallel_nand_init(&nand,
|
||
parallel_nand_port_stm32g474ce(),
|
||
¶llel_nand_mt29f1g08_geometry);
|
||
if (rc != PNAND_OK) {
|
||
/* Оставить диагностику доступной GUI и сообщить ошибку платы. */
|
||
}
|
||
|
||
parallel_nand_gas_init(&nand_gas, &nand, PNAND_GAS_DEFAULT_BASE);
|
||
}
|
||
```
|
||
|
||
Для Hynix на STM32F103ZET6 используйте
|
||
`parallel_nand_port_stm32f103ze()` и
|
||
`parallel_nand_hy27uf084g2m_geometry`; распиновка и ограничения приведены в
|
||
[`ports/stm32f103ze/README.md`](ports/stm32f103ze/README.md). Порт RCT6
|
||
с GPIO bit-bang сохранён как отдельный вариант для корпуса LQFP64.
|
||
|
||
Диспетчер общего адресного пространства вызывает
|
||
`parallel_nand_gas_read()`/`parallel_nand_gas_write()` для адресов
|
||
`0xE000..0xE51F`. Для STM32 с `c/set-protocol/pcan_gas` дополнительно включить
|
||
`src/parallel_nand_pcan_gas.c`, создать `pcan_gas_region_t` и вызвать
|
||
`parallel_nand_pcan_gas_region_init()`. Этот адаптер намеренно не нужен TMS.
|
||
Для полного дампа предпочтительны пакетные `READ_REGISTERS/WRITE_REGISTERS`,
|
||
а classic CAN GAS оставлен для совместимости и коротких диагностических чтений.
|
||
|
||
Доступ GUI и алгоритм полного дампа описаны в
|
||
[docs/MEMORY_GAS.md](docs/MEMORY_GAS.md). Электрические соединения — в README
|
||
соответствующего порта и [docs/EMPTY_BOARD_PINOUT.md](docs/EMPTY_BOARD_PINOUT.md).
|
||
|
||
## PROGRAM и ERASE
|
||
|
||
- `parallel_nand_program_page()` записывает полную main-область и, при
|
||
необходимости, полную OOB-область страницы.
|
||
- `parallel_nand_erase_block()` стирает один физический блок.
|
||
- Перед изменением ядро проверяет заводской bad-block marker, на время операции
|
||
снимает `WP#`, ждёт `R/B#`, проверяет fail-бит статуса и снова включает
|
||
защиту при любом результате.
|
||
- Порт обязан объявить `write_supported = 1`; иначе возвращается
|
||
`PNAND_ERROR_WRITE_PROTECTED`. Это защищает платы, где `WP#` постоянно
|
||
соединён с GND.
|
||
- Через GAS разрушительные команды требуют записи `0xA55A` в `CONFIRM`
|
||
непосредственно перед `PROGRAM_PAGE` или `ERASE_BLOCK`.
|
||
|
||
NAND можно программировать только из `1` в `0`; для повторной записи сначала
|
||
стирается весь блок. Не стирайте заводские bad-блоки и не используйте raw-запись
|
||
как файловую систему без ECC, wear leveling и защиты загрузочных блоков.
|
||
|
||
## Текущие границы
|
||
|
||
- Реализованы чтение, программирование страницы, стирание блока, RESET,
|
||
READ ID, STATUS и проверка bad-block marker.
|
||
- ECC пока не исправляет данные. GUI получает физические main/OOB и должен
|
||
помечать дамп как raw.
|
||
- В полном дампе bad-блоки не пропускаются: сохраняется физический порядок.
|
||
- Для другой NAND нужно передать другую `parallel_nand_geometry_t` и проверить
|
||
команды/маркер по её datasheet.
|
||
|
||
## Проверка первого запуска
|
||
|
||
1. Запустить `parallel_nand_init()`.
|
||
2. Через GAS проверить `0xE000 = 0x4E44`.
|
||
3. Записать `2` в `0xE004` (`READ_ID`).
|
||
4. Проверить `0xE00B = 0x002C`, `0xE00C = 0x00F1`.
|
||
5. Записать номер страницы в `0xE005/0xE006`, затем `3` в `0xE004`.
|
||
6. Дождаться `READY | PAGE_VALID` в `0xE002`.
|
||
7. Прочитать main из `0xE100..0xE4FF`, OOB из `0xE500..0xE51F`.
|
||
8. PROGRAM/ERASE проверять только на заведомо расходном блоке после сохранения
|
||
полного raw-дампа.
|