Сохранить текущие изменения 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

@@ -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, журналирование и восстановление
после пропадания питания.