Rockchip · AI & Linux Hub

Хранение и сеть

Rockchip RT-Thread SPI Flash: руководство разработчика

Rockchip RT-Thread SPI Flash: руководство разработчика — V1.4.0

· ArmSoM Editorial · Rockchip source documentation · 23 мин чтения

Справочник платформы Rockchip для RK RT-Thread SDK, чипов, перечисленных в оригинале, включая RK2108/RK2118. Поддержка конкретных плат ArmSoM не подтверждена, аппаратная проверка не проводилась. До адаптации проверьте SoC, SDK/BSP, версию RT-Thread, контроллер, IOMUX, проводку и напряжения. Команды и результаты — примеры оригинала, не измерения ArmSoM; аппаратные операции и доступ к flash не выполнялись. Есть только китайский оригинал; все четыре языка используют его рисунки.

RK-KF-YF-080 · V1.4.0

ArmSoM Docs · RT-Thread

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)

Рисунок китайского оригинала (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. Примечания:

  1. Реализации соответствуют диаграмме.
  1. 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 тогда недоступен. Последовательность:

  1. Уведомить все затронутые master о приостановке XIP.
  1. Отключить глобальные прерывания, чтобы CPU не исполнял по прерыванию XIP-код из NOR.
  1. Отключить XIP.

XIP on: после завершения стирания/записи и перехода FSPI в idle драйвер восстанавливает XIP. Без этих операций он включён. Возобновление:

  1. Включить XIP.
  1. Включить глобальные прерывания (оригинал буквально пишет «глобальный терминал»; опечатка отмечена в записи сверки).
  1. Уведомить приостановленные устройства о возобновлении 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)

Рисунок китайского оригинала (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)

Рисунок китайского оригинала (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.

  1. После загрузки spinand_test stress 5000 512 256, питание не отключать.
  1. Запишите журнал.
  1. Успех при нормальной работе после 24 часов, иначе неудача.

3.6.3 power_lost_test отключения питания

Цель: устойчивость к отключению, особенно частому в NAND без батареи. Подготовьте 10 устройств. Метод:

  1. Создайте нагрузку копирования файлов.
  1. Питание 2 секунды, отключение 3 секунды: цикл 5 секунд, 8 часов, около 5760 отключений. После каждого отключения устройство должно включиться и запустить копирование в пределах 5 секунд.
  1. Запишите журнал.
  1. Оригинал требует нормальную работу после 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)

Рисунок китайского оригинала (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);
}

Другие статьи по теме → · Учебные маршруты →