Справочник платформы Rockchip для RK RT-Thread SDK, чипов, перечисленных в оригинале, включая RK2108/RK2118. Поддержка конкретных плат ArmSoM не подтверждена, аппаратная проверка не проводилась. До адаптации проверьте SoC, SDK/BSP, версию RT-Thread, контроллер, IOMUX, проводку и напряжения. Команды и результаты — примеры оригинала, не измерения ArmSoM; аппаратные операции и доступ к flash не выполнялись. Есть только китайский оригинал; все четыре языка используют его рисунки.
RK-KF-YF-080 · V1.4.0
1. Введение
1.1 Поддерживаемые устройства
SPI NOR имеет малые корпуса, быстрое чтение по сравнению с другими малыми энергонезависимыми устройствами, мало выводов и простой протокол. Обычные чипы поддерживают 1/2/4 линии, устойчивы к инверсии битов, адресуют байты и читают без ожидания после команды/адреса, позволяя XIP (в источнике “Excute In Place”). RK RTOS предоставляет общие NOR-интерфейсы и автоматический XIP. SPI NAND использует те же контроллеры и поддерживается SDK RT-Thread. Однако необходим FTL либо соответствующая файловая система, с заметным расходом RAM/кода и ограниченной стабильностью. Требования к питанию при отключении высоки; MCU без батареи особенно уязвимы. Поэтому источник не рекомендует NAND, кроме отдельных случаев расширения для прошивки только для чтения.
1.2 Контроллеры
RK SPI flash использует FSPI, SFC или SPI.
- FSPI (Flexible Serial Peripheral Interface): SPI NOR/NAND, SPI PSRAM/SRAM; Standard (1 линия), Dual, Quad, в некоторых версиях Octal; SDR, в некоторых версиях DTR; XIP; встроенный DMA.
- SFC (Serial Flash Controller): SPI NOR/NAND, SPI PSRAM/SRAM; Standard/Dual/Quad; SDR; встроенный DMA.
- Универсальный SPI: SPI NOR/NAND и SPI PSRAM; Standard с одной линией; SDR; внешний DMA.
1.3 XIP NOR flash
XIP (eXecute In Place) позволяет CPU выбирать инструкции из отображённой flash без копирования в RAM; адрес выполнения совпадает с адресом отображения. NOR XIP доступен только для чтения, поэтому там размещаются код и неизменяемые данные. FSPI позволяет также DSP и другим master обращаться к flash как к SRAM только для чтения; см. TRM FSPI. API чтения NOR использует XIP (отображение, без лишней настройки регистров, предвыборка, высокая эффективность) либо CPU (настройка контроллера и перенос FIFO процессором). По умолчанию XIP. RT_SNOR_XIP_DATA_BEGIN задаёт начало: при 327680 диапазон [0:327680) читается CPU, [327680,конец] — XIP.
1.4 Архитектура драйвера SPI flash
Для FSPI/SFC/SPI выделен слой контроллера. Четыре слоя NOR: MTD; RTOS driver (регистрация устройства, контроллера/операций в HAL_SNOR, обёртка чтения/записи/стирания); протокол HAL_SNOR; контроллер. Оригинал называет три перечисленных типа «двумя».

Рисунок китайского оригинала (p.6)
FSPI: drv_snor.c оборачивает HAL чтение/запись в SPI_Xfer, регистрирует FSPI host и SPI_Xfer в HAL_SNOR, оборачивает чтение/запись/стирание и регистрирует OS-устройство в MTD. hal_snor.c реализует протокол NOR, hal_fspi.c — контроллер. SPI: drv_snor.c оборачивает чтение/запись OS-драйвера в SPI_Xfer, регистрирует host и SPI_Xfer в HAL_SNOR, оборачивает операции протокола и регистрирует MTD. hal_snor.c реализует протокол, hal_spi.c — нижний уровень контроллера, SpiDevice.c — регистрацию и обёртку RTOS SPI. Примечания:
- Реализации соответствуют диаграмме.
- RK SPI DMA находится в OS-драйвере. SPI обслуживает другие устройства и требует защиты границ аппаратных ресурсов. Поэтому flash использует OS SPI, не напрямую hal_spi.c.
1.5 Возможности FSPI чипов
Перечислены только SoC с открытой реализацией хранения.
| SOC | FSPI/SFC IO max rate | FSPI/SFC data io lines | Support XIP |
|---|---|---|---|
| RK2108/Pisces | 150MHz | x1\x2\x4 SDR | Y |
| RK2206 | 150MHz | x1\x2\x4 SDR | Y |
| RK2118 | SDR:133MHz DTR:80MHz |
x1\x2\x4 SDR x4 DDR with/without DQS x8 DDR with/without DQS |
Y |
Поддержка AP: Rockchip_Developer_Guide_Linux_Flash_Open_Source_Solution_CN.md. x1 — Standard, x2 Dual, x4 Quad, x8 Octal. Quad по умолчанию SDR, Octal — DDR with DQS.
2. SPI NOR
2.1 Настройка
2.1.1 Архитектура
| Type | Memory | Controller driver | Flash framework |
|---|---|---|---|
| SPI NOR | SPI NOR | hal: lib/hal/src/hal_fspi.c RT-Thread: bsp/rockchip/commob/drv_snor.c |
hal: lib/hal/src/hal_snor.c |
Корень HAL: bsp/rockchip/common/hal. Поддерживаемые NOR указаны в lib/hal/src/hal_snor.c, другие файлы — в том же каталоге. Сопоставьте ID или маркировку. ПО определяет чип по ID и выбирает максимальную ширину контроллера; уменьшение задаётся макросами драйвера.
2.1.2 Настройка драйвера
Сначала определите аппаратный контроллер SPI flash и выберите соответствующую схему. Основной пункт menuconfig:
RT-Thread rockchip common drivers --->
[*] Enable ROCKCHIP SPI NOR Flash
(80000000) Reset the speed of SPI Nor flash in Hz
[ ] Set SPI Host DUAL IO Lines /* 如果 FSPI 主控仅预留 IO0~1,应使用 Dual mode */
Choose SPI Nor Flash Adapter (Attach FSPI controller to SNOR) --->
Определения настроек:
RT_USING_MTD_NOR=y
RT_USING_SNOR=y
RT_SNOR_SPEED=80000000 /* IO 接口速率 */
# RT_SNOR_DUAL_IO=n /* 默认不配置,Quad SPI 限制为 Duad SPI 使用 */
# RT_SNOR_XIP_DATA_BEGIN=0 /* 默认不配置,XIP 读接口实现起始地址,详细参考 “Nor Flash XIP 技术”说明 */
RT_USING_SNOR_FSPI_HOST=y /* FSPI 控制器方案 */
# RT_USING_SNOR_SFC_HOST=y /* SFC 控制器方案 */
# RT_USING_SNOR_SPI_HOST=y /* SPI 控制器方案 */
# RT_SNOR_SPI_DEVICE_NAME="spi2_0" /* SPI 控制器方案,指定目标控制器 */
RT_USING_DFS_MNTTABLE=y # 启动 DFS mnt table 自动挂载支持
RT_USING_DFS_ELMFAT=y # 启用 elm FatFs
RT_DFS_ELM_MAX_SECTOR_SIZE=4096 # 设置 elm FatFs sector size,设定固定为 4KB
2.1.3 Таблица разделов
См. настройку таблицы разделов в rockchip/Rockchip_Developer_Guide_RT-Thread_CN.md. NOR регистрирует как устройства RT-Thread только разделы с FLAG [8,9] property 1, 2 или 3. Например root обычно Flag=0x305 и становится блочным устройством root.
2.1.4 Создание, разбор и регистрация разделов
Упакованная прошивка RK RT-Thread размещает RK_PARTITION в первых 2KB flash. Данные меняются в setting.ini. После инициализации NOR таблица разбирается и регистрируется snor_partition_init в drv_snor.c. Проверка регистрации:
msh />list_device
device type ref count
------- -------------------- ----------
root Block Device 1 /* 分区名 root,分区类型 block 设备,Nor flash 支持 setting.ini 修改设定为 MTD 设备 */
snor MTD Device 0 /* SPI Nor 根存储设备,分区读写最终接入到该 节点完成读写擦除 */
2.1.5 elm-fat и монтирование
Поддержка elm-fat RT-Thread:
RT-Thread Components --->
Device virtual file system --->
[*] Using device virtual file system
[*] Using mount table for file system /* 实现相应注册分区表,可实现分区上电自动挂 载 */
[*] Enable elm-chan fatfs /* fat 文件系统 */
elm-chan's FatFs, Generic FAT Filesystem Module --->
(4096) Maximum sector size to be handled. /*对于 SPI Nor 产品必须修改为 4096 */
При CONFIG_RT_USING_DFS_MNTTABLE добавьте регистрацию в mnt.c, например root в /:
const struct dfs_mount_tbl mount_table[] =
{
{"root", "/", "elm", 0, 0},
{0}
};
Для собственной последовательности монтирования:
dfs_mount("root", "/", "elm", 0, 0)
Команда монтирования:
mount root / elm
Образы elm-fat: см. ./bsp/rockchip/tools/mkroot.sh, основная команда mkfs.fat.
2.2 Особенности XIP
NOR поддерживает XIP; решение FSPI включает его автоматически. Далее особенности использования в изделии.
2.2.1 Включение XIP
FSPI flash по разделу настройки драйвера включает XIP по умолчанию. Для отключения выключите “Enable FSPI XIP”.
2.2.2 Переключение XIP при работе
Платформа автоматически переключает XIP; пользователю не нужно вызывать переключение. XIP off:
Стирание/запись NOR длительны и не поддерживаются во время XIP. При запросах, включая запись ФС, ПО приостанавливает XIP и переводит FSPI в normal mode. XIP тогда недоступен. Последовательность:
- Уведомить все затронутые master о приостановке XIP.
- Отключить глобальные прерывания, чтобы CPU не исполнял по прерыванию XIP-код из NOR.
- Отключить XIP.
XIP on: после завершения стирания/записи и перехода FSPI в idle драйвер восстанавливает XIP. Без этих операций он включён. Возобновление:
- Включить XIP.
- Включить глобальные прерывания (оригинал буквально пишет «глобальный терминал»; опечатка отмечена в записи сверки).
- Уведомить приостановленные устройства о возобновлении XIP. Точки входа:
static rt_base_t snor_xip_suspend(void)
static void snor_xip_resume(rt_base_t level)
Итого: NOR через FSPI включает XIP по умолчанию. При idle устройства читают NOR через отображённую XIP-память. Стирание/запись отключают XIP. Требуется уведомлять устройства о прекращении/возобновлении доступа. Отключение XIP также запрещает глобальные прерывания.
2.3 Примеры API
2.3.1 Байтное устройство SNOR MTD
См. _at_snor_test в snor_test.c:
snor_device = (struct rt_mtd_nor_device *)rt_device_find("snor");
rt_mtd_nor_erase_block(snor_device, test_lba * block_size, block_size);
rt_mtd_nor_write(snor_device, test_lba * block_size, (const rt_uint8_t
*)pwrite32, block_size);
rt_mtd_nor_read(snor_device, test_lba * block_size, (rt_uint8_t *)pread32,
block_size);
snor — байтное устройство. rt_mtd_nor_erase_block: Bytes, выравнивание минимум 4096Bytes (сектор flash). rt_mtd_nor_write/read: Bytes, минимум 1 Byte. Таблица RK использует секторы 512B; учитывайте преобразование.
2.3.2 Байтное MTD-устройство раздела
Драйвер NOR разбирает таблицу и регистрирует разделы. MTD partition из setting.ini становится байтным устройством с API SNOR MTD:
snor_device = (struct rt_mtd_nor_device *)rt_device_find("xxxx");
rt_mtd_nor_erase_block(snor_device, test_lba * block_size, block_size);
rt_mtd_nor_write(snor_device, test_lba * block_size, (const rt_uint8_t
*)pwrite32, block_size);
rt_mtd_nor_read(snor_device, test_lba * block_size, (rt_uint8_t *)pread32,
block_size);
2.3.3 Блочное устройство раздела
Block partition из setting.ini регистрируется блочным устройством. Используйте стандартные read/write RT-Thread; сектор 4KB.
2.4 Тестовый драйвер
При разработке SPI flash включите следующие простые тесты чтения/записи.
2.4.1 Настройка драйвера
RT-Thread bsp test case --->
RT-Thread Common Test case --->
[*] Enable BSP Common TEST
[*] Enable BSP Common SNOR TEST (NEW)
После настройки в msh появляется snor_test.
2.4.2 Команды теста
Введите snor_test для справки. Единицы команд ниже — байты.
1. snor_test write offset size
2. snor_test read offset size loop
3. snor_test erase offset
4. snor_test stress offset size loop
5. snor_test io_stress offset size loop width rw
6. snor_test pm_test
like:
snor_test write 2097152 4096
snor_test read 2097152 4096 2000
snor_test erase 2097152
snor_test stress 2097152 2097152 5000
snor_test io_stress 2097152 2097152 5000 4
snor_test pm_test
offset: смещение в байтах внутри flash, не XIP; только десятичное. stress: возрастающие данные. io_stress width: последовательность состояний IO; 4 для Quad, 8 для Octal. rw: 1 только запись со стиранием, 2 чтение, 3 чтение/запись.
2.4.3 Примеры команд
2.4.3.1 Скорость чтения
msh >snor_test read 2097152 4096 2000
[SNOR TEST] read: 30219d00 + 0x0:0x00000200,0x0000000f,0x000000ff,0x00000000,
[SNOR TEST] read: 30219d00 + 0x10:0x000000ff,0x000000cc,0x000000c3,0x000000cc,
[SNOR TEST] read: 30219d00 + 0x20:0x000000c3,0x0000003c,0x000000cc,0x000000ff,
[SNOR TEST] read: 30219d00 + 0x30:0x000000fe,0x000000ff,0x000000fe,0x000000ef,
snor read speed: 143719 KB/s
2.4.3.2 Сигналы Quad Flash
Тест сигнала записи:
snor_test io_stress 2097152 2097152 5000 4 1
Тест сигнала чтения:
snor_test io_stress 2097152 2097152 5000 4 2
2.4.3.3 Сигналы Octal Flash
Тест сигнала записи:
snor_test io_stress 2097152 2097152 5000 8 1
Тест сигнала чтения:
snor_test io_stress 2097152 2097152 5000 8 2
2.5 Устранение неисправностей
Проверка регистрации: list_device должен показывать snor.
“Init adapte error ret= -19” выводит результат snor_adapt: -1 означает NOR ID 0xff, возможна плохая пайка, проверьте схему/сигналы; -19 — чип не поддерживается, обратитесь к RK для добавления; -22 — контроллер SPI не найден.
Потребляет ли постоянно включённый XIP лишнюю мощность? FSPI по таймауту idle отпускает CS, NOR переходит в малопотребляющий idle; большой разницы нет.
Несколько master XIP: шина арбитрирует и выполняет запросы последовательно, ожидающие остаются на шине.
Частая запись ФС: разместите код в SRAM/PSRAM и отключите XIP, иначе страдает реальное время RTOS. При исполнении XIP минимизируйте стирание/запись NOR.
Чтение ФС не отключает XIP: драйвер читает через него.
Без таблицы разделов монтирование невозможно: её нужно сохранить в начале flash; текущий драйвер RK NOR разбирает только такую таблицу.
3. SPI NAND
3.1 Примечания
3.1.1 Хранение RK SPI NAND
| Filesystem | Update |
|---|---|
| FATFS | USB / programmer / OTA |
3.2 Настройка
3.2.1 Архитектура

Рисунок китайского оригинала (p.15)
| Type | Memory | Driver |
|---|---|---|
| SPI Nand | SPI Nand | DHARA FTL: bsp/rockchip/common/dhara/ RTT Mini FTL: bsp/rockchip/common/mini_ftl.c RTT SPI Nand: bsp/rockchip/common/drv_spinand.c HAL SPI Nand: lib/hal/src/hal_spinand.c HAL Controller: lib/hal/src/hal_fspi.c |
Корень HAL: bsp/rockchip/common/hal. Поддержка NAND — lib/hal/src/hal_spinand.c и соседние файлы. Сопоставьте ID/маркировку. Драйвер определяет ID и выбирает максимальную ширину IO; уменьшение задаётся макросами.
3.2.2 Настройка драйвера
Определите аппаратный контроллер перед выбором решения. Пункт menuconfig:
RT-Thread rockchip common drivers --->
[*] Enable ROCKCHIP SPI Nand Flash
(80000000) Reset the speed of SPI Nand flash in Hz
(y) Support mini ftl
Choose SPI Nor Flash Adapter (Attach FSPI controller to SNOR) --->
Attach FSPI controller to SPINAND
[ ] extend fspi cs1 as SPINAND device (NEW)
Определения настроек:
RT_USING_SNOR=n # 关闭 SPI Nor 驱动,通常外设仅有一种 SPI Flash
RT_USING_MTD_NAND=y
RT_USING_SPINAND=y
RT_SPINAND_SPEED=80000000 # IO 接口速率
RT_USING_SPINAND_FSPI_HOST=y # FSPI 控制器方案
RT_USING_FTL=y # 启用 SPI Nand FTL 存储管理算法
RT_USING_DHARA=y # 启用 SPI Nand DHARA FTL 存储管理算法(与 Mini FTL 兼容)
RT_USING_DFS_MNTTABLE=y # 启动 DFS mnt table 自动挂载支持
RT_USING_DFS_ELMFAT=y # 启用 elm FatFs
RT_DFS_ELM_MAX_SECTOR_SIZE=2048 # 设置 elm FatFs sector size,设定为 flash pagesize,通常为 2KB/4KB,参考颗粒手册
Также отключите XIP: XIP = ‘N’ в rtconfig.py.
3.2.3 Алгоритмы FTL
3.2.3.1 DHARA FTL
Dhara (Dæ:ra) — открытый FTL для NAND-систем с ограниченными ресурсами, предоставляющий изменяемый блочный интерфейс чтения/записи.
- Износ: число стираний любых двух блоков отличается максимум на 1.
- Скорость GC настраивается коэффициентом GC за счёт резервного места.
- Запись/trim логического сектора атомарны. При потере питания возврат к последней синхронизации; она периодическая либо принудительная.
- При равномерных плохих блоках все операции, включая запуск, имеют худшую сложность O(log n) для размера чипа n. При DHARA API блочного раздела используют DHARA, сектор равен странице, обычно 2KB/4KB. Ограничение: по умолчанию поддерживается только всё NAND как область FTL. Применение: один FSPI с NAND для прошивки/данных; один FSPI с NOR на CS0 для прошивки без XIP и NAND на CSN1 для данных; несколько FSPI, NOR на FSPI0 и NAND на FSPI1.
3.2.3.2 Драйвер Mini FTL
Mini FTL не стандартный FTL: только базовое управление плохими блоками, преимущественно для обновления прошивки разделов. Раздел root регистрируется одноимённым блочным устройством для ФС только для чтения.
3.2.4 Настройка таблицы разделов
3.2.4.1 Планирование разделов
Начало и размер кратны 256KB для блоков 128KB/256KB. Резерв замены плохих блоков: кроме раздела таблицы малым разделам 1–2 flash blocks, более 8MB — 1%. В конце рекомендуется 2MB: четыре блока таблицы плохих блоков и один хороший блок резервной таблицы, для 128KB/256KB. Для OTA рекомендуется A/B.
3.2.4.2 Расширение RK Partition
Таблица RK похожа на GPT, но экономнее и быстрее инициализируется, преимущественно RV1107/8 и MCU. NAND по умолчанию регистрирует последний раздел для DHARA FTL, обычно пользовательский root для ФС.
3.2.4.3 Расширение GPT
SDK RK поддерживает GPT; последний раздел по умолчанию управляется DHARA FTL, обычно root для ФС.
3.2.4.4 Собственный ROOT
Без расширения таблицы рассмотрите одиночный ROOT в drv_spinand.c:
RT_ROOT_PART_OFFSET
RT_ROOT_PART_SIZE
Единицы — секторы 512B. RK3308 RT-Thread build.sh показывает привязку определений к сборке.
3.2.5 Разбор и регистрация разделов
После инициализации NAND разбирается таблица и регистрируется последний раздел. Проверка:
msh />list_device
device type ref count
------- -------------------- ----------
userdata Block Device 0 /* DHARA FTL 实现,分区类型 block 设备, 通常为可读写 FAT 文件系统 */
root Block Device 1 /* Mini FTL 实现,分区类型 block 设备,通 常为只读 FAT 文件系统 */
spinand MTD Device 0 /* SPI Nand MTD 设备,分区读写最终接入到该 节点完成读写擦除 */
3.3 Прошивка с ПК
Используйте SocToolKit Windows/Linux; есть соответствующие массовые инструменты. Для OTA рекомендуется A/B.
И отдельные, и упакованные образы NAND в итоге прошиваются по разделам. RK Partition поддерживает отдельные, но не Firmware.img. GPT — отдельные и update.img. Остальные расширения — только отдельные.
3.4 Примеры API

Рисунок китайского оригинала (p.19)
3.4.1 Основной API байтного MTD
См. spinand_test в spinand_test.c:
mtd_dev = (struct rt_mtd_nor_device *)rt_device_find("spinand0");
rt_mtd_nand_check_block(mtd_dev, block);
rt_mtd_nand_erase_block(mtd_dev, block);
rt_mtd_nand_write(mtd_dev, page_addr + i, (const rt_uint8_t *)buffer, mtd_dev->page_size, RT_NULL, 0);
rt_mtd_nand_read(mtd_dev, page_addr + i, (rt_uint8_t *)buffer, mtd_dev->page_size, RT_NULL, 0);
spinand0 — байтное устройство. rt_mtd_nand_check_block: true для плохого, false для хорошего блока. Здесь оригинал называет rt_mtd_nor_erase_block (блоки) и rt_mtd_nor_write/read (байты, выравнивание по странице, обычно 2KB/4KB; см. руководство flash); имена NOR сохранены. Таблица RK использует секторы 512B; преобразуйте единицы.
3.4.2 Mini FTL: OTA/файловая система
OTA: mini_ftl_test_one_flash_block в spinand_test.c:
rt_uint32_t block_size = mtd_dev->pages_per_block * mtd_dev->page_size;
mtd_dev = (struct rt_mtd_nor_device *)rt_device_find("spinand0");
mini_ftl_erase(mtd_dev, addr, block_size);
mini_ftl_write(mtd_dev, buffer, addr, block_size);
mini_ftl_read(mtd_dev, buffer, addr, block_size);
mini_ftl_erase: байты, выравнивание blocksize. mini_ftl_write: байты, pagesize, сначала стирание. mini_ftl_read: байты, pagesize. При OTA выровняйте buffer по block_size, одним вызовом завершите erase/write/read с проверкой; перед обновлением elm FatFs сотрите весь раздел. RK Partition: rk_partition_list; GPT: dfs_part_list, пока без name info. После настройки раздел root регистрируется как root block через Mini FTL для ФС только для чтения. Только прошивка образа, без онлайн-форматирования.
3.4.3 API файловой системы DHARA FTL
Последний раздел регистрируется одноимённым блоком DHARA FTL для ФС чтения/записи. Поддерживаются прошивка образа и онлайн-форматирование.
3.5 Файловые системы
3.5.1 Поддержка elm FatFs
Блок Mini FTL только для чтения, монтирует FAT, прошивается FAT-образом, без онлайн-форматирования. DHARA FTL читает/пишет FAT, требует FAT-образ в оболочке DHARA и поддерживает онлайн-форматирование.
3.5.1.1 Монтирование разделов
При CONFIG_RT_USING_DFS_MNTTABLE добавьте регистрацию в mnt.c, например root в /:
const struct dfs_mount_tbl mount_table[] =
{
{"root", "/", "elm", 0, 0},
{0}
};
Для собственного монтирования:
dfs_mount("root", "/", "elm", 0, 0)
Команда монтирования:
mount root / elm
3.5.1.2 Онлайн-форматирование раздела
mkfs -t elm userdata
root только для чтения: монтирование, без онлайн-форматирования.
3.5.1.3 Офлайн-образы elm-fat
См. ./bsp/rockchip/tools/mkroot.sh и mkfs.fat; -S задайте по page_size, обычно 2048/4096 согласно NAND.
3.5.1.4 Офлайн-образы DHARA
Инструмент DHARA:
Usage: ./dhara_utils <file_path> <flash_page_size> <num_blocks>
Пример: FAT16 DHARA офлайн, раздел 504 блока, страница NAND 2KB:
mkfs.vfat -F 16 -s 1 -S 2048 fat.img
./rkbin/dhara_utils fat.img 2 504
Выход: fat.img.dhara.
Размер см. в планировании разделов.
3.6 Тестовый драйвер
3.6.1 Основная настройка теста
RT-Thread bsp test case --->
RT-Thread Common Test case --->
[*] Enable BSP Common TEST
[*] Enable BSP Common SPINAND TEST (NEW)
После настройки в msh появляется spinand_test:
msh />spinand_test
1. spinand_test write <page_addr> <page_num>
2. spinand_test read <page_addr> <page_nun>
3. spinand_test erase <blk_addr>
4. spinand_test erase_all <blk_addr>
5. spinand_test stress <loop>
6. spinand_test bbt
7. spinand_test markbad <blk_addr>
8. spinand_test mini_ftl_test <byte_offset>
9. spinand_test part_list
like:
spinand_test write 1024 1
spinand_test read 1024 1
spinand_test erase 16
spinand_test erase_all 512
spinand_test stress 5000
spinand_test bbt
spinand_test mini_ftl_test 67108864
spinand_test part_list
3.6.2 Нагрузка flash_stress_test
Цель: стабильность NAND при чтении/записи. Подготовьте 10 устройств. Пример области: смещение 512 блоков, размер 256 flash blocks.
- После загрузки spinand_test stress 5000 512 256, питание не отключать.
- Запишите журнал.
- Успех при нормальной работе после 24 часов, иначе неудача.
3.6.3 power_lost_test отключения питания
Цель: устойчивость к отключению, особенно частому в NAND без батареи. Подготовьте 10 устройств. Метод:
- Создайте нагрузку копирования файлов.
- Питание 2 секунды, отключение 3 секунды: цикл 5 секунд, 8 часов, около 5760 отключений. После каждого отключения устройство должно включиться и запустить копирование в пределах 5 секунд.
- Запишите журнал.
- Оригинал требует нормальную работу после 24 часов (это противоречит 8 часам выше; оба значения сохранены), иначе неудача. См. раздел примера исходников отключения.
3.7 Устранение неисправностей
3.7.1 Зависание RK2118 с NAND
Симптом:
FW data_offset:2048
FW data_size: 195584
FW load_addr: 0x1060800
copy 1090000 20a200 400
hash_256 fail! ret:-1
MemBoot fali!
SoftReset...
Попробуйте отключить XIP:
diff --git a/bsp/rockchip/rk2118/rtconfig.py b/bsp/rockchip/rk2118/rtconfig.py
index 2b6e696e2b..32b5117513 100644
--- a/bsp/rockchip/rk2118/rtconfig.py
+++ b/bsp/rockchip/rk2118/rtconfig.py
@@ -29,8 +29,8 @@ if os.getenv('RTT_EXEC_PATH'):
#BUILD = 'debug'
BUILD = 'release'
-XIP = 'Y'
-#XIP = 'N'
+#XIP = 'Y'
+XIP = 'N'
if os.getenv('RTT_BUILD_XIP'):
XIP = os.getenv('RTT_BUILD_XIP').upper()
3.7.2 NAND не поддерживает RK Firmware.img
RK Firmware.img заполняет неиспользуемые части разделов нулями, кроме допускаемого пустого последнего раздела. При тех же полезных образах рост разделов резко увеличивает заполнение; всё передаётся одним обновлением. NAND допускает заводские плохие блоки и требует резерв замены. Поэтому “one firmware” с заполнением несовместим: даже единый пакет нужно распаковать и записать только полезные образы по разделам. Программатор также не поддерживает монолитный образ.
3.7.3 Проблемы отключения NAND
Аварийное отключение обходит штатную деинициализацию и может оставить NAND при нестабильном напряжении. Главным образом страдают стирание (несколько миллисекунд) и программирование (сотни микросекунд). Для 3V3 обычно требуется минимум 2.7V; уточняйте по документации. Два типа отказов: неполная запись; случайные ошибки команд при нестабильном напряжении. Восстановление ФС защищает от неполных данных, но данные могут потеряться. Защита от нестабильного напряжения:
- PMIC контролирует VCC IO, обычно сбрасывает CPU ниже 2.91V, прекращая новые команды. Разряд внешней схемы должен сохранять питание около 1ms для последней операции.
- Reset IC аналогичен, обычный порог 2.93V.
- RK NPOR контролирует VCCIO и сбрасывает CPU по порогу. Предпочтительны батарея или постоянное питание. Иначе улучшите схему: PMIC/Reset IC/RK NPOR должны обнаружить спад VCC IO и сбросить CPU до команд при низком напряжении.
Добавьте ёмкость по demo RK, чтобы VCCIO flash оставалось нормальным обычно в течение tBERS (стирание блока). Снижайте отключения при доступе к flash. Предусмотрите восстановление: две копии прошивки, важные данные в read-only ФС, восстановление повреждённых записываемых разделов для работы или OTA. Для проверки времени выполните power_lost_test в реальном изделии/нагрузке и снимите VCC3V3/RESETn:

Рисунок китайского оригинала (p.25)
Осциллограф должен показывать точку RESETn/Reset IC (Y1), падение VCC3V3 до 2V7 (Y2) и время ΔY1Y2. Повторите и анализируйте минимум. Для RV1106 и подобных RKNPOR RESETn внутренний; используйте GPIO высокого уровня с внешней подтяжкой вниз. При сбросе GPIO отключается и падает; переход приблизительно соответствует сбросу CPU.
3.7.4 Пример исходников отключения NAND
#include <dfs_file.h>
static void readwrite_test(void *param)
{
int fd, size, len = 2048, loops = 0;
char *pwrite, *pread;
pwrite = rt_malloc(len);
if (!pwrite) {
rt_kprintf("malloc pwrite failed\n");
return;
}
pread = rt_malloc(len);
if (!pread) {
rt_kprintf("malloc pread failed\n");
rt_free(pwrite);
return;
}
fd = open("/file_stress.txt", O_RDWR | O_CREAT);
if (fd < 0)
{
rt_kprintf("%s open file failed\n", __func__);
goto err_open;
}
while (1) {
rt_kprintf("file_stress, loops=%d\n", loops);
rt_memset(pwrite, loops & 0xff, len);
lseek(fd, 0, SEEK_SET);
write(fd, pwrite, len);
lseek(fd, 0, SEEK_SET);
size = read(fd, pread, len);
if (size < 0) {
break;
}
if (rt_memcmp(pwrite, pread, len)) {
rt_kprintf("%s compare failed, %x\n", __func__, pread[0]);
break;
}
loops++;
}
close(fd);
err_open:
rt_free(pread);
rt_free(pwrite);
}
void file_stress(void)
{
rt_thread_t thread;
thread = rt_thread_create("file_stresss",
readwrite_test, NULL,
2048,
21, 20);
rt_thread_startup(thread);
}
