写在前面

买了很多Linux开发板但是从来没有好好的进行过Linux开发(驱动,应用等)的系统学习。趁着暑假这几天的空闲,捡起一块来进行Linux的系统性学习,在这作为一个记录来记录学习过程和遇到的一些问题。

使用的开发板是旺仔的平地铲D1S开发板,使用芯片为全志Allwinner的F133B,提供的SDK的Linux版本为5.4。前期根据旺仔提供的教程进行开发学习。后续如果使用别的开发板也写在这里吧。

Linux内核的开发

Linux内核程序可以选择作为动态模块加载,这样每次编译内核程序不用替换开发板的内核固件,比较方便。

动态模块开发相关

首先要确保Linux的内核支持动态模块,主要确认的是Kernel Configuration里:

[*]Enable loadable module support
...
[*]Module unloading

将上述内容保存并编译后烧录新的固件到开发板中即可,目前使用的开发板默认配置是开启的。

动态模块程序与编译

先来一个动态模块的程序、编译模板,大概了解一下Linux的动态模块程序该怎么写,Makefile怎么写,怎么启动、怎么退出等。

首先在开发板的Linux源码的drivers下创建目录:ko_test作为模块目录,在这个项目里完整路径为:

/home/zyc/linux_work/d1s/linux-5.4/drivers/ko_test/

然后在这个目录下主要创建两个文件,ko.c和Makefile,一个是程序源文件,一个是编译文件:

// SPDX-License-Identifier: GPL-2.0

/*

 * My first linux kernel code.

 *

 * Copyright (C) 2025 Wangzai 《搞linux的旺仔》

 *

 * This module serves no practical purpose and is solely for testing purposes.

 */

  

#include <linux/kernel.h>

#include <linux/types.h>

#include <linux/module.h>

  

static int __init fcode_init(void)

{

    int ret = 0;

  

    /*

     * 打印当前函数

     */

    pr_info("===> %s running\n", __func__);

  

    return ret;

}

  

static void __exit fcode_exit(void)

{

    pr_info("===> %s running\n", __func__);

}

  

MODULE_AUTHOR("Piglet");

MODULE_LICENSE("GPL v2");

MODULE_DESCRIPTION("This is my first code");

  

module_init(fcode_init);

module_exit(fcode_exit);
CROSS_PREFIX := ~/linux_work/d1s/riscv64-wangzai-linux-gnu-gcc/bin/riscv64-unknown-linux-gnu-

KERNEL_DIR := ~/linux_work/d1s/linux-5.4/

arch := riscv

obj-m := ko.o

  

cc := $(CROSS_PREFIX)gcc

ld := $(CROSS_PREFIX)ld

  

.PHONY:all

all:

    make ARCH=$(arch)  CC=$(cc) LD=$(ld) -C $(KERNEL_DIR) M=$(shell pwd) modules V=1

  

.PHONY:clean

clean:

    make ARCH=$(arch) CC=$(cc) LD=$(ld) -C $(KERNEL_DIR) M=$(shell pwd) clean

下面对上述的文件内容做一些说明:

首先是ko.c源文件: 其中// SPDX-License-Identifier: GPL-2.0是Linux内核要求的格式。

static int __init fcode_init(void)

{

    int ret = 0;

  

    /*

     * 打印当前函数

     */

    pr_info("===> %s running\n", __func__);

  

    return ret;

}

为动态模块的初始化入口函数,当动态模块被加载,这个函数就会被调用运行。