十一.编译uboot和Linux内核
1.将6818GEC.tar.gz和kernel20190724.tar.gz拷贝到Ubuntu的非共享目录
解压源代码:
tar -xzvf 6818GEC.tar.gz
使用kernel20190724.tar.gz替换6818GEC目录中的内核(黑色LCD底板才替换)
目录介绍:
GEC6818uboot ---------------- uboot源码
kernel ----------------------------- 内核源码
mk --------------------------------- 编译uboot和内核的脚本
out --------------------------------- 编译uboot和内核镜像文件的输出目录
prebuilts -------------------------- 编译工具链
linux -------------------------------- 三星提供的针对s5p6818的参考源码
prototype -------------------------- s5p6818平台硬件驱动的参考代码
2.编译uboot和内核(在6818GEC目录下执行)
编译uboot --------------- ./mk -u
编译内核 ---------------- ./mk -k
编译成功后镜像文件在out/release目录下
注意:如果编译内核最后报make_ext4fs不存在,需要安装安装
sudo apt-get update
sudo apt-get install lib32c-dev lib32stdc++6
3.Linux内核的配置
内核配置用来选择将哪些代码编译进内核
通过make menuconfig进入内核配置界面
可能出现的错误:
(1)出现缺少ncurses库的错误,需要安装ncurses
sudo apt-get update
sudo apt-get install ncurses-dev
(2)如果窗口太小,字体太大也会报错
最大化窗口,调小字体
内核的配置界面通过上下方向键移动光标定位的条目,底下三个按键通过左右方向键移动,如果要执行选中的按钮,直接按回车键
回车选中带箭头的条目可以进入子菜单,双击Esc返回上一级
带括号的条目可以选中,定位到该条目通过空格键选中/取消选中
(3)配置内核支持虚拟终端
Device Drivers --->
Character devices --->
[*] Virtual terminal
[ ] Enable character translations in console
[*] Support for console on virtual terminal (NEW)
[*] Support for binding and unbinding console drivers
保存退出
完成配置之后覆盖配置文件
cp .config arch/arm/configs/GEC6818_defconfig
重新编译内核
练习:
完成uboot和内核的编译,以及内核的配置
4.烧写uboot和内核
将编译出来的uboot镜像和内核镜像去替换刷机工具包中的uboot和内核镜像,再用前面介绍的刷机方法刷机。
只烧写内核
一.Linux驱动
Linux驱动属于内核的一部分,学习驱动开发时将驱动设计为内核模块,内核模块是一种可以在系统运行时加载和卸载的机制。
1.内核编程的注意事项
1.不能使用C标准库和C标准头文件
2.使用GNU C
3.没有内存保护机制
4.不能处理浮点运算
5.注意并发互斥和可移植性问题
2.内核模块的编写
需要包含头文件
#include <linux/init.h>
#include <linux/module.h>
必须实现加载函数和卸载函数
//加载函数 ---------- 模块加载自动调用
int xxx(void)
{
//......
return 0;//返回0表示加载成功
}
//卸载函数 ----------- 模块卸载时自动调用
void yyy(void)
{
//......
}
使用内核提供的宏来修饰加载函数和卸载函数
module_init(xxx);//修饰加载函数
module_exit(yyy);//修饰卸载函数
注:内核中打印函数叫printk,用法和printf几乎一样。
模块许可证:
在编写模块时必须加上模块许可证,防止内核被污染,造成某些功能无法使用。
MODULE_LICENSE("GPL");//GPL模块许可证
模块源代码:
#include <linux/init.h>
#include <linux/module.h>
//加载函数
int hello_init(void)
{
printk(KERN_WARNING"hello GEC!\n");
return 0;
}
//卸载函数
void hello_exit(void)
{
printk(KERN_WARNING"byebye GEC!\n");
}
module_init(hello_init);
module_exit(hello_exit);
//模块许可证
MODULE_LICENSE("GPL");
3.内核模块的编译
内核模块的编译使用对应内核的编译方法来编译(内核源码必须编译过),使用类似于以下格式的Makefile来编译模块
#内核源代码目录
KERNEL_DIR=/home/gec/GZFX2108/driver/6818GEC/kernel
#定义编译工具链路径
CROSS_PATH=/home/gec/GZFX2108/driver/6818GEC/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-
#编译成模块
obj-m += first.o
#编译命令
default:
$(MAKE) CROSS_COMPILE=$(CROSS_PATH) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod* *.ord* *.sy* .*cmd .tmp*
使用make命令进行编译,生成的模块文件的后缀为.ko
4.模块的使用
Linux命令:
insmod ------------- 加载模块
insmod 模块文件路径
rmmod -------------- 卸载模块
rmmod 模块名
lsmod -------------- 查看已加载的模块
lsmod
练习:
实现一个内核模块的编写,编译和使用,修改printk中的数字(0~7),测试哪些数字可以打印出来