Linux driver development study notes [1]: character device driver development

table of Contents

1. Character device driver

Two, character device driver development steps

1. Compile the character device driver module

2. Loading and unloading of the drive module

3. Specific implementation of character device registration and cancellation

4. Realize the specific operation function of the device

Three, test APP writing and testing


1. Character device driver

Character devices are the most basic type of device drivers in Linux drivers. A character device is a device that reads and writes bytes one by one, and reads and writes data in a sequential order. For example, our most common lighting, buttons, IIC, SPI, LCD, etc. are all character devices, and the drivers of these devices are called character device drivers. Linux application calls to the driver

 

The application program runs in the user space, and the Linux driver is part of the kernel, so the driver runs in the kernel space. When we want to implement operations on the kernel in user space, such as using the open function to open the /dev/led driver, because user space cannot directly operate on the kernel, we must use a method called "system call" to implement slave users The space is "trapped" into the kernel space, so that the operation of the underlying driver can be realized. These functions such as open, close, write and read are provided by the C library. In Linux systems, system calls are part of the C library. When we call the open function, the process is as shown in the figure

 

Two, character device driver development steps

Things to note when writing a driver:

1. The Linux kernel source code is needed when compiling the driver! Therefore, unzip the linux kernel source code and compile the linux kernel source code. Get zImage and .dtb. You need to use the compiled zImage and dtb to start the system.

2. Boot from the SD card, and uboot is burned to the SD card. uboot obtains zimage and dtb from ubuntu via tftp, and rootfs is also mounted via nfs.

3. Set up bootcmd and bootargs

setenv bootargs 'console=ttymxc0,115200
  root=/dev/nfs rw
  nfsroot=192.168.199.158:/home/denghengli/linux/nfs/rootfs
  ip=192.168.199.20:192.168.199.158:192.168.199.1:255.255.255.0::eth0:off'
setenv bootcmd ‘tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;’

4. Put the compiled .ko file in the /lib/modules/<kernel-version> directory in the root file system .

1. Compile the character device driver module

Step 1: Create a VSCode project

Step 2: Add the header file path for VSCode

The path of the header file in the source code. Open VSCode, press Crtl+Shift+P” to open the VSCode console, then enter C/C++: Edit configurations(JSON)”, open the C/C++ edit configuration file, after opening, it will automatically generate a name in the .vscode directory It is the file of c_cpp_properties.json, includePath represents the path of the header file, you need to add the path of the header file in the Linux source code

"${workspaceFolder}/**", 
"/home/denghengli/linux/IMX6ULL/linux/nxptoalpha_linux/include", 
"/home/denghengli/linux/IMX6ULL/linux/nxptoalpha_linux/arch/arm/include", 
"/home/denghengli/linux/IMX6ULL/linux/nxptoalpha_linux/arch/arm/include/generated/"

Step 3: Create a new chardevbase.c character driver file and write a Makefile

KERNELDIR := /home/denghengli/linux/IMX6ULL/linux/nxptoalpha_linux

CURRENT_PATH := $(shell pwd)
#obj-m表示将 chardevbase.c这个文件编译为chardevbase.ko模块。
obj-m := chardevbase.o

build: kernel_modules

#具体的编译命令,后面的 modules表示编译模块,-C表示将当前的工作目录切
#换到指定目录中,也就是 KERNERLDIR目录。 M表示模块源码目录,“ make modules”命令
#中加入 M=dir以后程序会自动到指定的 dir目录中读取模块的源码并将其编译为 .ko文件。
kernel_modules :
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules

clean:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

After completion, input make to compile the dynamic module file of chardevbase.ko

2. Loading and unloading of the drive module

After the kernel is started, enter the root file system and use insmod or modprobe to load the driver. The insmod command cannot solve the dependency of the module. Modprobe will analyze the dependency of the module, and then load all the dependent modules of the module into the kernel, so modprobe The command is smarter than insmod; by default, the modprobe command will search for modules in the /lib/modules/<kernel-version> directory under the root file system . When loading a new module with modprobe, you need to call the depmod command first. Use the command rmmod to remove the driver.

比如加载chardevbase.ko 
insmod chardevbase.ko 

depmod modprobe chardevbase.ko 
rmmod chardevbase

 

After the driver module is loaded successfully, you can use lsmod to check it.

lsmode

Uninstall the module using the rmmod command

3. Specific implementation of character device registration and cancellation

The loading and unloading of the driver module is actually registering and unregistering the character device with the system.

1, we need to load the module function chardevbase_init use function register_chrdev register a character device to the system, uninstall the driver when the need to write off the character in front of a registered device, use the function unregister_chrdev in chardevbase_exit cancellation of character device

2. The Linux kernel divides the device number into two parts: the major device number and the minor device number. The major device number occupies the first 12 digits, and the minor device number occupies the lower 20 digits. Operation function or macro of device number:

从dev_t获取主设备号和次设备号:MAJOR(dev_t),MINOR(dev_t)
使用主设备号和次设备号构成dev_t:MKDEV(major,minor)

If you use statically assigned device numbers, you need to check which device numbers are used by the current system when setting, to avoid conflicts, use the command: 

cat /proc/devices

3. Add LICENSE and author information

/*
    模块输入与输出
 */
static int __init chardevbase_init(void)
{
    int ret = 0;
    printk("chardevbase_init\r\n");

    /*注册字符设备*/
    ret = register_chrdev(CHARDEVBASE_MAJOR, CHARDEVBASE_NAME, &chardevbase_fops);
    if (ret < 0){
        printk("chardevbase init failed!\r\n");
    }
    return 0;
}

static void __exit chardevbase_exit(void)
{
    printk("chardevbase_exit\r\n");

    /*卸载字符设备*/
    unregister_chrdev(CHARDEVBASE_MAJOR, CHARDEVBASE_NAME);
}

module_init(chardevbase_init); /*入口*/
module_exit(chardevbase_exit); /*出口*/

MODULE_AUTHOR("denghengli");
MODULE_LICENSE("GPL");

4. Realize the specific operation function of the device

After registering the character device with the system, you need to add device-related file_operations by yourself

/*
 字符设备操作集合
*/
static struct file_operations chardevbase_fops = {
    .owner = THIS_MODULE,
    .open = chardevbase_open,
    .release = chardevbase_release,
    .read = chardevbase_read,
    .write = chardevbase_write,
};

 

Three, test APP writing and testing

When writing a driver, you can use the man manual that comes with Linux to view the usage of the function. The usage method is man [section] [command], such as man 1 ls

1、Standard commands (标准命令)
2、System calls (系统调用)
3、Library functions (库函数)
4、Special devices (设备说明)
5、File formats (文件格式)
6、Games and toys (游戏和娱乐)
7、Miscellaneous (杂项)
8、Administrative Commands (管理员命令)
9 其他(Linux特定的), 用来存放内核例

1. Write the chardevbaseAPP.c application test program, compile it into a chardevbaseAPP executable file, and copy it to rootfs/lib/modules/4.1.15/

arm-linux-gnueabihf-gcc chardevbaseAPP.c -o chardevbaseAPP 
sudo cp chardevbaseAPP /home/denghengli/linux/nfs/rootfs/lib/modules/4.1.15/ -f

2. Load the driver module and check the device number of the chardevbase driver

modprobe chardevbase.ko 
cat /proc/devices

3. Create a device node file

The successful loading of the driver needs to create a corresponding device node file in the /dev directory. The application program completes the operation of the specific device by operating the device node file. After loading the driver module, it will be automatically created in /dev, but it has not been registered yet, so first manually register one. If chardevbaseAPP wants to read and write the chardevbase device, read and write directly on /dev/chardevbase. The file equivalent to /dev/chardevbase is the realization of the chardevbase device in user space.

/*其中“ mknod”是创建节点命令 ,“/dev/chardevbase”是要创建的节点文件 
*c表示这是个字符设备,200是设备的主设备号 0”是设备的次设备号。
*/

mknod /dev/chardevbase c 200 0

4. Execute the test program

./chardevbaseAPP /dev/chardevbase

 

 

 

 

Guess you like

Origin blog.csdn.net/m0_37845735/article/details/106892621