liteOS-A study notes-4. Use memory to simulate FLASH (realize storage device startup)

1. Equipment classification:

Reprinted from the difference between character devices and block devices

(1) Character equipment:

Character devices are accessed in an orderly manner according to the character stream, such as serial ports and keyboards are all character devices. If a hardware device is accessed in a character stream, it should be attributed to a character device; conversely, if a device is accessed randomly (unordered), then it is a block device.

The file_operations structure at the core of the driver function: open read write

(2) Block device:

The devices in the system that can access fixed-size data pieces (chunks) randomly (not in order) are called block devices , and these data pieces are called blocks. For example: flash also needs to operate according to sector.

The most common block device is the hard disk. In addition, there are many other block devices such as floppy disk drives, CD-ROM drives, and flash memory. Note that they are all used by mounting the file system-this is also the general access method for block devices.

The block_operations structure at the core of the driver function: "OpenharmonyFor6ull\third_party\NuttX\include\nuttx\fs\fs.h"

Among them, the geometry structure is defined as follows "OpenharmonyFor6ull\kernel\liteos_a\fs\include\fs\fs.h"

struct geometry
{
  bool   geo_available;    /* true: The device is available */
  bool   geo_mediachanged; /* true: The media has changed since last query eg:U盘是否插拔过*/
  bool   geo_writeenabled; /* true: It is okay to write to this device */
  unsigned long long geo_nsectors;     /* Number of sectors on the device */
  size_t geo_sectorsize;   /* Size of one sector */
};

(3) Difference:

 The main difference between a character device and a block device is: when a read/write request is issued to a character device, the actual hardware I/O generally occurs immediately; while the block device is not, it uses a block of system memory as a buffer. When the process requests the device to meet the user's requirements, it will return the requested data. If it cannot, call the request function to perform the actual I/O operation. Therefore, the block device is mainly designed for slow devices such as disks to avoid excessive consumption. More CPU time to wait~~~

 The fundamental difference between these two types of devices is whether they can be accessed randomly—in other words, whether they can jump from one location to another at will when accessing the device .

 

For example: the keyboard device provides a data stream. When you type the string "fox", the keyboard driver will return this three-character data stream in exactly the same order as the input. It doesn't make sense to let the keyboard driver scramble to read strings or read other characters. Therefore, the keyboard is a typical character device, which provides a stream of characters input by the user from the keyboard. Reading the keyboard will get a character stream, first "f", then "o", finally "x", and finally the end of file (EOF). When no one is typing on the keyboard, the character stream is empty. The situation with hard disk devices is different. The drive of the hard disk device may require to read the content of any block on the disk, and then turn to read the content of other blocks, and the position of the read block on the disk does not have to be continuous , so the hard disk can be accessed randomly. Rather than being accessed in a stream, it is obviously a block device.

 

The kernel management of block devices is much more detailed than that of character devices, and the issues to be considered and the work done are much more complicated than character devices. This is because the character device only needs to control one position—the current position—and the position accessed by the block device must be able to move back and forth in different sections of the medium. So in fact, the kernel does not need to provide a special subsystem to manage character devices, but the management of block devices must have a special service subsystem. Not only is the complexity of block devices much higher than character devices, but the more important reason is that block devices have high requirements for execution performance; each additional use of the hard disk will improve the performance of the entire system, and its effect It is much greater than the doubled increase in keyboard throughput. In addition, we will see that the complexity of block devices will leave a lot of room for this optimization.

For example: In Linux, if several programs need to write to the hard disk, in fact, the ll_rw_block() function is called first, and then the hardware is operated when the number of bytes is enough.

 

 

 

  The block device is read through the system cache, not directly from the physical disk. The character device can be read directly from the physical disk without going through the system cache. (Such as keyboard, directly interrupt correspondingly)

 

The character device is a bare device. By looking at the content under ll /dev/vg00/, if it starts with a c character, it is a character device

The block device is a file device. By looking at the content under ll /dev/vg00/, if the beginning with a character b is a block device

 

2. Define the block_operations structure

The core is to implement the block_operations structure mentioned above, and each function of the structure needs to be implemented

(1) Implement the open function

(2) Implement the close function

(3) Implement the read function

Self-defined the base address/sector size/total size of the memory used to simulate flash

Read data from flash, starting address: base address + offset address of which sector;

(4) Implement the write function

(5) Realize the geometry function: set the information of the block structure, whether it is available, whether it is writable, how many sectors there are, and the size of the sector

3. Register the block_operations structure

(1) Use the register_blockdriver function to register the structure

Note: The block device should be initialized with the code in if0, that is, the function los_disk_init(), which then calls the register_blockdriver function.

Description of the input parameters of the function

 * Input Parameters:
 * path-The path to the inode to create The path to create the node
 * bops-The block driver operations structure Waiting to register the address of the block_operations structure
 * mode-Access privileges (not used) Not used
 * priv-Private, user data that will be associated with the inode.
 *
 * Returned Value:
 * Zero on success (with the inode point in'inode'); A negated errno 0 means success, negative number means failure
 * value is returned on a failure (all error values ​​returned by
 * inode_reserve):
 *

 

(2) Code call

《OpenharmonyFor6ull\vendor\nxp\imx6ull\board\board.c》

void SystemInit() function

----Call 1------->static void imx6ull_driver_init() function                  

              ------Call---->my_ramdisk_init() function                       

----Call 2----->static void imx6ull_mount_rootfs() function                

             -----Call---->mount("/dev/ramdisk", "/", "vfat", 0, NULL) function. Among them, "/dev/ramdisk" is the path above, mounted to the root directory, vfat is the file system format,

                                                                                                                        In other words, the device node of the root file system is the above device "/dev/ramdisk", which is to mount the root file system

4. Actual compilation

(1) Compile the kernel source code: make -j 16

(2) Compile the root file system: make rootfs FSTYPE=VFAT or make rootfs FSTYPE=jffs2

About the file system:

(1) Kernel startup will mount the virtual file system procfs, and various virtual devices can be registered on the virtual file system: for example: /dev/ramdisk /dev/uart

(2) Mount the real device: mount ("/dev/ramdisk",/) Once the real device is mounted, then procfs does not exist.

5. Q&A records

(1) The file system structure of liteOS-a:

[1] The source code corresponding to the init executable file is: "OpenharmonyFor6ull\kernel\liteos_a\apps\init\src\init.c"

[2] Shell executable file: implemented in kernel mode, for example, the kill command is implemented by the file "OpenharmonyFor6ull\kernel\liteos_a\kernel\base\misc\kill_shellcmd.c". The OsShellCmdKill function is called when the kill command is entered in the shell

#ifdef LOSCFG_SHELL
SHELLCMD_ENTRY(kill_shellcmd, CMD_TYPE_EX, "kill", 2, (CmdCallBackFunc)OsShellCmdKill);
#endif

(2) There is no dev directory in rootfs, but the dev directory is again after startup. Why?

The /dev directory is a virtual directory, the files mounted under dev are all virtual files, and these files correspond to the drivers

 

 

Guess you like

Origin blog.csdn.net/xiaoaojianghu09/article/details/109479729