Сохранить текущие изменения NAND и LED перед объединением веток

This commit is contained in:
2026-09-15 15:57:06 +03:00
parent 20dbc2c721
commit 698632ebf3
35 changed files with 1841 additions and 31 deletions

View File

@@ -30,7 +30,7 @@ TSOP-48 (суффикс `WP`). На второй фотографии NAND —
| `CLE` | 16 | фиксация команды |
| `ALE` | 17 | фиксация адреса |
| `WE#` | 18 | строб команды/адреса от МК |
| `WP#` | 19 | для read-only 10 кОм на GND; для записи — GPIO и pull-down |
| `WP#` | 19 | GPIO МК и pull-down 10 кОм; только для чтения допустим GND через 10 кОм |
| `I/O0` | 29 | двунаправленная шина, бит 0 |
| `I/O1` | 30 | двунаправленная шина, бит 1 |
| `I/O2` | 31 | двунаправленная шина, бит 2 |
@@ -69,10 +69,12 @@ TSOP-48 (суффикс `WP`). На второй фотографии NAND —
## Первый запуск
1. Не устанавливать NAND и проверить 3,3 В, отсутствие КЗ и уровни `CE#/WE#/RE#`.
2. Установить NAND, оставить `WP#` в нуле и выполнить RESET `FFh`.
2. Установить NAND, проверить pull-down и уровень `WP# = 0`, выполнить RESET `FFh`.
3. Прочитать ID `90h`: ожидаемые первые байты для профиля — `2C F1`.
4. Считать одну страницу два раза и сравнить main/OOB побайтно.
5. Только после устойчивого чтения запускать полный дамп через GAS.
6. PROGRAM/ERASE проверять на расходном блоке после сохранения raw-дампа;
убедиться осциллографом, что `WP#` поднимается только на время операции.
## Источники для проверки footprint

View File

@@ -18,6 +18,8 @@ parallel_nand_gas
общее ядро parallel_nand
├─ TMS320F2812: XINTF
├─ STM32F103RC: GPIO
├─ STM32F103ZE: FSMC
├─ STM32F407VE: FSMC
└─ STM32G474CE: GPIO
```
@@ -77,7 +79,7 @@ ARM.
| Адрес | Доступ | Название | Значение |
|---:|:---:|---|---|
| `E000` | R | `SIGNATURE` | `0x4E44` (`ND`) |
| `E001` | R | `VERSION` | версия окна, сейчас 1 |
| `E001` | R | `VERSION` | версия окна, сейчас 2 |
| `E002` | R | `STATUS` | состояние операции |
| `E003` | R | `ERROR` | код `PNAND_*`, 0 = нет ошибки |
| `E004` | W | `COMMAND` | команда окна |
@@ -92,8 +94,9 @@ ARM.
| `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 |
| `E010` | W | `CONFIRM` | `0xA55A` непосредственно перед разрушительной командой |
| `E100..E4FF` | R/W | `PAGE_DATA` | 1024 регистра main, два байта LE |
| `E500..E51F` | R/W | `PAGE_OOB` | 32 регистра OOB, два байта LE |
Между управляющими регистрами и окнами данных есть зарезервированные адреса.
Чтение блока через них не выполняется: каждый запрос должен начинаться внутри
@@ -107,6 +110,8 @@ ARM.
| 1 | `0x0002` | `BUSY` |
| 2 | `0x0004` | `PAGE_VALID` |
| 3 | `0x0008` | `BAD_BLOCK` |
| 4 | `0x0010` | `WRITE_SUPPORTED`, порт способен управлять `WP#` |
| 5 | `0x0020` | `BUFFER_DIRTY`, буфер изменён после чтения/очистки |
| 15 | `0x8000` | `ERROR`, подробность в `E003` |
GUI читает окно данных только при `READY=1`, `PAGE_VALID=1`, `ERROR=0`.
@@ -118,6 +123,9 @@ GUI читает окно данных только при `READY=1`, `PAGE_VALI
| 1 | `RESET` | сброс NAND и ожидание Ready |
| 2 | `READ_ID` | обновляет `E00B/E00C` |
| 3 | `READ_PAGE` | загружает main/OOB выбранной страницы |
| 4 | `CLEAR_BUFFER` | заполняет main/OOB значением `0xFF` для подготовки записи |
| 5 | `PROGRAM_PAGE` | программирует выбранную страницу из буфера |
| 6 | `ERASE_BLOCK` | стирает блок, содержащий выбранную страницу |
Запись номера страницы и запуск — две отдельные операции. Сначала GUI пишет
`PAGE_LO/PAGE_HI`, затем записывает `READ_PAGE` в `COMMAND`. Нельзя отправлять
@@ -172,6 +180,28 @@ GUI хранит номер последней полностью записан
## PROGRAM/ERASE
Запись и стирание не включены намеренно. Они требуют отдельного разрешения,
проверки ECC, защиты загрузочных блоков и двухфазного подтверждения через GAS.
До добавления этих функций `WP#` удерживается активным аппаратным портом.
Разрушительные команды доступны только если установлен флаг
`WRITE_SUPPORTED`. Ядро проверяет bad-block marker и отказывается изменять
заводской плохой блок. `WP#` снимается только внутри операции и включается
обратно после проверки status fail-бита, тайм-аута или другой ошибки.
Для программирования очищенной страницы:
1. Записать `PAGE_LO/PAGE_HI`.
2. Выполнить `CLEAR_BUFFER`.
3. Записать необходимые main/OOB-регистры. Незаписанные байты останутся
`0xFF`; OOB лучше не менять без определённой ECC-разметки.
4. Записать `0xA55A` в `CONFIRM`.
5. Следующей записью без промежуточных операций отправить `PROGRAM_PAGE`.
6. Проверить `READY`, отсутствие `ERROR` и изменение `GENERATION`.
Для стирания записать любую страницу целевого блока в `PAGE_LO/PAGE_HI`, затем
`0xA55A` в `CONFIRM` и сразу `ERASE_BLOCK`. Изменение страницы, буфера или
другого управляющего регистра сбрасывает подтверждение. После успешного
стирания `PAGE_VALID` очищается.
Повторное программирование не может превратить `0` обратно в `1`: для этого
требуется стирание всего блока. Перед первым тестом сохраните полный raw-дамп,
исключите загрузочные блоки и используйте заведомо расходный исправный блок.
Библиотека не реализует ECC, wear leveling, журналирование и восстановление
после пропадания питания.