Руководство по разработке драйвера SPI-NAND для Linux
Руководство по разработке драйвера SPI-NAND для Linux

Каталог статей

Руководство по разработке драйвера SPI-NAND для Linux

1 Обзор

1.1 Цель написания

Представляем дизайн драйверов Sunxi SPIN и mtd/ubi для облегчения разработки соответствующих драйверов и приложений.

1.2 Область применения

Этот дизайн подходит для всех платформ Sunxi.

1.3 Соответствующий персонал

Разработчики модулей Nand, разработчики приложений и т. д.

2 Термины, сокращения и понятия

MTD:(Memory Technology устройство) используется для доступа к устройствам хранения данных linux подсистема. Этот модуль MTD подсистема flash Приводная часть

UBI:UBI Подсистема основана на MTD подсистема,существовать MTD реализовано на nand Логика управления функциями, восходящая защита NAND Характеристики

плохой блок (Bad Block):Производственный процесси nand Физические свойства сами по себе приводят к тому, что существующее покидает завод, и нормальный процесс использования середина приведет к получению некачественного продукта. блок

3 Проектирование процесса

3.1 Архитектура

Драйвер NAND MTD/UBI в основном включает в себя 5 основных компонентов, как показано ниже:

Рисунок 3-1: Архитектура UBI

проиллюстрировать:

  • Стандартный интерфейс MTD: общий интерфейс чтения и записи для стыковки со слоем MTD.
  • FLASH bad block manager: водитель пара слоев flash плохой Блокиз Управление
  • FLASH SPL: В основном для чтения и письма. boot0, boot1, могут использоваться для ioctl Для загрузки0, загрузки1 изобновление
  • БЕЗОПАСНОЕ ХРАНИЛИЩЕ: в основном обеспечивает управление частными данными на верхнем уровне. SPI: уровень реализации контроллера на стороне HOST.

3.2 Структура исходного кода

Каталог исходного кода ядра: linux-5.4/drivers/mtd/awnand/spinand

Язык кода кода:javascript
копировать
.
├── Kconfig
├── Makefile
├── physic
│   ├── bbt.c
│   ├── cache.c
│   ├── core.c
│   ├── ecc.c
│   ├── id.c
│   ├── Makefile
│   ├── ops.c
│   └── physic.h
├── secure-storage.c
├── sunxi-common.c
├── sunxi-core.c
├── sunxi-debug.c
├── sunxi-nftl-core.c
└── sunxi-spinand.h

В каталоге ядра

Язык кода кода:javascript
копировать
`-- include
	`-- linux
	   `-- mtd
		    |-- aw-spinand.h

3.3 Определение ключевых данных

3.3.1 структура данных флэш-устройства.
Язык кода кода:javascript
копировать
struct aw_spinand_phy_info {
    const char *Model;
    unsigned char NandID[MAX_ID_LEN];
    unsigned int DieCntPerChip;
    unsigned int BlkCntPerDie;
    unsigned int PageCntPerBlk;
    unsigned int SectCntPerPage;
    unsigned int OobSizePerPage;
    #define BAD_BLK_FLAG_MARK 0x03
    #define BAD_BLK_FLAG_FRIST_1_PAGE 0x00
    #define BAD_BLK_FLAG_FIRST_2_PAGE 0x01
    #define BAD_BLK_FLAG_LAST_1_PAGE 0x02
    #define BAD_BLK_FLAG_LAST_2_PAGE 0x03
    int BadBlockFlag;
    #define SPINAND_DUAL_READ BIT(0)
    #define SPINAND_QUAD_READ BIT(1)
    #define SPINAND_QUAD_PROGRAM BIT(2)
    #define SPINAND_QUAD_NO_NEED_ENABLE BIT(3)
    #define SPINAND_ONEDUMMY_AFTER_RANDOMREAD BIT(8)
    int OperationOpt;
    int MaxEraseTimes;
    #define HAS_EXT_ECC_SE01 BIT(0)
    #define HAS_EXT_ECC_STATUS BIT(1)
    enum ecc_status_shift ecc_status_shift;
    int EccFlag;
    enum ecc_limit_err EccType;
    enum ecc_oob_protected EccProtectedType;
};

проиллюстрировать:

Model:flash из model имя

NandID:flash из id код

DieCntPerChip: за chip из die число

BlkCntPerDie: за die Сколько их block

PageCntPerBlk: за block Сколько их page

Секткнтперпаже: за page Сколько ихвентиляторокруг

OobSizePerPage: за page из obb размер

BadBlockFlag:плохой блок логотипов магазинкаждый существует block из этого page середина

  1. BAD_BLK_FLAG_FRIST_1_PAGE
  2. BAD_BLK_FLAG_FIRST_2_PAGE
  3. BAD_BLK_FLAG_LAST_1_PAGE
  4. BAD_BLK_FLAG_LAST_2_PAGE

OperationOpt: поддержка работы

  1. SPINAND_DUAL_READ
  2. SPINAND_QUAD_READ
  3. SPINAND_QUAD_PROGRAM
  4. SPINAND_QUAD_NO_NEED_ENABLE
  5. SPINAND_ONEDUMMY_AFTER_RANDOMREAD

MaxEraseTimes: Максимальное количество стертых данных.

EccFlag: Чтение характерного материала ecc status Говорит, что каталог должен быть другим

GD5F1GQ4UCYIG проходить 0Fh + C0h получать ecc статус, настройка не требуется EccFlag

MX35LF1GE4AB проходить 7Ch + one dummy byte получать ecc статус, затем настройте EccFlag = HAS_EXT_ECC_STATUS

Экктип: Настройки ecc Соответствие значений из статусных отношений

EccProtectedType: в spare Перейти к выбору получения ecc защищать из 16byte как oob округ

Пример (MX35LF2GE4AD):

Язык кода кода:javascript
копировать
{
    .Model = "MX35LF2GE4AD",
    .NandID = {0xc2, 0x26, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff},
    .DieCntPerChip  = 1,
    .SectCntPerPage = 4,
    .PageCntPerBlk  = 64,
    .BlkCntPerDie   = 2048,
    .OobSizePerPage = 64,
    .OperationOpt = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM | SPINAND_DUAL_READ,
    .MaxEraseTimes = 65000,
    .EccFlag = HAS_EXT_ECC_STATUS,
    .EccType = BIT4_LIMIT5_TO_8_ERR9_TO_15,
    .EccProtectedType = SIZE16_OFF4_LEN4_OFF8,
    .BadBlockFlag = BAD_BLK_FLAG_FIRST_2_PAGE,
},
3.3.2 структура данных флэш-чипа.
Язык кода кода:javascript
копировать
struct aw_spinand_chip {
    struct aw_spinand_chip_ops *ops;
    struct aw_spinand_ecc *ecc;
    struct aw_spinand_cache *cache;
    struct aw_spinand_info *info;
    struct aw_spinand_bbt *bbt;
    struct spi_device *spi;
    unsigned int rx_bit;
    unsigned int tx_bit;
    unsigned int freq;
    void *priv;
};

Эта структура определяет flash chip Слой физической моделиструктуры данныха также chip пара слоев flash интерфейс эксплуатации.

aw_spinand_chip_ops:flash Чтение, запись, стирание и другие рабочие интерфейсы

aw_spinand_ecc:flash ecc Чтение, запись и проверка рабочего интерфейса

aw_spinand_cache: для кеша page из управления, улучшить эффективность чтения и письма

aw_spinand_info:flash ID、page size и другую информацию и получать информацию из рабочего интерфейса

aw_spinand_bbt:flash плохой блокировать таблицу и интерфейсы операций управления

spi_device:spi Родительское устройство из операционной структуры

rx_bit: флаг операции чтения статуса

tx_bit: флаг операции записи состояния

3.3.3 aw_spinand_chip_request
Язык кода кода:javascript
копировать
struct aw_spinand_chip_request {
    unsigned int block;
    unsigned int page;
    unsigned int pageoff;
    unsigned int ooblen;
    unsigned int datalen;
    void *databuf;
    void *oobbuf;
    unsigned int oobleft;
    unsigned int dataleft;
};

Управляйте целевой структурой и изменяйте ее, чтобы заполнить данные, с которыми мы хотим работать. block из этого page изсколько смещенияданные

databuf/oobbuf

блок: блок, с которым нужно работать

страница: страница, на которой нужно работать

pageoff: смещение операции

ооблен: операция oob длина

datalen: длина данных операции

databuf: управлять целевыми данными

oobbuf: цель операции oob

3.3.4 ubi_ec_hdr
Язык кода кода:javascript
копировать
struct ubi_ec_hdr {
    __be32 magic;
    __u8 version;
    __u8 padding1[3];
    __be64 ec; /* Warning: the current limit is 31-bit anyway! */
    __be32 vid_hdr_offset;
    __be32 data_offset;
    __be32 image_seq;
    __u8 padding2[32];
    __be32 hdr_crc;
} __packed;

@magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)

@version: version of UBI implementation which is supposed to accept this UBI image

@padding1: reserved for future, zeroes

@ec: the erase counter

@vid_hdr_offset: where the VID header starts

@data_offset: where the user data start

@image_seq: image sequence number

@padding2: reserved for future, zeroes

@hdr_crc: erase counter header CRC checksum

EC: Erase Подсчитайте, запишите количество стираний блоков, существующих ubiattach Укажите один, когда из если бы PEB Нет

EC, затем используйте среднее значение из EC стоимость, напишите EC Значение увеличивается только при стирании существующих 1

3.3.5 ubi_vid_hdr
Язык кода кода:javascript
копировать
struct ubi_vid_hdr {
    __be32 magic;
    __u8 version;
    __u8 vol_type;
    __u8 copy_flag;
    __u8 compat;
    __be32 vol_id;
    __be32 lnum;
    __u8 padding1[4];
    __be32 data_size;
    __be32 used_ebs;
    __be32 data_pad;
    __be32 data_crc;
    __u8 padding2[4];
    __be64 sqnum;
    __u8 padding3[12];
    __be32 hdr_crc;
} __packed;

@magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)

@version: UBI implementation version which is supposed to accept this UBI image(%UBI_VERSION)

@vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)

@copy_flag: if this logical eraseblock was copied from another physical eraseblock(for wear-leveling reasons)

@compat: compatibility of this volume(%0, %UBI_COMPAT_DELETE, %UBI_COMPAT_IGNORE,%UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)

@vol_id: ID of this volume

@lnum: logical eraseblock number

@padding1: reserved for future, zeroes

@data_size: how many bytes of data this logical eraseblock contains

@used_ebs: total number of used logical eraseblocks in this volume

@data_pad: how many bytes at the end of this physical eraseblock are not used

@data_crc: CRC checksum of the data stored in this logical eraseblock

@padding2: reserved for future, zeroes

@sqnum: sequence number

@padding3: reserved for future, zeroes

@hdr_crc: volume identifier header CRC checksum

Описание параметра

@sqnum это создать это VID Время заголовка из глобального счетчика последовательности из значения. каждый раз UBI написать новое из VID Первый раз flash Счетчик глобальной последовательности увеличивается, например, если это логическая eraseblock Карта к новому изфизиз. erase-block час. Глобальный счетчик последовательности является беззнаковым 64 битовое целое число, мы предполагаем, что оно никогда не переполнится. @sqnum(серийный номер) Используется для разделения старых и новых версий блоков логического стирания.

Есть две ситуации, когда может быть несколько физических eraseblock соответствуют той же логике стереть блок, т.е. существующий заголовок идентификации тома середина имеет то же самое из @vol_id и @lnum ценить. Предположим, у нас есть блок логического стирания. L, который отображается в блок физического стирания P。

  1. потому что UBI Блоки физического стирания могут стираться асинхронно, поэтому могут возникнуть следующие ситуации: L стирается асинхронно, поэтому P планируется удалить, а затем L написано, то есть. сопоставлен с другим блоком физического стирания П1, так что P1 пишется, то происходит нечистый перезапуск. Результат - есть две физики из eraseblock P и P1 соответствуют той же логикеиз eraseblock Л. но P1 Серийный номер больше, поэтому UBI существоватьсоединять flash Выберите, когда P1。
  2. UBI Логическое стирание блоков время от времени переехать Другие блоки физического стирания для выравнивания износа. Например, если UBI будет L от P переехать в P1,существовать P Перед физическим удалением произойдет нечистая перезагрузка с двумя физически стертыми блоками. P и P1 соответствует L,UBI долженсуществовать flash соединять Выберите, когда Чтосерединаодин。@sqnum Какое поле представляет PEB даоригинальныйиз (Очевидно P из @sqnum ниже) и копирую. Но да выбирает физически стертый блок да с более высоким серийным номером из-за недостаточности, потому что что может произойти нечистая перезагрузка, копировать процесс изсередина так P серединаданныеповрежден(P->P1 Не закончен). Просто выбрать физически стертый блок с меньшим серийным номером недостаточно, т.к. эти данные могут быть очень старыми (учитыватьсуществоватькопироватьпозже, чтобы P1 Добавьте больше данных из ситуаций). Кроме того, может существовать нечистая перезагрузка, стирание P Время только начинается, поэтому это вызовет нестабильность П, «в основном» да OK из, но есть еще нестабильные ситуации.

UBI использовать @copy_flag Поле указывает, что этот блок логического стирания является копией. УБИ Также рассчитать данные из CRC, когда данные перемещаются и сохраняются в копии (P1) из @data_crc поле. Поэтому, когда UBI Надо начинать с двух (P или P1) При выборе физически стертого блока проверяются новые блоки (P1) из @copy_flag。если оно очищено,Ситуация проста,Новый из будет выбран середина. Если это значение установлено,затем проверьте копию (P1) данные КПР. если CRC Проверка верна, потому что этот блок физического стирания выбран середина (П1). В противном случае будет выбран более старый из П. Если дастатический объем,@data_crc Поле содержит содержимое блока логического стирания. CRC Проверьте и. Для динамических томов он не содержит CRC проверятьиправило。толькоиз Исключенияда,Когда блок физически стираетсяданные При перемещении подсистемой выравнивания износа,Данные расчета подсистемы выравнивания износа CRC и сохраните его в @data_crc Полесередина。

@used_ebs Поле仅用于статический объем,это указывает на то, что объемданные Сколько блоков стирания необходимо。Для динамических томов,Это поле не указано и всегда содержит 0.

@data_pad Параметры выравнивания существующего значения рассчитываются при создании тома. Поэтому @data_pad Поле эффективно уменьшает объем блоков логического стирания из-за размера. Когда человек существует UBI Блок программного обеспечения, ориентированный на использование тома (например, крамфс) Это да очень удобно.

LEB и PEB

Рисунок 3-2: PEB-LEB

3.4 Описание основного интерфейса

3.4.1 Интерфейс уровня MTD
3.4.1.1 aw_rawnand_mtd_erase
Язык кода кода:javascript
копировать
static int aw_rawnand_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)

description:mtd erase interface

@mtd:MTD device structure

@instr:erase operation descrition structure

return:success return 0,fail return fail code

3.4.1.2 aw_rawnand_mtd_read
Язык кода кода:javascript
копировать
static int aw_rawnand_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,size_t *retlen, u_char *buf)

description:mtd read interface

@mtd:MTD device structure

@from:offset to read from MTD device

@len: data len

@retlen:had read data len

@buf:data buffer

return:success return max_bitflips,fail return fail code

3.4.1.3 aw_rawnand_mtd_read_oob
Язык кода кода:javascript
копировать
static int aw_rawnand_mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)

description:mtd read data with oob

@mtd:MTD device structure

@ops:oob eperation descrition structure

return:success return max_bitflips,fail return fail code

3.4.1.4 aw_rawnand_mtd_write
Язык кода кода:javascript
копировать
static int aw_rawnand_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)

description:mtd write data interface

@to:offset to MTD device

@len:want write data len

@retlen:return the writen len

@buf:data buffer

return:success return 0, fail return code fail

3.4.1.5 aw_rawnand_mtd_write_oob
Язык кода кода:javascript
копировать
static int aw_rawnand_mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *
ops)

description:write data with oob

@mtd:MTD device structure

@to:offset to MTD device

@ops:oob operation descrition structure

return:success return 0, fail return code fail

3.4.1.6 aw_rawnand_mtd_block_isbad

static int aw_rawnand_mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)

description:check block is badblock or not

@mtd:MTD device structure

@ofs: offset the mtd device start (align to simu block size)

return:true if the block is bad, or false if the block is good

3.4.1.7 aw_rawnand_mtd_block_markbad
Язык кода кода:javascript
копировать
static int aw_rawnand_mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)

description:mark block at the given offset as bad block

@mtd:MTD device structure

@ofs:offset the mtd device start

return:success to mark return 0, or fail return fail code.

3.4.2 Интерфейс физического уровня
3.4.2.1 aw_spinand_chip_read_single_page
Язык кода кода:javascript
копировать
static int aw_spinand_chip_read_single_page(struct aw_spinand_chip *chip, struct aw_spinand_chip_request *req)

description:Read physics on a page

@chip:See 3.3.2

@req:See 3.3.3

return:zero on success, else a negative error code.

3.4.2.2 aw_spinand_chip_write_single_page

Язык кода кода:javascript
копировать
static int aw_spinand_chip_write_single_page(struct aw_spinand_chip *chip, struct aw_spinand_chip_request *req)

description:Write physics on a page

@chip:See 3.3.2

@req:See 3.3.3

return:zero on success, else a negative error code.

3.4.2.3 aw_spinand_chip_erase_single_block
Язык кода кода:javascript
копировать
static int aw_spinand_chip_erase_single_block(struct aw_spinand_chip *chip, struct aw_spinand_chip_request *req)

description:Erase physics on a block

@chip:See 3.3.2

@req: See 3.3.3

return:zero on success, else a negative error code.

3.4.2.4 aw_spinand_chip_isbad_single_block
Язык кода кода:javascript
копировать
static int aw_spinand_chip_isbad_single_block(struct aw_spinand_chip *chip, struct aw_spinand_chip_request *req)

description:Set to bad block

@chip:See 3.3.2

@req:See 3.3.3

return:zero on success, else a negative error code.

3.4.2.5 aw_spinand_chip_markbad_single_block
Язык кода кода:javascript
копировать
static int aw_spinand_chip_markbad_single_block(struct aw_spinand_chip *chip, struct aw_spinand_chip_request *req)

description:Set to bad block

@chip:See 3.3.2

@req:See 3.3.3

return:zero on success, else a negative error code.

Конфигурация из 4 модулей

4.1 конфигурация модуля uboot

Язык кода кода:javascript
копировать
Device Drivers-->Sunxi flash support-->
[*]Support sunxi nand devices
[*]Support sunxi nand ubifs devices
[*]Support COMM NAND V1 interface

Как показано ниже:

​ Шаг 4-1: u-boot-spinand-menuconfig

Конфигурация модуля ядра 4.2

Язык кода кода:javascript
копировать
Device Drivers->Memory Technology Device(MTD) support-->sunxi-nand

​ Рисунок 4-2: UBI

Рисунок 4-3: ker_nand-cfg

Рисунок 4-4: ker_spinand

Язык кода кода:javascript
копировать
Device Drivers->SPI support

Рисунок 4-5: spi-1

Рисунок 4-6: spi-2

Язык кода кода:javascript
копировать
Device Drivers->DMA Engine support

Рисунок 4-7: DMA-1

Рисунок 4-8: DMA-2

Язык кода кода:javascript
копировать
Device Drivers->SOC(System On Chip)

​ Рисунок 4-9: SID

Язык кода кода:javascript
копировать
File systems-->Miscellaneous filesystems-->

​ картина 4-10: менюconfig_spinand_ubifs

4.3 env.cfg

существовать env.cfg середина Добавить и изменить следующее значение, setargs_nand_ubi Первый copy одна порция setargs_nand Затем добавьте соответствующие переменные

Рисунок 4-11: build-mkcmd

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose