Linux MTD system analysis,

Publisher:温柔阳光Latest update time:2024-07-19 Source: cnblogsKeywords:Linux Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

MTD, Memory Technology Device, is a memory technology device. In the Linux kernel, the MTD layer is introduced to provide a unified interface for NOR FLASH and NAND FLASH devices. MTD isolates the file system from the underlying FLASH memory.

As shown in the figure above, MTD devices can usually be divided into four layers, from top to bottom: device node, MTD device layer, MTD original device layer, and hardware driver layer.


Flash hardware driver layer: The Flash hardware driver layer is responsible for the read, write and erase operations of the Flash hardware. The driver of the Nand Flash chip of the MTD device is in the drivers/mtd/nand/ subdirectory, and the Nor Flash chip driver is in the drivers/mtd/chips/ subdirectory.


MTD original device layer: The data structure used to describe the MTD original device is mtd_info, which defines a large amount of data and operation functions about MTD. Among them, mtdcore.c: MTD original device interface related implementation, mtdpart.c: MTD partition interface related implementation.


MTD device layer: Based on the MTD original device, the Linux system can define MTD block devices (major device number 31) and character devices (device number 90). Among them, mtdchar.c: MTD character device interface related implementation, mtdblock.c: MTD block device interface related implementation.


Device node: Create an MTD block device node (major device number 31) and an MTD character device node (major device number 90) in the /dev subdirectory through mknod. You can access the MTD character device and block device by accessing this device node.


MTD data structure:


1. The Linux kernel uses the mtd_info structure to represent the MTD raw device, which defines a lot of data and operation functions about MTD (as will be seen later). All mtd_info structures are stored in the mtd_table structure data. In /drivers/mtd/mtdcore.c:



struct mtd_info *mtd_table[MAX_MTD_DEVICES];

2. The Linux kernel uses the mtd_part structure to represent partitions, where the mtd_info structure members are used to describe the partition. Most members are determined by its master partition mtd_part->master, and various functions also point to the corresponding functions of the master partition.




struct mtd_part {

struct mtd_info mtd; /* Partition information, mostly determined by the master*/

struct mtd_info *master; /* master partition of the partition*/

uint64_t offset; /* Partition offset address*/

int index; /* Partition number (this field does not exist after Linux 3.0) */

struct list_head list; /* Link mtd_part into a linked list mtd_partitons */

int registered;

};

The main members of the mtd_info structure put important data in the front and less important data in the back for easy observation.




struct mtd_info {

u_char type; /* MTD type, including MTD_NORFLASH, MTD_NANDFLASH, etc. (refer to mtd-abi.h) */

uint32_t flags; /* MTD attribute flags, MTD_WRITEABLE, MTD_NO_ERASE, etc. (see mtd-abi.h) */

uint64_t size; /* size of mtd device*/

uint32_t erasesize; /* The erase unit size of the MTD device, for NandFlash it is the size of the Block*/

uint32_t writesize; /* Write size, bytes for norFlash, one page for nandFlash*/

uint32_t oobsize; /* OOB bytes*/

uint32_t oobavail; /* Number of available OOB bytes */

unsigned int erasesize_shift; /* default is 0, not important */

unsigned int writesize_shift; /* default is 0, not important*/

unsigned int erasesize_mask; /* default is 1, not important*/

unsigned int writesize_mask; /* Default is 1, not important*/

const char *name; /* name, not important*/

int index; /* index number, not important*/

int numeraseregions; /* usually 1 */

struct mtd_erase_region_info *eraseregions; /* Variable erase region*/

void *priv; /* Device private data pointer, for NandFlash it refers to the nand_chip structure*/

struct module *owner; /* Usually set to THIS_MODULE */

/* Erase function */

int (*erase) (struct mtd_info *mtd, struct erase_info *instr);

/* Read and write flash functions*/

int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);

int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);

/* Read and write Flash functions with oob*/

int (*read_oob) (struct mtd_info *mtd, loff_t from,

struct mtd_oob_ops *ops);

int (*write_oob) (struct mtd_info *mtd, loff_t to,

struct mtd_oob_ops *ops);

int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);

int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);

int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);

int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);

int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);

int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);

int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);

int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);

/* Sync */

void (*sync) (struct mtd_info *mtd);

/* Chip-supported device locking */

int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);

int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);

/* Power management function */

int (*suspend) (struct mtd_info *mtd);

void (*resume) (struct mtd_info *mtd);

/* Bad block management function*/

int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);

int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);

void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);

unsigned long (*get_unmapped_area) (struct mtd_info *mtd,

unsigned long len,

unsigned long offset,

unsigned long flags);

struct backing_dev_info *backing_dev_info;

struct notifier_block reboot_notifier;  /* default mode before reboot */

/* ECC status information */

struct mtd_ecc_stats ecc_stats;

int subpage_sft;

struct device dev;

int usecount;

int (*get_device) (struct mtd_info *mtd);

void (*put_device) (struct mtd_info *mtd);

};

The read(), write(), read_oob(), write_oob(), and erase() functions in the mtd_info structure are the main functions that the MTD device driver needs to implement. Fortunately, Linux experts have helped us implement a set of mtd_info member functions suitable for most FLASH devices.



If the MTD device has only one partition, use the following two functions to register and unregister the MTD device.



int add_mtd_device(struct mtd_info *mtd)

int del_mtd_device (struct mtd_info *mtd)

If the MTD device has other partitions, use the following two functions to register and unregister the MTD device.


int add_mtd_partitions(struct mtd_info *master,const struct mtd_partition *parts,int nbparts)

int del_mtd_partitions(struct mtd_info *master)

The mtd_partition structure represents the partition information




struct mtd_partition {

char *name; /* Partition name, such as TQ2440_Board_uboot, TQ2440_Board_kernel, TQ2440_Board_yaffs2 */

uint64_t size; /* Partition size*/

uint64_t offset; /* Partition offset value*/

uint32_t mask_flags; /* Mask flag, not important*/

struct nand_ecclayout *ecclayout; /* OOB layout */

struct mtd_info **mtdp;     /* pointer to store the MTD object */

};

Among them, the nand_ecclayout structure is:

struct nand_ecclayout {

__u32 eccbytes; /* Number of ECC bytes */

__u32 eccpos[64]; /* ECC checksum is stored in the OOB area*/

__u32 oobavail;

/* Number of available OOB bytes in addition to the ECC checksum*/

struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];

};

For more information about the nand_ecclayout structure instance, please refer to the nand_oob_8, nand_oob_16, and nand_oob_64 instances in drivers/mtd/nand/nand_base.c.

MTD device layer:



MTD character device interface:


/drivers/mtd/mtdchar.c file implements the MTD character device interface, through which you can directly access the Flash device. Like the previous character driver, you can read and write Flash through open(), read(), write(), and ioctl() in the file_operations structure. You can get Flash device information, erase Flash, read and write NAND OOB, get OOB layout, and check NAND bad blocks through a series of IOCTL commands (MEMGETINFO, MEMERASE, MEMREADOOB, MEMWRITEOOB, MEMGETBADBLOCK IOCRL)


MTD block device interface:


The /drivers/mtd/mtdblock.c file implements the MTD block device interface. The main principle is to map the data in the erase block of Flash in the memory, then modify it, and finally erase the block on Flash and write the mapped block in the memory to the Flash block. The whole process is called the read/modify/erase/rewrite cycle. However, this is unsafe. When the following operation sequence occurs, read/modify/erase/poweroff, the data of this block will be lost.

MTD hardware driver layer:


The Linux kernel implements a general NAND driver (/driver/mtd/nand/nand_base.c) under the MTD layer, so the chip-level NAND driver no longer needs to implement member functions such as read(), write(), read_oob(), and write_oob() in the mtd_info structure.


MTD uses nand_chip to represent a NAND FLASH chip. This structure contains a series of underlying mechanisms such as Nand Flash address information, read and write methods, ECC mode, hardware control, etc.



struct nand_chip {

void __iomem *IO_ADDR_R; /* Read 8-bit I/O line address*/

void __iomem *IO_ADDR_W; /* Write 8-bit I/O line address*/

/* Read a byte from the chip */

uint8_t (*read_byte)(struct mtd_info *mtd);

[1] [2]
Keywords:Linux Reference address:Linux MTD system analysis,

Previous article:OK6410 DMA bare metal summary
Next article:Analysis of Linux serial port driver

Recommended ReadingLatest update time:2024-11-16 09:30

3.4. Embedded Linux kernel production
We have already made uboot, and the next step is to make the kernel. First enter the kernel source code and execute make distclean to clear the files generated by the previous compilation. Note that there is an additional condition ARCH=arm when configuring the kernel. After pr
[Microcontroller]
3.4. Embedded Linux kernel production
Path memory tracking car based on ARM and Linux
introduction Smart cars are an emerging comprehensive technology that has developed in recent years. They have been widely used in the military field and are becoming increasingly popular in production and life . At present, there are two types of autonomous movement of smart cars: tracking and obstacle avoidance.
[Microcontroller]
Path memory tracking car based on ARM and Linux
Linux-2.6.32 transplanted on mini2440 development board transplanted watchdog driver
1 Configure the watchdog driver in the kernel. The Linux-2.6.32.2 kernel has a perfect watchdog driver for S3C2440. We only need to configure it and we can use it. Execute: make menuconfig in the kernel source code directory, enter the kernel configuration main menu, and select the followin
[Microcontroller]
OK6410A Development Board (VIII) 67 linux-5.11 OK6410A Implementation of per-cpu linux kernel synchronization mechanism
What is the problem being solved? The race condition caused by SMP // Actually, it avoids the race condition of SMP, because each CPU has a variable with the same name, and there will be no race condition between SMPs Cannot solve race conditions caused by other reasons Other points It only makes sense under CONFIG_
[Microcontroller]
LCD device driver in Linux (4) - based on s3c6410 platform
In this article, we will talk about the parts related to specific TFT displays. When we encounter a specific display, we should set what parameters and how to set these parameters. 1. The s3cfb_WXCAT43.c (linux2.6.28driversvideosamsung) file contains the settings for the specific monitor. Let's look at it section by
[Microcontroller]
LCD device driver in Linux (4) - based on s3c6410 platform
ARM-Linux development steps
I got a YC2440 (s3c2440) development board. After a few days of study, I have some understanding of the arm-linux system development steps. Taking the development of this development board as an example, the arm-linux development work is roughly divided into 4 parts: 1. Hardware 2. Bootloader 3. Kernel 4. File syste
[Microcontroller]
Linux-3.6.6 transplantation based on S3C2440 - LED driver
Many drivers in the current Linux version are based on the device model, and LED is no exception. Simply put, the device model is that the system thinks that all devices are connected to the bus, and to make the device work, the corresponding driver is needed. The device model will generate a virtual file s
[Microcontroller]
Compiling Mplayer under Linux - S3C6410
mplayer cross-compilation process: GCC version: Sourcery G++ 4.2.1 Target machine: S3C6410 ARM core is arm1176jzf-s (GCC has -mcpu=arm1176jzf-s) Host: Ubuntu 8.04 Tips: mplayer has automatic configure, no need to write Make manually~ Pay attention to the difference between GCC parameters and confi
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号