Linux driver - compile the module into the kernel

linux driver - character device driver
linux driver - character device driver (automatically generate device node file)
linux driver - convert module Compile into kernel

The drivers introduced in the previous two sections are all in the form of modules and need to be loaded manually. This section describes how to compile the modules into the kernel.

Add C file

#include "linux/device/class.h"
#include "linux/export.h"
#include "linux/uaccess.h"
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>

#define CHRDEVBASE_NAME "chrdevbase" /* 设备名 */
#define CHRDEVBASE_NUM 1             /* 设备数目 */

static char write_buf[100];
static char read_buf[100];

static char *string_test = "kernel data this tyustli test";

typedef struct {
    
    
    dev_t dev_id;          /* 设备号 */
    struct cdev c_dev;     /* cdev */
    struct class *class;   /* 类 */
    struct device *device; /* 设备 */
    int major;             /* 主设备号 */
    int minor;             /* 次设备号 */
} new_chrdev_t;

new_chrdev_t new_chrdev;

static int chrdevbase_open(struct inode *inode, struct file *file)
{
    
    
    printk("k: chrdevbase open\r\n");

    return 0;
}

static ssize_t chrdevbase_read(struct file *file, char __user *buf,
                               size_t count, loff_t *ppos)
{
    
    
    unsigned long ret = 0;

    printk("k: chrdevbase read\r\n");
    memcpy(read_buf, string_test, strlen(string_test));

    ret = copy_to_user(buf, read_buf, count);
    if (ret == 0) {
    
    
        printk("k: read data success\r\n");
    } else {
    
    
        printk("k: read data failed ret = %ld\r\n", ret);
    }

    return ret;
}

static ssize_t chrdevbase_write(struct file *file, const char __user *buf,
                                size_t count, loff_t *ppos)
{
    
    
    unsigned long ret = 0;

    printk("k: chrdevbase write\r\n");

    ret = copy_from_user(write_buf, buf, count);
    if (ret == 0) {
    
    
        printk("k: write data success write data is: %s\r\n", write_buf);
    } else {
    
    
        printk("k: write data failed ret = %ld\r\n", ret);
    }

    return count;
}

static int chrdevbase_release(struct inode *inode, struct file *file)
{
    
    
    printk("k: chrdevbase release\r\n");

    return 0;
}

static struct file_operations chrdevbase_fops = {
    
    
    .owner = THIS_MODULE,
    .open = chrdevbase_open,
    .read = chrdevbase_read,
    .write = chrdevbase_write,
    .release = chrdevbase_release,
};

static int __init chrdevbase_init(void)
{
    
    
    int err = 0;

    err = alloc_chrdev_region(&new_chrdev.dev_id, 0, CHRDEVBASE_NUM,
                              CHRDEVBASE_NAME);
    if (err < 0) {
    
    
        printk("k: alloc chrdev region failed err = %d\r\n", err);
        return -1;
    }

    /* get major and minor */
    new_chrdev.major = MAJOR(new_chrdev.dev_id);
    new_chrdev.minor = MINOR(new_chrdev.dev_id);
    printk("k: newcheled major=%d,minor=%d\r\n", new_chrdev.major,
           new_chrdev.minor);

    new_chrdev.c_dev.owner = THIS_MODULE;
    cdev_init(&new_chrdev.c_dev, &chrdevbase_fops);
    err = cdev_add(&new_chrdev.c_dev, new_chrdev.dev_id, CHRDEVBASE_NUM);
    if (err < 0) {
    
    
        printk("k: cdev add failed err = %d\r\n", err);
        goto out;
    }

    new_chrdev.class = class_create(CHRDEVBASE_NAME);
    if (IS_ERR(new_chrdev.class)) {
    
    
        printk("k: class create failed\r\n");
        goto out_cdev;
    }

    new_chrdev.device = device_create(new_chrdev.class, NULL, new_chrdev.dev_id,
                                      NULL, CHRDEVBASE_NAME);
    if (IS_ERR(new_chrdev.device)) {
    
    
        printk("k: device create failed\r\n");
        goto out_class;
    }

    printk("k: base module init\r\n");

    return 0;

out_class:
    class_destroy(new_chrdev.class);
out_cdev:
    cdev_del(&new_chrdev.c_dev);
out:
    unregister_chrdev_region(new_chrdev.dev_id, CHRDEVBASE_NUM);

    return err;
}

static void __exit chrdevbase_exit(void)
{
    
    
    device_destroy(new_chrdev.class, new_chrdev.dev_id);
    class_destroy(new_chrdev.class);
    cdev_del(&new_chrdev.c_dev);
    unregister_chrdev_region(new_chrdev.dev_id, CHRDEVBASE_NUM);

    printk("k: base module exit!\r\n");
}

module_init(chrdevbase_init);
module_exit(chrdevbase_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("tyustli");
MODULE_INFO(intree, "Y"); /* loading out-of-tree module taints kernel */

Copy the module source code in the previous section to the drivers/char directory
Insert image description here

Modify Makefile

Insert image description here

  • CONFIG_MY_MODULE is a configuration macro. If this macro is defined, it is obj-y += my_module.o
  • my_module.o is to add a C file yourself, just write .o here

Modify Kconfig file

Insert image description here

  • MakefileThe file relies on the CONFIG_MY_MODULE macro, so just define the MY_MODULE macro here.

Module enable

Insert image description here
空格即可选中

Shift + ?Help information can be displayed
Insert image description here

Kernel boot log

workingset: timestamp_bits=30 max_order=17 bucket_order=0
squashfs: version 4.0 (2009/01/31) Phillip Lougher
jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
9p: Installing v9fs 9p2000 file system support
io scheduler mq-deadline registered
io scheduler kyber registered
io scheduler bfq registered
k: newcheled major=250,minor=0
k: base module init
OF: graph: no port node found in /bus@40000000/motherboard-bus@40000000/iofpga@7,00000000/i2c@16000/dvi-transmitter@60
sii902x 0-0060: supply iovcc not found, using dummy regulator
sii902x 0-0060: supply cvcc12 not found, using dummy regulator
simple-pm-bus bus@40000000:motherboard-bus@40000000:iofpga@7,00000000: Failed to create device link (0x180) with dcc:tcrefclk
simple-pm-bus bus@40000000:motherboard-bus@40000000:iofpga@7,00000000: Failed to create device link (0x180) with dcc:tcrefclk
physmap-flash 40000000.flash: physmap platform flash device: [mem 0x40000000-0x43ffffff]
40000000.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
k: newcheled major=250,minor=0
k: base module init

Automatically printed out

reference

  • https://www.rt-thread.org/document/site/#/development-tools/build-config-system/Kconfig

Guess you like

Origin blog.csdn.net/tyustli/article/details/134255158