小白自制Linux开发板 三. Linux内核与文件系统移植
上一篇完成了uboot的移植,但是想要愉快的在开发板上玩耍还需要移植Linux内核和文件系统。
1.Linux内核
事实上对于F1C100S/F1C200S,Linux官方源码已经对licheepi nano进行支持。所以我们完全可以通过licheepi nano的配置文件进行移植。
1.1. 下载内核源码
进入Linux系统官网:
这里面列出的都是一些主要版本,如主线版本,上时间支持版本,个人推荐使用最新的长时间支持版本(5.10.69)。但是因为我这个项目是在参考一位大神的文档的基础上构建的,所以使用的是5.7.1版本,接下来就给一个选择其他版本的方式。
选择任意一项点击 [browse]
在新打开页面选择 【summary】点击【tag】中的【…】切换下载
如果想要直接下载5.7.1版本,请直接使用下面的连接
https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.7.1.tar.gz
下载后完成后,将代码复制到Ubuntu虚拟机并解压源码。
1.2.配置编译
与上一篇中编译u-boot一样,我们也需要配置对Linux编译进行配置:
- 指定架构类型
- 指定交叉编译工具
- 项目配置
指定架构,就这个很好理解,就是指定CPU类型,就是配置为Arm就行,交叉编译工具即为上一篇已经安装好的编译工具。
用VS打开Linux内核代码,找到Makefile文件:
修改如下配置:
ARCH ?= arm
CROSS_COMPILE ?=arm-linux-gnueabi-
如果没找到ARCH 或 CROSS_COMPILE字段,自己手动添加也行,如下图所示:
事实上这两个字段可以不用指定,在进行make的时候加上对应的参数就行,这里为了避免麻烦,所以直接放到了makefile文件中
接下来就是指定项目配置了,这个操作就是让Linux内核认F1C100S/F1C200S这颗soc。
进入内核源码中的arch/arm/configs目录中,可以看到有很多开发板的配置文件,其中sunxi_defconfig是全志的配置文件,但是该配置文件非常不全,需要额外配置大量的选项,一般选项多大上千个,这里先使用licheepi_nano的配置文件。
https://files.cnblogs.com/files/twzy/linux-licheepi_nano_defconfig.zip
下载该文件,解压出linux-licheepi_nano_defconfig,然后将其放到arch/arm/configs/目录下
然后通过终端进入Linux-5.7.1根目录,输入命令:
make menuconfig
进入图形配置界面,如图所示:
该界面和u-boot配置一样,所以操作方式也是一样的,上下键移动选项,使用空格键进行选中或取消选择,同样通过空格键或回车键,进入子选项配置,通过Tab键选择保存和退出即可返回上级菜单或命令行界面,也可以直接双击Esc键返回上级目录。
1.3 配置TF卡设备树信息
我们在完成内核配置后还需要配置TF卡的设备树配置,否则即便是能正常运行内核,在加载文件系统的时候还是会有问题,在这里配置很简单:
在linux-5.7.1/arch/arm/boot/dts 目录下,分别修改suniv-f1c100s.dtsi、suniv-f1c100s-licheepi-nano.dts 两个文件(记住这两个文件、以后我们修改的地方多了^_^)
修改suniv-f1c100s.dtsi文件
在soc->pio 下添加如下代码
mmc0_pins: mmc0-pins {
pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
function = "mmc0";
};
soc下添加如下代码
mmc0: mmc@1c0f000 {
compatible = "allwinner,suniv-f1c100s-mmc",
"allwinner,sun7i-a20-mmc";
reg = <0x01c0f000 0x1000>;
clocks = <&ccu CLK_BUS_MMC0>,
<&ccu CLK_MMC0>,
<&ccu CLK_MMC0_OUTPUT>,
<&ccu CLK_MMC0_SAMPLE>;
clock-names = "ahb",
"mmc",
"output",
"sample";
resets = <&ccu RST_BUS_MMC0>;
reset-names = "ahb";
interrupts = <23>;
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
如图,图中的配置可能与读者实际内容不一致,这是因为我改了很多东西,忽略即可,只需要关注红色框中的内容即可。
修改suniv-f1c100s-licheepi-nano.dts文件,添加如下代码
&mmc0 {
vmmc-supply = <®_vcc3v3>;
bus-width = <4>;
broken-cd;
status = "okay";
};
接下来执行make命令开始编译内核和设备树相关的文件了
make
首次进行编译,通常会需要很长时间,编译完成后,就会在在arch/arm/boot目录下生成内核文件:zImage,在arch/arm/boot/dts目录下设备树文件:suniv-f1c100s-licheepi-nano.dtb 。
在编译过程中,因为所配置Ubuntu系统的差异,可能会因缺少某些组件导致编译报错,不要慌,将对应的错误关键信息复制到搜索引擎后安装即可,一下是作者碰到的两个编译报错,如果有必要可以提前安装:
linux-内核编译配置 lexer.lex.c错误
wu@ubuntu:~/linux-5.4.8$ make exynos_defconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/confdata.o
HOSTCC scripts/kconfig/expr.o
LEX scripts/kconfig/lexer.lex.c
/bin/sh: 1: flex: not found
scripts/Makefile.host:9: recipe for target ‘scripts/kconfig/lexer.lex.c’ failed
make[1]: * [scripts/kconfig/lexer.lex.c] Error 127
Makefile:567: recipe for target ‘exynos_defconfig’ failed
make: * [exynos_defconfig] Error 2
解决方法:
sudo apt-get install bison
sudo apt-get install flex
编译Linux内核时遇到:“error : openssl/bio.h :No such file or folder”
scripts/extract-cert.c:21:25: fatal error: openssl/bio.h: No such file or directory
compilation terminated.
scripts/Makefile.host:90: recipe for target 'scripts/extract-cert' failed
make[1]: * [scripts/extract-cert] Error 1
Makefile:556: recipe for target 'scripts' failed
make: * [scripts] Error 2
安装openssl:
sudo apt install libssl-dev
1.4 TF分区配置
在上一篇中提到过u-boot 中的bootcmd 配置了Linux内核文件和设备树文件存放位置,即TF卡的0:1分区中,而且我们已经得到了对应的文件,那我们应该怎么操作呢。
还记得我们在上一篇中安装的Gparted软件吗,如果不记得,可以通过以下命令安装:
sudo apt-get install gparted
把需要写入系统的TF卡插到电脑的USB上,打开该软件,可以看到此时有两个存储设备,一个是sda另一个是sdb,其中sdb就是我们的TF卡。如图:
选中sdb,我们可以看到分区表中显示为未分配,对于常规Linux嵌入式系统我们需要分两个区,一个是存放zImage和dtb文件,即在bootcmd中配置的0:1分区,另一个区存放根文件系统。对于第一个分区,格式为fat16格式,因为u-boot只能识别这个格式,对于第二个区,一般为ext4格式,为Linux内核识别的格式。下面开始分区吧。
选中未分配空间并右击鼠标,点击[新建],然后填写相关属性,然后点击[添加],所示。
需要注意【之前的空余空间】选择1M,这是给u-boot预留的(u-boot在分区表中是无法看到的),【新大小】选择32M ,【文件系统】选择fat16,【卷标】输入boot。
我们这里可以用相同的方式新建第二分区——ext4分区,如下图
这里我们设置为100M,文件系统为ext4,卷标为rootfs,然后添加添加。
配置好分区表后,点击工具来中的【对钩】使配置的分区表生效。
配置分区完毕后,我们就可以在文件管理器中看到挂载的两个分区,如图
1.5 内核复制与执行
那么,我们将刚才生成好的zImage和dtb文件复制到TF卡的BOOT分区中
退出TF卡,插入开发板,上电,按重启,我们就可以看到u-boot启动完成后,自动进入了内核启动环节,但是启动后一会就报错了,因为挂载文件系统产生错误。
U-Boot SPL 2018.01-05679-g013ca457fd-dirty (Sep 28 2021 - 15:29:32)
DRAM: 32 MiB
Trying to boot from MMC1 U-Boot 2018.01-05679-g013ca457fd-dirty (Sep 28 2021 - 15:29:32 +0800) Allwinner Technology CPU: Allwinner F Series (SUNIV)
Model: Snail Card
DRAM: 32 MiB
MMC: SUNXI SD/MMC: 0
*** Warning - bad CRC, using default environment In: serial@1c25000
Out: serial@1c25000
Err: serial@1c25000
Net: No ethernet found.
starting USB...
No controllers found
Hit any key to stop autoboot: 0
reading zImage
4515448 bytes read in 231 ms (18.6 MiB/s)
reading suniv-f1c100s-licheepi-nano.dtb
6105 bytes read in 26 ms (228.5 KiB/s)
## Flattened Device Tree blob at 80c00000
Booting using the fdt blob at 0x80c00000
Loading Device Tree to 816fb000, end 816ff7d8 ... OK Starting kernel ... [ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 5.7.1 (twzy@ubuntu) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11), GNU ld (Linaro_Binutils-2017.11) 2.28.2.20170706) #55 Tue Sep 28 21:04:24 CST 2021
[ 0.000000] CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
[ 0.000000] CPU: VIVT data cache, VIVT instruction cache
[ 0.000000] OF: fdt: Machine model: LinuxCard by Kevin
[ 0.000000] Memory policy: Data cache writeback
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 8128
[ 0.000000] Kernel command line: console=tty0 console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 rw
[ 0.000000] Dentry cache hash table entries: 4096 (order: 2, 16384 bytes, linear)
[ 0.000000] Inode-cache hash table entries: 2048 (order: 1, 8192 bytes, linear)
[ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[ 0.000000] Memory: 21496K/32768K available (7168K kernel code, 403K rwdata, 1664K rodata, 1024K init, 246K bss, 11272K reserved, 0K cma-reserved, 0K highmem)
[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 ………………… [ 6.598874] Run /etc/init as init process
[ 6.603993] Run /bin/init as init process
[ 6.609078] Run /bin/sh as init process
[ 6.613763] Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance.
[ 6.629985] CPU: 0 PID: 1 Comm: swapper Not tainted 5.7.1 #55
[ 6.636727] Hardware name: Allwinner suniv Family
[ 6.642216] [<c010d604>] (unwind_backtrace) from [<c010ab60>] (show_stack+0x10/0x14)
[ 6.651031] [<c010ab60>] (show_stack) from [<c01165a4>] (panic+0xe8/0x2e4)
[ 6.658951] [<c01165a4>] (panic) from [<c071d080>] (kernel_init+0xd8/0x110)
[ 6.666960] [<c071d080>] (kernel_init) from [<c0100140>] (ret_from_fork+0x14/0x34)
[ 6.675547] Exception stack(0xc1835fb0 to 0xc1835ff8)
[ 6.681293] 5fa0: 00000000 00000000 00000000 00000000
[ 6.690714] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 6.700102] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[ 6.707633] Rebooting in 5 seconds..
[ 12.687513] Reboot failed -- System halted
内核移植就基本结束了,要想让小板真正的运行起来,还需要Linux的文件系统,那开始吧。
2.文件系统移植
根文件系统(rootfs)是内核启动后挂载的第一个文件系统,如果没有根文件系统,内核将无法开启shell以及其他进程。
实际上内核启动后会先挂载一个虚拟的文件系统,这个虚拟文件系统是在内存中运行的,其主要运行核心进程,虚拟文件系统挂载之后才挂载硬盘(TF卡或者emmc)上的根文件系统。
制作文件系统也有很多方式,如通过busyBox、Buildroot等工具制作。
本次使用Buildroot,制作过程相对简单,兼容性好,由于根文件系统制作比较简单。
进入buildroot官网
https://buildroot.org/downloads
这里选择buildroot2018.2.11版本,将下载好软件包传入Ubuntu系统中,然后解压并进入源码目录中,输入清理命令。主要用于初始化一些设置,命令如下:
make clean
然后输入以下命令进入配置界面
make menuconfig
此时会终端进入图形配置界面,如图:
2.1 Target options配置
先选择Target options选项,进行对应芯片soc相关的配置,如图:
配置如图所示,下面是对其的解释
- 第一个选项为架构选择,这里选择ARM架构小端模式,
- 第二个为输出的二进制文件格式,这里选择EFL格式,
- 第三个为架构体系,这里选择arm926t,因为F1C200S/F1C100S的架构就是这个架构,
- 第四个为矢量浮点处理器,这里不勾选,因为对于F1C200S/F1C100S而言,其内部没有浮点运算单元,只能进行软浮点运算,也就是模拟浮点预运算。
- 第五个为应用程序二进制接口,这里选择EABI,原因是该格式支持软件浮点和硬件实现浮点功能混用。
- 第六个为浮点运算规则,这里使用软件浮点
- 第七个选择指令集,这里选择ARM指令集,因为thumb主要针对Cortex M系列而言的,对于运行操作系统的A系列以及ARM9和ARM11而言,使用的都是32位的ARM指令集。
按【Tab键】选择<save>进行保存,按【Esc键】回到上一级配置界面。
2.2 Build options配置
进入第二个Build options选项,配置如图
按T【ab键】选择<save>进行保存,按【Esc键】回到上一级配置界面。
2.3 Toolchain配置
进入第三个Toolchain选项,配置如图:
这里我们选择一些C\C++相关的库,这样我们就可以在开发板上直接编译程序了,保存返回。
2.4 System configuration配置
对于System configuration选项,这里主要是配置一些系统登录时候显示的内容,配置如图
这里主要配置了登录时候显示的内容和root账号登录密码,接下来保存配置并且退回到命令行界面。
然后执行构建文件系统命令:
make
因为是首次编译,而且buildroot在制作文件系统的时候需要联网获取组件,所以会编译很久,那么“去和妲己玩耍吧”
当你终于被别人坑的自闭的时候,文件系统大概也许可能已经编译完毕了。
2.5 文件系统移植与执行
此时在源码的output/images目录下有一个rootfs.tar,这个文件就是最终生成的根文件系统镜像,现在只需要将该镜像解压到TF卡的第二分区即可。插入TF卡到电脑端,进入out/images目录,然后输入
# sudo tar -xvf rootfs.tar -C /media/<你的用户名>/rootfs/
# 墨云的账号是twzy
sudo tar -xvf rootfs.tar -C /media/twzy/rootfs/
此时可以看到TF卡的rootfs分区中有文件系统了
插入开发板,连接好串口,打开串口助手或者其他串口终端软件,可以看到根文件系统成功挂载,同时进入shell交互,用户名默认为root,密码:123456,进入root账号后
那么恭喜,你已经拥有了自己的Linux发行版。
至此我们完成了全部的系统移植任务,从下一篇开始我们将会升级我们的硬件设备和做一些更加有意义的东西,期待吗?
2.6 升级逼格
我们发现登录进自制的Linux系统后,命令行前置无论怎样只显示一个#号,逼格略低呀,怎么处理呢?
修改/etc/profile文件
vi /etc/profile
写入
export PS1='[\u@\h: \w\a\]$'
重启小板,就可以看到与与常规Linux一样的操作体验了,只是root账号的时候还是显示 $ 符号
需要注意的是,在开发板运行过程中,如果想要重启,请先执行
poweroff
命令正常关闭系统后,在按重启按钮,否则有很大概率回造成文件系统损坏。
3. 点个灯吧
还记得我们在第一篇中提到过的我们自制小开发板的唯一的那个外设——LED灯吗?
那我们就利用Linux提供的GPIO系统通过shell命令进行点灯实验吧。
我们首先需要回到文件系统制作菜单
Device Drivers ->
GPIO Support ->
/sys/class/gpio/… (sysfs interface)。
按如下方式进行配置,然后编译完rootfs,重新写入小板
通过硬件可知LED灯连接的是PE6接口,低电平亮灯
这里我们先要了解一下GPIO编号和值的计算方式
引脚编号 = 控制引脚的寄存器基数 + 控制引脚寄存器位数
批注:
引脚编号是gpiochipxxx下的base + 第几个GPIO,也就是base加偏移,偏移的是位数。
例如gpiochip34 下的第1个GPIO那么编号就是34 + 1 = 35
对于F1C200S/F1C100S这里:A=0、B=1、C=2D=3、E=4 ……、32是固定值、6就是偏移量
举个栗子(如果使想用 PE6,那么引脚编号就可能等于 4 x 32 + 6 = 134。
这是一些参考命令
# 1、导出
echo 134 > /sys/class/gpio/export
# 2、设置方向
echo out > /sys/class/gpio/gpio134/direction
# 3、查看方向
cat /sys/class/gpio/gpio134/direction
# 4、设置输出(对于LED 设置1 为高电平即LED灯灭,设置0 为低电平,LED灯亮)
echo 1 > /sys/class/gpio/gpio134/value
# 5、查看输出值
cat /sys/class/gpio/gpio134/value
# 6、取消导出
echo 134 > /sys/class/gpio/unexport
输入如下命令:
echo 134 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio134/direction # 灯亮 (默认设置为高电平)
echo 0 > /sys/class/gpio/gpio134/value # 灯灭
echo 1 > /sys/class/gpio/gpio134/value # 灯亮 echo 134 > /sys/class/gpio/unexport
效果如下:
我们这里借助Linux内建的GPIO子系统进行了电灯实验,但是真正Linux灵魂点灯是要通过驱动方式来实现的,但是谁让我是小白呢,以后再说吧。
小白自制Linux开发板 三. Linux内核与文件系统移植的更多相关文章
- 小白自制Linux开发板 八. Linux音频驱动配置
不知不觉小白自制开发板系列已经到第八篇了,本篇要配置的是音频驱动,也算是硬件部分的最后一片了,积攒的文章也差不多全放完了,后续更新可能会放缓,还请见谅. 对于F1C200s是自带了多媒体处理功能的,所 ...
- 小白自制Linux开发板 二. u-boot移植
上一篇:小白自制Linux开发板 一. 瞎抄原理图与乱画PCB 中我们做了一个小型而没用的开发板,用的是Licheepi Nano的镜像,那从本篇开始我们开始自己构建它的灵魂吧. 我们都知道,PC在 ...
- 嵌入式Linux开发板
嵌入式Linux开发板开发介绍: iTOP-4412嵌入式Linux开发板搭载三星Exynos四核处理器,配备1GB内存,4GB固态硬盘EMMC存储,独家配备三星S5M8767电源管理,配备Andro ...
- Linux开发板(树莓派)和服务器进行双向通信(socket)
前言 物联网是目前嵌入开发必备的属性之一,我们常常需要把自己开发板和云端进行交互,本篇博文就记录一下. 使用Socket来实现Linux开发板和服务器进行双向通信,Python中是默认集成了s ...
- 意法半导体STM32MP157A MPU加持,米尔科技首款ST Linux开发板MYD-YA157C评测
ST公司去年推出了MPU系列芯片,MPU系列不同于以往产品,它既包含有ARM公司Cortex M 单片机核心,也包含有ARM公司Cortex A 应用处理器核心,以期将STM32单片机产品优势扩展到更 ...
- 【Linux开发】OpenCV在ARM-linux上的移植过程遇到的问题4---共享库中嵌套库带路径【已解决】
[Linux开发]OpenCV在ARM-linux上的移植过程遇到的问题4-共享库中嵌套库带路径[已解决] 标签:[Linux开发] 紧接着上一篇,我居然又尝试了一下编译opencv,主要是因为由于交 ...
- 嵌入式Linux开发教程:Linux常见命令(上篇)
摘要:这是对周立功编著的<嵌入式Linux开发教程>的第7期连载.本期刊载内容有关LinuxLinux常见命令中的导航命令.目录命令和文件命令.下一期将连载网络操作命令.安装卸载文件系统等 ...
- 【Linux开发】OpenCV在ARM-linux上的移植过程遇到的问题2---CMAKE配置问题
实际上这里说的是移植的第一步,下载到源码后,我用的是opencv2.4.9,解压缩,然后可以利用cmake-gui来进行configure配置,这里面需要设置交叉编译的工具链,具体的可以参考[Linu ...
- [学习嵌入式开发板]iTOP-4412实现NFS网络文件系统
本文转自迅为:http://www.topeetboard.com 学习平台:iTOP-4412开发板 本文讲解如何在 iTOP-4412 开发板上实现 NFS 网络文件系统. 我们使用的软硬件环境是 ...
随机推荐
- LeetCode42. 接雨水(java)
42.接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种 ...
- Redis脑图
转自:http://alphawang.com/blog/redis-mind-map/ 最近梳理了下 Redis 知识图谱,画了个脑图,涵盖了 Redis 数据类型.持久化机制.主从.哨兵.集群.应 ...
- ☕【Java技术指南】「TestNG专题」单元测试框架之TestNG使用教程指南(上)
TestNG介绍 TestNG是Java中的一个测试框架, 类似于JUnit 和NUnit, 功能都差不多, 只是功能更加强大,使用也更方便. 详细使用说明请参考官方链接:https://testng ...
- VS2017 提示找不到某个.dll库,或某个dll库丢失,原因
可能因为那个dll的确不存在 可能因为需要在环境变量->系统环境变量->添加该dll所在目录
- MySQL授权认证
• MySQL-权限系统介绍 • 权限系统的作用是授予来自某个主机的某个用户可以查询.插入.修改.删除等数据库操作的权限 • 不能明确的指定拒绝某个用户的连接 • 权限控制(授权与回收)的执行语句包括 ...
- shp的基本操作
本节将介绍如何利用python完成对shp的基本操作 1.读取shp四至 import shapefile sf = shapefile.Reader(r"E:\shp\1.shp" ...
- Pytest 系列(24)- allure 环境准备
如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html allure 和 pytest 相 ...
- 简说yuv
最近弄了一个读取y4m文件转成yuv的流的事情,记录一些yuv相关的细节 为什么会有yuv 因为我们目前的显示器显示的原理都是三原色,几乎所有的视频数据最后都要转为rgb格式才能渲染到显示屏上,而原始 ...
- word域实现动态填充信息附件下载
1.问题描述:在页面上一些下载附件功能,点击触发执行下载操作时候,有些电脑的浏览器可以,有些电脑的浏览器下载不了,电脑打开弹出的下载框下载的不是一个文件,而是一个如jspx后缀名的页面,jspx后缀是 ...
- Flex语法和常用鼠标手势
Flex弹性和模型 1.display : flex/inline-flex ;(设置给氟元素) flex : 将对象作为弹性伸缩盒显示: inline-flex : 将对象作为内联块级弹性伸缩显示: ...