001-驱动基础

基本概念

  • Linux kernel
  • linux_sdk.tar.gz
    • 由芯片原厂(例如:Rockchip)BSP开发人员基于 Linux kernel 开发,提供给Linux驱动开发人员。
    • 泰山派rk3566的linux sdk: tspi_linux_sdk_repo_20240131.tar.gz 是由立创开发人员写的(类似上面的BSP开发人员)
  • Linux driver
    • Linux驱动开发:在有Linux sdk的基础上进行开发,根据项目需求,决定增、删、改、调哪些外设,为应用开发人员提供驱动接口。
    • 当前学习的内容

准备工作

  • 设备与环境

    个人笔记本电脑:Windows 10;gitee;mingw64;北京迅为电子开发板rk3568资料;移动WiFi(192.168.0.3)

    Ubuntu Linux 20.4:VSCode;make;aarch64-none-linux-gnu;gitee;USB直连移动WiFi(192.168.42.133)

    Linux开发板:泰山派;gitee;移动WiFi(192.168.0.196)

  • Ubuntu Linux 20.4编译官方提供的linux_sdk.tar.gz(官方指:瑞芯微或嘉立创)

    • 个人存放路径/jnheCode/tspkfb/kernel
  • 交叉编译器环境配置

    1
    sudo vi /etc/profile
    1
    2
    3
    # 末尾添加
    # export PATH=$PATH:/usr/local/你的交叉编译器/bin
    export PATH=$PATH:/usr/local/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin

模板记住

  • 驱动模板(全文默写)

    1
    2
    3
    4
    5
    6
    7
    8
    /* 头文件 */
    /* 参数传入(可选) */
    /* 符号导出(可选) */
    /* 函数 */
    /* 模块加载 */
    /* 模块卸载 */
    /* 开源协议(可选) */
    /* 作者信息(可选) */
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    /* 头文件 */
    #include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    /* 参数传入(可选) */
    /* 符号导出(可选) */
    /* 函数 */
    static int helloworld_init(void)
    {
    printk("helloworld_init\r\n");
    return 0;
    }
    static void helloworld_exit(void)
    {
    printk("helloworld_exit\r\n");
    }
    /* 模块加载 */
    module_init(helloworld_init);
    /* 模块卸载 */
    module_exit(helloworld_exit);
    /* 开源协议(可选) */
    MODULE_LICENSE("GPL v2")
    /* 作者信息(可选) */
    MODULE_AUTHOR("jianghe")
  • Makefile模板(全文默写)

    1
    2
    3
    # 架构 交叉编译器
    # 目标 内核路径等
    # make和make clean
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 架构 交叉编译器
    ARCH = arm64
    CROSS_COMPILE = aarch64-none-linux-gnu-
    # 目标 内核路径等
    obj-m += helloworld.o
    KDIR := /jnheCode/tspkfb/kernel
    PWD ?= $(shell pwd)
    # make和make clean
    all:
    make -C $(KDIR) M=$(PWD) modules
    clean:
    make -C $(KDIR) M=$(PWD) clean
  • 加载与导出

    1
    2
    3
    insmod helloworld.ko
    lsmod
    rmmod helloworld.ko
  • 参数传入(记住思路)

    1
    2
    3
    /* 定义数据类型 */
    /* 参数传入函数(重点) */
    /* 同:驱动模板 */
    布尔型 布尔反值 字符指针 char * 短整型 无符号短整型 整型 无符号整型 长整型 无符号长整型
    bool inbool charp short ushort int uint long ulong
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /*- kernel/include/linux/moduleparam.h -*/
    #include <linux/module.h>
    /*
    * name:模块参数的名称
    * type:模块参数的数据类型
    * perm:模块参数的访问权限
    */
    module_param(name, type, perm)
    module_param_array(name, type, nump, perm)
    module_param_string(name, string, len, perm)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /*- kernel//include/linux/stat.h -*/
    #define S_IRUSR 00400 /*文件所有者可读*/
    #define S_IWUSR 00200 /*文件所有者可写*/
    #define S_IXUSR 00100 /*文件所有者可执行*/
    #define S_IRGRP 00040 /*与文件所有者同组的用户可读*/
    #define S_IWGRP 00020 /*与文件所有者同组的用户可写*/
    #define S_IXGRP 00010 /*与文件所有者同组的用户可执行*/
    #define S_IROTH 00004 /*与文件所有者不同组的用户可读*/
    #define S_IWOTH 00002 /*与文件所有者不同组的用户可写*/
    #define S_IXOTH 00001 /*与文件所有者不同组的用户可可执行*/
    1
    2
    3
    4
    # insmod helloworld.ko 参数名=参数值
    insmod parameter.ko number=100 name="topeet" para=0,1,2,3,4,5,6,7 str="itop"
    lsmod
    rmmod helloworld.ko
  • 符号导出(记住思路)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //----------------------------
    /*- kernel/include/linux/export.h -*/
    #include <linux/module.h>
    /* 定义数据类型和函数 */
    /* 导出数据类型和函数 */
    /* 同:驱动模板 */
    //----------------------------
    /* 导入(extern)数据类型和函数 */
    /* 同:驱动模板 */
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //-----------------------
    /* 定义数据类型和函数 */
    int num = 10;
    int add(int a, int b)
    {
    return (a+b);
    }
    /* 导出数据类型和函数 */
    EXPORT_SYMBOL(num);
    EXPORT_SYMBOL(add);
    /* 同:驱动模板 */
    //----------------------------
    /* 导入(extern)数据类型和函数 */
    extern int num;
    extern int add(int a, int b);
    /* 同:驱动模板 */
    1
    2
    # 加载:先依赖后模块
    # 卸载:先模块后依赖