搭建orangepi5plus的开发环境可谓是一波三折,为此我总结了一个脚本文件全自动搭建环境
buiild_env_5p_driver.sh 文件内容
#!/bin/sh
## 1.创建文件夹
ROOTPATH=$(pwd)/orangepi-5plus
mkdir -p ${ROOTPATH} && cd ${ROOTPATH}
## 2.下载交叉编译工具
wget https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/_toolchain/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu.tar.xz
tar xf gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu.tar.xz
## 3.下载内核源码
git clone --depth=1 -b orange-pi-5.10-rk3588 https://github.com/orangepi-xunlong/linux-orangepi/
cd ${ROOTPATH}/linux-orangepi/
## 4.生成内核编译脚本
cat > make.sh << EOF
#!/bin/sh
## 0.clean
make ARCH=arm64 distclean
## 1.config
make -j 24 ARCH=arm64 CROSS_COMPILE=\${CROSS_COMPILE} rockchip_linux_defconfig
## 2.cross compile Image
make -j 24 ARCH=arm64 CROSS_COMPILE=\${CROSS_COMPILE} Image
## 3.cross compile DTB
make -j 24 ARCH=arm64 CROSS_COMPILE=\${CROSS_COMPILE} rockchip/rk3588-orangepi-5-plus.dtb
## 4.cross compile modules
make -j 24 ARCH=arm64 CROSS_COMPILE=\${CROSS_COMPILE} modules
sync
exit 0
EOF
chmod +x make.sh
sync
## 5.编译内核源码
export CROSS_COMPILE=$(realpath ${ROOTPATH}/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-)
export KERNEL_SRC=$(realpath ${ROOTPATH}/linux-orangepi/)
./make.sh
cd ${ROOTPATH}
## 6.编译外部驱动
mkdir -p ${ROOTPATH}/drivers/helloworld/ && cd ${ROOTPATH}/drivers/helloworld/
### 6.1 生成Makefile文件
cat > Makefile << EOF
#obj-m则表示该文件要作为模块编译,目标编译成.ko模块。
obj-m := helloworld.o
ARCH=arm64
CC=\$(CROSS_COMPILE)gcc
PWD := \$(shell pwd)
#shell pwd会取得当前工作路径
all:
XXX@\$(MAKE) -C \$(KERNEL_SRC) M=\$(PWD) modules ARCH=\$(ARCH) CROSS_COMPILE=\$(CROSS_COMPILE)
clean:
XXX@rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions *.order *.symvers *.mod
.PHONY:clean
EOF
sed -i "s/XXX/\t/g" Makefile
sync
### 6.2 驱动程序源码
cat > helloworld.c << EOF
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#define DRV_VERSION ("V1.0.0")
#define DEV_NAME ("helloworld")
static char buffer[128] = {0};
/* 读sys文件,例如cat /sys/class/misc/helloworld/drv_version */
static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", DRV_VERSION);
}
//定义一个名字为drv_version的设备属性文件
static DEVICE_ATTR(drv_version, S_IRUSR, version_show, NULL);
/* 读sys文件,例如cat /sys/class/misc/helloworld/buffer */
static ssize_t sys_buffer_write_usage(struct device *dev, struct device_attribute *attr, char *buf)
{
#if 1
return sprintf(buf, "%s \n", buffer);
#else
return sprintf(buf, "Usage:\n"
"\t[echo \"xxx\" > /sys/class/%s/%s/buffer] \n",
dev->class->name, dev_name (dev));
#endif
}
/* 写sys文件,例如 echo "xxx" > /sys/class/misc/helloworldister_rdwr/buffer */
static ssize_t sys_buffer_write_ops(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
memset (buffer, 0, sizeof (buffer));
count = snprintf (buffer, sizeof (buffer), "%s", buf);
return count;
}
//定义一个名字为 buffer 的设备属性文件
static DEVICE_ATTR(buffer, S_IWUSR|S_IRUSR, sys_buffer_write_usage, sys_buffer_write_ops);
static int helloworld_open(struct inode * inode, struct file * file)
{
return 0;
}
static int helloworld_close(struct inode * inode, struct file * file)
{
return 0;
}
static long helloworld_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
return 0;
}
static struct file_operations helloworld_fops = {
.owner = THIS_MODULE,
.compat_ioctl = helloworld_ioctl,
.unlocked_ioctl = helloworld_ioctl,
.open = helloworld_open,
.release = helloworld_close
};
static struct miscdevice helloworld_dev = {
MISC_DYNAMIC_MINOR,//255
DEV_NAME,
&helloworld_fops,
};
static int __init helloworld_module_init(void)
{
int ret = -1;
struct device *dev = NULL;
ret = misc_register(&helloworld_dev);
if (ret)
{
printk("[%s]ERROR: could not register %s devices\n", DEV_NAME, DEV_NAME);
return ret;
}
// printk ("[%s] PAGE_SIZE=0X%lX \n", DEV_NAME, PAGE_SIZE);
dev = helloworld_dev.this_device;
//在设备目录下创建一个drv_version属性文件
if(sysfs_create_file(&(dev->kobj), &dev_attr_drv_version.attr)) {
printk ("[%s] sysfs_create_file error!\n", DEV_NAME);
//return -1;
}
//在设备目录下创建一个buffer属性文件
if(sysfs_create_file(&(dev->kobj), &dev_attr_buffer.attr)) {
printk ("[%s] sysfs_create_file error!\n", DEV_NAME);
// return -1;
}
printk ("[%s] load %s successfully! version is %s\n", DEV_NAME, DEV_NAME, DRV_VERSION);
return 0;
}
static void __exit helloworld_module_exit(void)
{
struct device *dev = helloworld_dev.this_device;
sysfs_remove_file (&(dev->kobj), &dev_attr_buffer.attr);
sysfs_remove_file (&(dev->kobj), &dev_attr_drv_version.attr);
misc_deregister(&helloworld_dev);
printk("[%s] rmmod %s ok!\n", DEV_NAME, DEV_NAME);
}
module_init(helloworld_module_init);
module_exit(helloworld_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("XXX");
MODULE_DESCRIPTION("Helloworld driver");
EOF
sync
## 6.3 编译驱动
make clean && make
sync
exit 0
把这个文件放在任意目录下,然后执行:chmod +x buiild_5p_driver.sh && ./buiild_5p_driver.sh 即可。在运行前请确保能打开github(建议使用翻墙软件)
中图不报错的话就可以了,然后在makefile中把交叉编译链和内核路径修改一下。有问题请加微信:lingtu15679003191