龙芯2k0300 - 久久派开发环境搭建及内核升级
最近,打算参加第21届全国智能汽车竞赛走马观碑组,在《第21届智能汽车竞赛走马观碑》我们介绍了竞赛规则、以及硬件、软件设计方案,在硬件设计方案中我们选用了久久派2K0300核心板WiFI版本。
本节主要针对核心板硬件资源以及开发环境搭建进行详细介绍。
一、介绍
1.1 硬件特性
龙芯2K0300处理器官网地址:《https://www.loongson.cn/index.php/product/show?id=33》,相关产品手册:
1.1.1 龙芯2K0300
LS2K0300芯片是基于LA264处理器核的多功能SOC芯片,可广泛适用于工业控制、通信设备、信息家电和物联网等应用领域。
龙芯LS2K0300采用高集成度设计,提供丰富的功能接口,可满足多场景应用需求,同时支持低功耗技术,能够在低能耗表现下提供高效处理性能。
LS2K0300芯片片内集成16位DDR4内存控制器,并集成了丰富的外设接口:USB2.0接口,GMAC接口,DVO显示接口,I2S音频接口,SPI/QSPI,ADC,SDIO,eMMC和其他工控领域常用接口。
龙芯2K0301是2K0300的内存合封版,两者CPU内核、主频、外设完全一致,唯一核心区别在于:2K0301内部直接封装了4GB DDR4内存,而2K0300需要外置内存。
1.1.1.1 CPU
2个 龙芯LA264处理器核,主频1.0GHz;
32KB一级指令缓存和32KB一级数据缓存,支持ECC校验;512KB二级共享缓存,支持ECC校验。
1.1.1.2 Memory
16位DDR4-1600控制器,支持ECC校验,典型速率1600Mbps。
1.1.1.3 AI支持
没有像瑞芯微RK3588那样内置独立的NPU,但它仍然具备一定的AI处理能力。
| 参数 | 规格 | 解读 |
|---|---|---|
| 向量加速 | 内置128位向量单元 | 这是它处理AI任务的关键。向量单元可以加速SIMD(单指令多数据流)运算,对于卷积神经网络中的矩阵乘法等操作,比纯CPU快很多。 |
| AI框架支持 | 支持 NCNN、Tengine、ONNX Runtime 等 | 官方和社区正在将主流的端侧推理引擎移植到LoongArch架构上。 这意味着你可以先在电脑上训练好模型(如NanoDet),然后通过NCNN等工具转换,部署到2K0300上,利用它的向量单元进行加速推理。 |
| 实际推理能力 | 预计能实时运行轻量级模型 | 参考类似规格的芯片(如Cortex-A53 1.0GHz),2K0300处理 320x320 输入的 NanoDet 模型,帧率预计可以达到 10-20 FPS 左右。对于车模控制来说,这个速度基本够用,但需要做好代码优化。 |
1.1.1.4 外设接口
| 接口类型 | 数量/规格 | 描述 |
|---|---|---|
| DVO | 1 | 1 路DVO显示输出,分辨率可支持 320×240~1920×1080@60Hz/24bit |
| USB控制器 | 2 | 1个USB2.0 HOST接口,1个OTG接口支持HOST/DEVICE 模式 HOST 接USB摄像头; OTG 可配置为HOST接调试设备,或配置为Device用于烧录系统(Type-C口)。 |
| GMAC 控制器 | 2 | 2路10M/100M/1000M 自适应 GMAC控制器,支持RGMII/MII |
| I2S | 1 | 1路I2S接口、支持单声道和立体声道音频数据、支持DMA传输模式 |
| SPI | 4 | 1 路支持系统启动(SPI0),2 路支持QSPI 模式(SPI0/1) |
| UART | 10 | 集成10个UART控制器 |
| I2C | 4 | 集成4路I2C控制器,支持主从模式 |
| ADC | 8通道,12位 | 集成1个8通道12位AD接口 |
| CAN | 4 | 支持 4路CAN接口,支持CAN-FD,支持DMA传输模式 |
| TIMER | 3 | 集成3组定时器 A/G/B-TIMER |
| PWM | 4 | 集成4路PWM控制器,支持输入/输出 |
| GPIO | 106 | 集成106路复用GPIO,支持位操作,支持输入/输出,支持外部中断输入 |
| SDIO | 2 | 集成2个SDIO控制器,均支持SDIO/eMMC |
1.1.1.5 指令集
LoongArch:龙芯自主指令集架构,这意味着它不是ARM,也不是x86。
1.1.2 核心板
下面是我购买的2K0300久久派核心板的正面外形,从PCB上我们可以看到这个板子上的电气元件的密度是非常大的:
更多有关久久派产品规格以及接口介绍的可以参考《LS2K0300久久派_V1.1板卡使用手册v1.2_20240705.pdf》。
1.1.2.1 产品设计架构
1.1.2.2 配置清单
配置清单:
RAM:512MB DDR4-1600;SPI Nor Flash:8MB;eMMC:8G;- 显示:
1个54 pin下触FPC连接器,支持触摸;已适配显示屏型号LCD070CG+1024600FD31(飞凌嵌入式); - 音频:
1个3.5mm音频插孔; RTC:支持内置RTC;WiFi/BT:板载WiFi/BT模块,支持单天线;- 千兆网口:
1个千兆网口; USB-A:两个USB 2.0 Type-A接口;AD插针:8路12位ADC,2.54mm间隔插针IO插针(2.54mm间隔2*15pin插针):2路SPI,其中SPI2支持slave模式,也可复用为4路PWM;2路I2C,可复用为GPIO;
3路UART,可复用为GPIO;UART0默认调试串口,波特率115200;2路CAN,可复用为GPIO;
2路PWM,可复用为GPIO;- 复位:
1个板载复位按键; - 指示灯:
3个电源/复位/状态指示灯; LA_JTAG:1个LA_JTAG连接器,1.27mm间隔2*4pin LA_JTAG连接器排针;- 供电:
DC 5V/2A Type-C供电、2 PRTC电池; - 尺寸:
88MM X 56MM。
1.2 接口布局
核心板接口图:
我们可以通过《 Loongson-2K0300-99PAI》下载电路原理图。在开发板上有两排引脚,上边是单排插针(10个),下边是双排插针(30个)。
1.2.1 ADC
板卡集成8路12 bit ADC采样接口,支持单端采样,也支持差分采样,采样电压范围0~1.8V,调试接口采用2.54mm间距1*10 pin插针。接口pin序定义及差分采样组合说明见下表:
| PIN | 信号定义 | 备注 |
|---|---|---|
| 1 | P3V3 | 3.3V 电源输出 |
| 2 | GND0 | |
| 3 | ADC 通道 4 | 0/4 通道可以独立采样,也可以作为差分采样 |
| 4 | ADC 通道 0 | 0/4 通道可以独立采样,也可以作为差分采样 |
| 5 | ADC 通道 1 | 1/5 通道可以独立采样,也可以作为差分采样 |
| 6 | ADC 通道 5 | 1/5 通道可以独立采样,也可以作为差分采样 |
| 7 | ADC 通道 2 | 2/6 通道可以独立采样,也可以作为差分采样 |
| 8 | ADC 通道 6 | 2/6 通道可以独立采样,也可以作为差分采样 |
| 9 | ADC 通道 3 | 3/7 通道可以独立采样,也可以作为差分采样 |
| 10 | ADC 通道 7 | 3/7 通道可以独立采样,也可以作为差分采样 |
1.2.2 LCD
板卡集成1路LCD显示输出,分辨率可支持320*240~1920*1080@60Hz/24bit。调试接口采用0.5mm间距54 pin下触FPC连接器。连接器pin序及定义如下所示:
| PIN | 信号定义 | 备注 |
|---|---|---|
| 1 | TSX+ | 扩展触摸信号, NC |
| 2 | TSX- | 扩展触摸信号, NC |
| 3 | TSY+ | 扩展触摸信号, NC |
| 4 | TSY- | 扩展触摸信号, NC |
| 5, 15, 24, 33, 42, 46, 48 | GND | |
| 6 | LS2K_GPIO54 | 电源使能(硬件默认上拉) |
| 7 | LS2K_I2C_SDA0 | |
| 8 | LS2K_I2C_SCL0 | |
| 9, 10, 11, 12 | NC | |
| 13 | LS2K_GPIO52 | 触摸板中断(硬件默认上拉) |
| 14 | LS2K_GPIO53 | 触摸板复位(硬件默认上拉) |
| 16 - 23 | LS2K_LCD_D[0:7] | B 数据 |
| 25 - 32 | LS2K_LCD_D[8:15] | G 数据 |
| 34 - 41 | LS2K_LCD_D[16:23] | R 数据 |
| 43 | LS2K_LCD_HSYNC | 水平同步 |
| 44 | LS2K_LCD_VSYNC | 垂直同步 |
| 45 | LS2K_LCD_EN | 数据有效 |
| 47 | LS2K_LCD_CLK | 时钟输出 |
| 49 | LS2K_PWM0 | 背光控制(GPIO87) |
| 50 - 54 | VCC_5V |
龙芯已适配显示屏型号: LCD070CG+1024600FD31(飞凌嵌入式)。
1.2.3 LA_JTAG
板卡集成1.27mm间距2*4pin JTAG插针接口,可通过龙芯JTAG仿真器转接小板直接对插。板载连接器pin序及定义如下表:
1.2.4 音频接口
板卡集成1路音频接口,由处理器I2S接口经音频编解码器ES8388引出,支持耳机插拔检测,支持麦克风输入(暂不可用)和音频输出。ES8388也挂在2K0300的I2C0总线上,设备地址为0x10;耳机插拔检测信号为GPIO55(原理图中网络名称标成LS2K_GPIO102,实际为LS2K_GPIO55)。
调试接口采用4段式3.5mm音频插孔(默认CTIA,可支持OMTP)。
1.2.5 以太网接口
板卡集成1路千兆以太网接口,由处理器GMAC0接口连接一个PHY芯片YT8531C转出,支持1000/100/10Mbps网络自适应切换,调试接口采用标准RJ45连接器。连接器pin序及定义如下表所示:
1.2.6 USB2.0接口
板卡集成2路USB接口,由处理器USB2.0接口直出,兼容USB1.1、USB2.0。调试接口采用1个双口堆叠式USB TYPE A连接器。
连接器pin序及定义如下表所示:
1.2.7 指示灯
板卡右上角集成3颗LED指示灯,如下图所示从左往右依次为
- 复位指示灯:在复位期间常亮
- 运行状态指示灯:用于出厂内存压力测试或用户调试使用(由
GPIO83控制,低电平点亮); - 电源指示灯:电源指示灯在外部电源
5V输入正常时点亮。
1.2.8 I/O插针接口
板卡集成2.54mm间距2*15 pin IO插针接口,用于接口扩展。 默认功能包括2路电源、2路PWM、2路CAN总线、2路I2C总线、2路SPI和3路UART串口(3.3V LVTTL电平);
久久派引脚图表(在《龙芯2k0300处理器用户手册.pdf》中有所有引脚复用关系表):
信号定义为出厂默认功能。如需使用部分管脚其他复用功能则可根据备注中的GPIO编号对照LS2K0300数据手册的“引脚功能复用表”进行配置。
在使用诸如按键、蜂鸣器、编码器、无线模块、TFT屏幕、ADC 采集以及电机驱动等外设时,首要步骤是明确这些设备与开发板之间连接的具体引脚配置;
二、开发环境搭建
2.1 VMware安装
对于VMware安装可以参考《嵌入式Linux开发环境搭建》,该博客中提供的VMware 已经过期,新版本的下载地址:VMware Pro 17。
2.2 ubuntu安装以及配置
对于ubuntu安装可以参考《嵌入式Linux开发环境搭建》,这里可以安装Ubuntu 22.04.5 LTS,安装完成后进入虚拟机查看版本信息;
hengyang@ubuntu:~/桌面$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.5 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
2.2.1 网络设置
WMware网络设置支持三种模式:
bridged(桥接模式):虚拟机能得到一个独立IP地址,网络能提供多个IP地址;虚拟机可以访问外部网络,外部网络也可以访问虚拟机;NAT(网络地址转换模式) : 如果网络中只提供一个IP地址,虚拟机和主机使用一个IP地址;虚拟机可以外部网络,但是外部网络访问不了虚拟机;- 主机模式 (主机没有联网):相当于把主机和虚拟机通过一根网线连接在一起;

之前我们在安装ubuntu的时候选择了桥接模式,需要确保如下配置正确:
- 打开
VMware→ 点击菜单栏编辑 → 虚拟网络编辑器; - 在弹出的窗口中,找到VMnet0,确保它设置为桥接模式;
- 在桥接到下拉框中,手动选择你正在使用的物理网卡(根据
windows主机的ipconfig查看当前使用的物理网卡,如Realtek PCIe GbE Family Controller); - 如果
VMnet0不在列表中,可以点击右下角的 “更改设置”(需要管理员权限),然后点击“还原默认设置”来恢复。
我们需要设置ubuntu和主机在同一网段内,由于我的windows操作系统的IP为172.23.34.186:
C:\Users\zhengyang>ipconfig
Windows IP 配置
以太网适配器 以太网:
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::43b3:b450:a09b:8c8d%16
IPv4 地址 . . . . . . . . . . . . : 172.23.34.186
子网掩码 . . . . . . . . . . . . : 255.255.128.0
默认网关. . . . . . . . . . . . . : 172.23.0.1
查看ubuntu的网络配置:
zhengyang@ubuntu:~/桌面$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.100 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::eb89:d648:fbc9:91b0 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:79:69:69 txqueuelen 1000 (以太网)
RX packets 3460 bytes 563979 (563.9 KB)
RX errors 0 dropped 21 overruns 0 frame 0
TX packets 210 bytes 15145 (15.1 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 19 base 0x2000
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (本地环回)
RX packets 274 bytes 27156 (27.1 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 274 bytes 27156 (27.1 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
可以看到,本例中的网卡为ens33,同时可以看到相应的IP信息等。
可以看到虚拟机和宿主机不在一个网段,这里我们直接进入ubuntu桌面,点击左下角设置,选中网络,修改IpV4信息确保在一个网段;
此时宿主机(172.23.34.186)和虚拟机(172.23.34.187)网络应该是可以互相ping:
如果网络宿主机和虚拟机网络不通,请检查防火墙是否关闭。
此时我们就可以通过MobaXterm工具远程SSH登录ubuntu虚拟机;
2.2.2 安装依赖
首先更新软件源:
zhengyang@ubuntu:~$ sudo apt update
安装一些依赖库,编译内核时可能会用到:
zhengyang@ubuntu:~$ sudo apt install make gcc flex bison libssl-dev bc libncurses-dev
2.2.3 安装cmake
CMake是一个跨平台的构建工具,其支持程度要好于qmake。CMake的配置更加灵活、强大,也更容易维护。CMake是一个比make更高级的编译配置工具,它可以根据不同平台、不同的编译器,生成相应的Makefile或者vcproj项目。
如果编译安装可以参考:《CMake安装》,但是这种方式一般比较复杂。这里直接使用apt命令安装;
zhengyang@ubuntu:~$ sudo apt install cmake
zhengyang@ubuntu:~$ cmake -version
cmake version 3.22.1
CMake suite maintained and supported by Kitware (kitware.com/cmake).
2.2.4 安装git
安装git:
zhengyang@ubuntu:~$ sudo apt install git
zhengyang@ubuntu:/opt/2k0300$ git --version
git version 2.34.1
2.3 安装VS Code
Visual Studio code,简称VS Code,是微软在2015年推出的一个轻量但功能强大的源代码编辑器,支持 windows、Linux和 mac os操作系统,扩展组件非常丰富,可以快速搭建成为项目开发的神兵利器。
2.3.1 下载安装
我们从官方网站下载deb安装包,注意这里我下载的是X86架构,我们创建一个目录并将其拷贝进来:
zhengyang@ubuntu:/opt$ sudo mkdir 2K0300
zhengyang@ubuntu:/opt$ sudo chmod -R 777 ./2k0300/
# 下载完成,拷贝到这个目录
zhengyang@ubuntu:/opt$ ll ./2k0300/
-rw-rw-r-- 1 zhengyang zhengyang 121978886 3月 18 21:42 code_1.111.0-1772846623_amd64.deb
运行如下命令安装:
zhengyang@ubuntu:/opt$ cd ./2k0300/
zhengyang@ubuntu:/opt/2k0300$ sudo dpkg -i code_1.111.0-1772846623_amd64.deb
安装完成后我们可以通过左下角的菜单找到Visual Studio code,双击打开;
2.3.2 插件配置
为了便于后续的开发与调试,我们安装一系列插件,无限扩展VS Code的功能。
C/C++ # 运行编译C/C++程序
C/C++ Snippets # C/C++重用代码块
C/C++ Advanced Lint # C/C++静态检测
Code Runner # 代码运行
Include AutoComplete # 自动头文件包含
Markdown All in One # 提供增强的Markdown支持
GitHub Copilot # 安装AI编程助手
CMake # 支持CMake语法,完整的构建、调试、项目管理;
Rainbow Brackets # 彩虹花括号,有助于阅读代码
GBKtoUTF8 # 将 GBK 转换为 UTF8#
C/C++ Project Generator # 工程相关
Chinese(Simplified) # 中文环境
vscode-icons # Vscode图标插件,主要是资源管理器下各个文件夹的图标
compareit # 比较插件,可以用于比较两个文件的差异
DeviceTree # 设备树语法插件
2.4 安装交叉编译环境
由于x86和LoongArch架构最底层的指令集不同,所以两个平台的程序不能通用,需要分开编译,编译的工具链是不一样。
由于我们日常的开发习惯,LoongArch架构的计算机资源等等因素,我们通常会在x86架构的平台上编写代码并编译然后放到ARM上运行。 所以就需要搭建交叉编译环境。
什么是交叉编译环境呢?简单点说就是在一个架构的处理器上能编译在另一个架构上运行的程序的环境。 再简单点来说,就是在x86架构下安装LoongArch的编译工具。
下载交叉编译工具:
zhengyang@ubuntu:/opt/2k0300$ wget https://gitee.com/open-loongarch/cross-toolchain/blob/master/gcc-13/loongarch64-linux-gnu-gcc13.3.tar.xz
zhengyang@ubuntu:/opt/2k0300$ ls -l
-rw-rw-r-- 1 zhengyang zhengyang 121978886 3月 18 21:42 code_1.111.0-1772846623_amd64.deb
-rw-rw-r-- 1 zhengyang zhengyang 135974 3月 21 18:08 loongarch64-linux-gnu-gcc13.3.tar.xz
2.4.1 解压
解压交叉编译工具链,放置到/opt目录下,也可自己指定解压目录;
zhengyang@ubuntu:/opt/2k0300$ sudo tar -xvf loongarch64-linux-gnu-gcc13.3.tar.xz -C /opt
zhengyang@ubuntu:/opt/2k0300$ ll /opt/loongarch64-linux-gnu-gcc13.3
drwxr-xr-x 2 zhengyang zhengyang 12288 2月 13 2025 bin/
drwxr-xr-x 4 zhengyang zhengyang 4096 2月 13 2025 etc/
drwxr-xr-x 8 zhengyang zhengyang 4096 2月 13 2025 include/
drwxr-xr-x 8 zhengyang zhengyang 4096 2月 13 2025 lib/
lrwxrwxrwx 1 zhengyang zhengyang 3 2月 13 2025 lib64 -> lib/
drwxr-xr-x 4 zhengyang zhengyang 4096 2月 13 2025 libexec/
lrwxrwxrwx 1 zhengyang zhengyang 30 2月 13 2025 loongarch64-linux-gnu -> loongarch64-loongson-linux-gnu/
drwxr-xr-x 6 zhengyang zhengyang 4096 2月 13 2025 loongarch64-loongson-linux-gnu/
drwxr-xr-x 17 zhengyang zhengyang 4096 2月 13 2025 share/
lrwxrwxrwx 1 zhengyang zhengyang 40 2月 13 2025 sysroot -> ./loongarch64-loongson-linux-gnu/sysroot/
lrwxrwxrwx 1 zhengyang zhengyang 1 2月 13 2025 usr -> ./
drwxr-xr-x 2 zhengyang zhengyang 4096 2月 13 2025 version/
2.4.2 配置环境变量
配置环境变量:
zhengyang@ubuntu:/opt/2k0300$ sudo vim /etc/profile
打开profile文件后,在最后添加:
#设置交叉编译工具链
export PATH=$PATH:/opt/loongarch64-linux-gnu-gcc13.3/bin/
执行如下命令使配置生效:
zhengyang@ubuntu:/opt/2k0300$ source /etc/profile
验证安装:
zhengyang@ubuntu:/opt/2k0300$ loongarch64-linux-gnu-gcc -v
使用内建 specs。
COLLECT_GCC=/opt/loongarch64-linux-gnu-gcc13.3/bin/loongarch64-linux-gnu-gcc.br_real
COLLECT_LTO_WRAPPER=/opt/loongarch64-linux-gnu-gcc13.3/bin/../libexec/gcc/loongarch64-loongson-linux-gnu/13.3.0/lto-wrapper
目标:loongarch64-loongson-linux-gnu
配置为:./configure --prefix=/home/tao/work/buildroot/ooo/host --
......
线程模型:posix
Supported LTO compression algorithms: zlib
gcc 版本 13.3.0 (Buildroot -ga9f4f28a-dirty)
2.5 编译移植OpenCV
参考《opencv安装及配置》安装opencv 4.9版本。
2.5.1 安装依赖
zhengyang@ubuntu:/opt/2k0300$ sudo apt install -y libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libatlas-base-dev gfortran libgtk2.0-dev libjpeg-dev libpng-dev ffmpeg
2.5.2 下载源码
下载安装包:
zhengyang@ubuntu:/opt/2k0300$ wget -O opencv-4.10.0.tar.gz https://github.com/opencv/opencv/archive/4.10.0.tar.gz
zhengyang@ubuntu:/opt/2k0300$ ls -l opencv-4.10.0.tar.gz
-rw-rw-r-- 1 zhengyang zhengyang 94993429 3月 19 10:46 opencv-4.10.0.tar.gz
解压:
zhengyang@ubuntu:/opt/2k0300$ tar -zxvf opencv-4.10.0.tar.gz
zhengyang@ubuntu:/opt/2k0300$ cd opencv-4.10.0/
# 创建build和install目录
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0$ mkdir build install
2.5.3 编译配置
配置OpenCV,启用/禁用某个配置:
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0$ cd build/
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/build$ CC=loongarch64-linux-gnu-gcc \
CXX=loongarch64-linux-gnu-g++ \
cmake .. \
-D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=../install \
-D CMAKE_EXE_LINKER_FLAGS="-lpthread -lrt -ldl" \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF \
-D BUILD_EXAMPLES=OFF \
-D WITH_GTK=OFF \
-D WITH_OPENMP=ON \
-D WITH_V4L=ON \
-D WITH_IPP=OFF \
-D WITH_ITT=OFF \
-D WITH_TBB=OFF
其中:
CMAKE_INSTALL_PREFIX:安装路径;CMAKE_EXE_LINKER_FLAGS:链接线程库;BUILD_TESTS:不编译测试;BUILD_PERF_TESTS:不编译性能测试;BUILD_EXAMPLES:不编译示例;WITH_GTK:不需要GUI;WITH_OPENMP:开启并行优化;WITH_V4L:支持摄像头;WITH_IPP、WITH_ITT、WITH_TBB:仅对x86平台有意义。在ARM、龙芯等非Intel平台上禁用它是标准做法。
更多配置可以参考:《OpenCV 配置选项参考文档》。cmake ..之后会输出:
......
-- Video I/O:
-- DC1394: NO
-- FFMPEG: NO
-- avcodec: YES (58.134.100)
-- avformat: YES (58.76.100)
-- avutil: YES (56.70.100)
-- swscale: YES (5.9.100)
-- avresample: NO
-- GStreamer: NO
-- v4l/v4l2: YES (linux/videodev2.h)
--
-- Parallel framework: OpenMP
--
......
--
-- OpenCL: YES (no extra features)
-- Include path: /opt/2k0300/opencv-4.10.0/3rdparty/include/opencl/1.2
-- Link libraries: Dynamic load
--
......
2.5.4 编译安装
编译安装:
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/build$ make -j${nproc}
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/build$ make install
默认安装到/opt/2k0300/opencv-4.10.0/install路径下,
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/build$ ll /opt/2k0300/opencv-4.10.0/install
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 21 18:57 bin/
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 21 18:57 include/
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 21 18:57 lib/
drwxrwxr-x 4 zhengyang zhengyang 4096 3月 21 18:57 share/
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/build$ cd ../install
比如:
/opt/2k0300/opencv-4.10.0/install/include/opencv4:头文件安装目录;/opt/2k0300/opencv-4.10.0/install/lib:库文件安装目录;
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/install$ ls lib/
cmake libopencv_features2d.so libopencv_highgui.so.410 libopencv_ml.so.4.10.0 libopencv_videoio.so
libopencv_calib3d.so libopencv_features2d.so.410 libopencv_highgui.so.4.10.0 libopencv_objdetect.so libopencv_videoio.so.410
libopencv_calib3d.so.410 libopencv_features2d.so.4.10.0 libopencv_imgcodecs.so libopencv_objdetect.so.410 libopencv_videoio.so.4.10.0
libopencv_calib3d.so.4.10.0 libopencv_flann.so libopencv_imgcodecs.so.410 libopencv_objdetect.so.4.10.0 libopencv_video.so
libopencv_core.so libopencv_flann.so.410 libopencv_imgcodecs.so.4.10.0 libopencv_photo.so libopencv_video.so.410
libopencv_core.so.410 libopencv_flann.so.4.10.0 libopencv_imgproc.so libopencv_photo.so.410 libopencv_video.so.4.10.0
libopencv_core.so.4.10.0 libopencv_gapi.so libopencv_imgproc.so.410 libopencv_photo.so.4.10.0
libopencv_dnn.so libopencv_gapi.so.410 libopencv_imgproc.so.4.10.0 libopencv_stitching.so
libopencv_dnn.so.410 libopencv_gapi.so.4.10.0 libopencv_ml.so libopencv_stitching.so.410
libopencv_dnn.so.4.10.0 libopencv_highgui.so libopencv_ml.so.410 libopencv_stitching.so.4.10.0
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/install$ ll include/opencv4/opencv2/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 21 18:57 calib3d/
-rw-r--r-- 1 zhengyang zhengyang 225103 6月 2 2024 calib3d.hpp
drwxrwxr-x 8 zhengyang zhengyang 4096 3月 21 18:57 core/
-rw-r--r-- 1 zhengyang zhengyang 157253 6月 2 2024 core.hpp
-rw-r--r-- 1 zhengyang zhengyang 3200 3月 21 18:15 cvconfig.h
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 21 18:57 dnn/
-rw-r--r-- 1 zhengyang zhengyang 3347 6月 2 2024 dnn.hpp
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 21 18:57 features2d/
-rw-r--r-- 1 zhengyang zhengyang 73046 6月 2 2024 features2d.hpp
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 21 18:57 flann/
-rw-r--r-- 1 zhengyang zhengyang 28076 6月 2 2024 flann.hpp
drwxrwxr-x 15 zhengyang zhengyang 4096 3月 21 18:57 gapi/
-rw-r--r-- 1 zhengyang zhengyang 1324 6月 2 2024 gapi.hpp
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 21 18:57 highgui/
-rw-r--r-- 1 zhengyang zhengyang 37533 6月 2 2024 highgui.hpp
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 21 18:57 imgcodecs/
-rw-r--r-- 1 zhengyang zhengyang 28502 6月 2 2024 imgcodecs.hpp
drwxrwxr-x 4 zhengyang zhengyang 4096 3月 21 18:57 imgproc/
-rw-r--r-- 1 zhengyang zhengyang 257230 6月 2 2024 imgproc.hpp
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 21 18:57 ml/
-rw-r--r-- 1 zhengyang zhengyang 92634 6月 2 2024 ml.hpp
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 21 18:57 objdetect/
-rw-r--r-- 1 zhengyang zhengyang 43093 6月 2 2024 objdetect.hpp
-rw-r--r-- 1 zhengyang zhengyang 3463 6月 2 2024 opencv.hpp
-rw-r--r-- 1 zhengyang zhengyang 752 3月 21 18:15 opencv_modules.hpp
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 21 18:57 photo/
-rw-r--r-- 1 zhengyang zhengyang 38134 6月 2 2024 photo.hpp
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 21 18:57 stitching/
-rw-r--r-- 1 zhengyang zhengyang 14712 6月 2 2024 stitching.hpp
drwxrwxr-x 4 zhengyang zhengyang 4096 3月 21 18:57 video/
-rw-r--r-- 1 zhengyang zhengyang 2516 6月 2 2024 video.hpp
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 21 18:57 videoio/
-rw-r--r-- 1 zhengyang zhengyang 69457 6月 2 2024 videoio.hpp
接着我们随便找一个库文件,查看一下其架构信息;
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/install$ file lib/libopencv_core.so.4.10.0
lib/libopencv_core.so.4.10.0: ELF 64-bit LSB shared object, LoongArch, version 1 (GNU/Linux), dynamically linked, not stripped
恭喜!这个输出说明编译成功了。file 命令显示的信息非常关键:
ELF 64-bit LSB shared object:这是一个标准的64位动态链接库;LoongArch:明确表明该库是为龙芯LoongArch架构编译的,可以在你的2K0300上直接运行。not stripped:表示调试符号未被去除,不影响使用,只是文件稍大。如果你想减小体积,之后可以用loongarch64-linux-gnu-strip工具去除符号。
2.5.5 在龙芯板子上部署OpenCV
注意:!!!执行接下来的流程前需要先升级开发板的镜像系统,升级流程参考后面的章节。
打包编译结果:
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/install$ tar -czvf opencv-4.10.0-loongarch64.tar.gz ./*
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/install$ ll opencv-4.10.0-loongarch64.tar.gz
-rw-rw-r-- 1 zhengyang zhengyang 15454239 3月 19 14:21 opencv-4.10.0-loongarch64.tar.gz
确保龙芯核心板和ubuntu虚拟机在同一个局域网,并且网络已通,然后传输文件到龙芯核心板;
zhengyang@ubuntu:/opt/2k0300/opencv-4.10.0/install$ scp opencv-4.10.0-loongarch64.tar.gz root@龙芯IP:/home/root/
同样通过MobaXterm工具远程SSH登录龙芯核心板,在龙芯板子上解压安装;
zhengyang@ubuntu:~$ ssh root@龙芯IP
创建opencv目录并解压:
root@LoongOS:~$ mkdir -p /usr/local/opencv
root@LoongOS:~$ cd /usr/local/opencv
root@LoongOS:/usr/local/opencv$ tar -zxvf /home/root/opencv-4.10.0-loongarch64.tar.gz
配置动态链接库,编辑/etc/ld.so.conf,文末加入/usr/local/lib;
root@LoongOS:~$ sudo vim /etc/ld.so.conf
......
/usr/local/opencv/lib
更新动态链接库缓存:
root@LoongOS:~$ sudo /sbin/ldconfig -v
验证库是否被识别:
root@LoongOS:~$ ldconfig -p | grep opencv
2.5.6 编写测试程序验证OpenCV
在ubuntu虚拟机中编写测试代码,在2K0300目录下创建子目录:
zhengyang@ubuntu:/opt/2k0300$ mkdir opencv_test
zhengyang@ubuntu:/opt/2k0300$ cd opencv_test/
创建一个测试文件test_opencv.cpp:
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
int main() {
// 打印OpenCV版本
std::cout << "OpenCV version: " << CV_VERSION << std::endl;
// 创建一个100x100的绿色图像
cv::Mat testMat(100, 100, CV_8UC3, cv::Scalar(0, 255, 0));
std::cout << "Test matrix created, size: " << testMat.size() << std::endl;
// 如果有摄像头,尝试打开
cv::VideoCapture cap(0);
if(cap.isOpened()) {
std::cout << "Camera opened successfully" << std::endl;
cap.release();
} else {
std::cout << "No camera detected" << std::endl;
}
return 0;
}
交叉编译测试程序:
# 使用交叉编译器编译
zhengyang@ubuntu:/opt/2k0300/opencv_test$ loongarch64-linux-gnu-g++ test_opencv.cpp -o test_opencv \
-I/opt/2k0300/opencv-4.10.0/install/include/opencv4 \
-L/opt/2k0300/opencv-4.10.0/install/lib \
-lopencv_videoio \
-lopencv_highgui \
-lopencv_imgproc \
-lopencv_imgcodecs \
-lopencv_core \
-lpthread -lrt -ldl
zhengyang@ubuntu:/opt/2k0300/opencv_test$ ll
-rwxrwxr-x 1 zhengyang zhengyang 22520 3月 19 14:48 test_opencv*
-rw-rw-r-- 1 zhengyang zhengyang 686 3月 19 14:43 test_opencv.cpp
# 查看编译出的文件信息
zhengyang@ubuntu:/opt/2k0300/opencv_test$ file test_opencv
test_opencv: ELF 64-bit LSB executable, LoongArch, version 1 (SYSV), dynamically linked, interpreter /lib64/ld.so.1, for GNU/Linux 4.15.0, not stripped
注意:!!!执行接下来的流程前需要先升级开发板的镜像系统,升级流程参考后面的章节。
传输测试程序到龙芯核心板:
zhengyang@ubuntu:/opt/2k0300/opencv_test$ scp test_opencv root@你的龙芯IP:/home/root/
在龙芯板子上运行测试:
# SSH登录龙芯板子
zhengyang@ubuntu:/opt/2k0300/opencv_test$ ssh root@你的龙芯IP
# 运行测试程序
root@LoongOS:~$ ./test_opencv
如果看到类似下面的输出,说明OpenCV已经成功运行在龙芯平台上:
OpenCV version: 4.10.0
Test matrix created, size: [100 x 100]
Camera opened successfully
三、升级镜像制作概述
3.1 新世界
龙芯系统有两套不兼容的LoongArch生态,核心差异在底层标准、内核、软件兼容、发行版、使用场景 。
龙芯的旧世界(ABI 1.0)和新世界(ABI 2.0)是两套不兼容的软件生态体系。简单来说,旧世界是龙芯早期仓促推出的、未能完全融入开源主线的“过渡方案”;而新世界则是龙芯与开源社区合力打造的、代表现在与未来的“标准方案”。
3.1.1 新旧世界对比
| 对比维度 | 旧世界 (ABI 1.0) | 新世界 (ABI 2.0) |
|---|---|---|
| 内核版本 | 4.19 及更早版本 | 较新版本内核,主流为 6.x |
| 固件 (固件) | 基于旧版UEFI,使用BPI结构体传递信息 | 基于标准UEFI,使用系统表传递信息 |
| 内核镜像格式 | ELF格式,需旧版GRUB引导 | EFI Stub (PE格式),可直接由UEFI固件引导 |
| 代表性系统 | 麒麟、UOS V20、Loongnix 20 | Arch Linux、Debian、deepin v25、OpenEuler |
| 开源程度 | 部分底层代码未开放,难以二次开发 | 完全开源,可完整融入上游社区 |
| 生态与软件 | 有现成商业软件(如微信、QQ旧版),但版本老旧 | 软件正在适配,可通过 libLoL 兼容运行旧世界软件 |
3.1.2 PMON介绍
久久派2K0300核心板默认配套的是PMON固件以及linux 4.19的内核,PMON是一个兼有BIOS和boot loader部分功能的开放源码软件,多用于嵌入式系统。基于龙芯的系统采用PMON作为类BIOS兼boot loader,并在其基础上做了很多完善的工作,支持BIOS启动配置,内核加载,程序调试,内存寄存器显示、设置以及内存反汇编等。
PMON存放在板载的SPI0接口挂载的SPI Nor Flash,支持JTAG烧录、离线烧录。如果对PMON如何引导linux内核启动感兴趣,可以参考《Linux内核分析——基于LoongArch架构(Linux-6.0).pdf》内核初始化章节,核心板上电开机以后首先运行PMON,启动过程中根据配置文件,开始Linux内核启动过程;
boot.cfg文件指定内核文件的路径名(原始内核vmlinux或者压缩版内核vmlinuz);
default 0
timeout 2
showmenu 0
title 2k300 CC Update
kernel (usb0,0)/vmlinuz
initrd (usb0,0)/update.cpio.gz
args console=ttyS0,115200
这里我们不做过多的介绍,后面我们会将其升级为新世纪版本。
3.1.3 BSP 2.0
升级的源码来源官方仓库《 Docs-2K0300》。该仓库有两个BSP:
| 软件 | BSP1.0 | BSP2.0 |
|---|---|---|
| u-boot | u-boot 2022.04 | u-boot 2022.04 |
| linux | linux 5.10 | linux 6.12 |
| rootfs | buildroot 2021.02、openwrt 22.03、openharmony 4.1/5.1 | buildroot 2024.08、alpine linux 3.21、openwrt 24.10、openeuler embedded 24.03、openharmony 6.0 |
| cross-toolchain | gcc-8.3 | gcc-13.3 |
| 开发环境(推荐) | ubuntu 18.04 or ubuntu 20.04 | ubuntu 22.04 or ubuntu 24.04 |
这里我们使用BSP2.0,相关资料如下:
- 一键拉取源码与交叉工具链;
- 龙芯
2K0300先锋派&蜂鸟板源码编译操作指南-v2.0; - 广东龙芯
2K300先锋派&锋鸟板-v2.0:链接:https://pan.baidu.com/s/1FZcnFcmTGd5GcyP8ayFm5A?pwd=1234; python在线仓库;docker镜像在线仓库。
3.2 build-2k0300
build-2k030仓库可以快速搭建龙芯2k0300开发环境,下载源码:
zhengyang@ubuntu:/opt/2k0300$ git clone https://gitee.com/open-loongarch/build-2k0300.git
zhengyang@ubuntu:/opt/2k0300$ cd build-2k0300/
zhengyang@ubuntu:/opt/2k0300/build-2k0300$ ll
-rw-rw-r-- 1 zhengyang zhengyang 847 3月 19 19:42 README.en.md
-rw-rw-r-- 1 zhengyang zhengyang 374 3月 19 19:42 README.md
-rwxrwxr-x 1 zhengyang zhengyang 404 3月 19 19:42 set_env.sh*
-rwxrwxr-x 1 zhengyang zhengyang 1568 3月 19 19:42 start.sh*
运行以下命令拉取u-boot,kernel, buildroot源码与交叉工具链:
zhengyang@ubuntu:/opt/2k0300/build-2k0300$ ./start.sh
+ '[' '!' -e workspace ']'
+ mkdir workspace
+ cd workspace
+ echo '===================install some packages=================='
===================install some packages==================
+ sudo apt update
......
下载完成后查看workspace目录:
zhengyang@ubuntu:/opt/2k0300/build-2k0300$ ll workspace/
drwxrwxr-x 19 zhengyang zhengyang 4096 3月 19 19:49 buildroot-2024.08/
drwxrwxr-x 5 zhengyang zhengyang 4096 3月 19 19:50 cross-toolchain/
drwxrwxr-x 27 zhengyang zhengyang 4096 3月 19 19:49 linux-6.12/
-rw-rw-r-- 1 zhengyang zhengyang 404 3月 19 19:50 set_env.sh
drwxrwxr-x 25 zhengyang zhengyang 4096 3月 19 19:46 u-boot/
3.2.1 start.sh源码
start.sh脚本用于快速获取并配置交叉编译工具链、u-boot、内核源码以及Buildroot;
#!/bin/bash
set -ex
if [ ! -e workspace ]; then
mkdir workspace
fi
cd workspace
echo "===================install some packages=================="
sudo apt update
sudo apt install -y git vim openssh-server
sudo apt install -y build-essential make gcc g++ bison flex libssl-dev libelf-dev cmake pigz
echo "===================get u-boot==============================="
if [ ! -e u-boot ]; then
git clone https://gitee.com/open-loongarch/u-boot.git
fi
echo "===================get kernel==============================="
if [ ! -e linux-6.12 ]; then
git clone https://gitee.com/open-loongarch/linux-6.12.git
fi
echo "===================get buildroot==============================="
if [ ! -e buildroot-2024.08 ]; then
git clone https://gitee.com/open-loongarch/buildroot-2024.08.git
fi
echo "===================get cross toolchain==============================="
if [ ! -e cross-toolchain ]; then
git clone https://gitee.com/open-loongarch/cross-toolchain.git
fi
#wget https://gitee.com/open-loongarch/cross-toolchain/raw/master/gcc-13/loongarch64-linux-gnu-gcc13.3.tar.xz
#wget https://gitee.com/open-loongarch/cross-toolchain/raw/master/gcc-13/loongarch64-linux-gnu-gcc13.3.tar.xz.md5
pushd cross-toolchain/gcc-13
md5sum -c loongarch64-linux-gnu-gcc13.3.tar.xz.md5
if [ $? -eq 0 ] ; then
sudo tar xf loongarch64-linux-gnu-gcc13.3.tar.xz -C /opt
echo "toolchain decompress success."
else
echo "toolchain not incomplete, please try again."
fi
popd
if [ ! -e set_env.sh ]; then
wget https://gitee.com/open-loongarch/build-2k0300/raw/master/set_env.sh
fi
3.2.2 start.sh分析
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1. 准备工作区 | 创建 workspace目录并进入 | 所有下载的源码都会放在这个目录下,保持整洁。 |
| 2. 安装系统依赖 | apt install 一系列包 | 包括编译工具(build-essential)、版本控制(git)、编辑器(vim)、SSH 服务、SSL 开发库、CMake 等。这些是编译内核、U-Boot 和 Buildroot 所必需的。 |
| 3. 获取uboot源码 | 克隆 open-loongarch/u-boot.git | 这是龙芯平台的uboot引导程序源码。 |
| 4. 获取内核源码 | 克隆 open-loongarch/linux-6.12.git | 内核版本为 6.12 |
| 5. 获取 Buildroot | 克隆 open-loongarch/buildroot-2024.08.git | Buildroot 是一个用来构建嵌入式 Linux 系统的工具,可以自动生成交叉编译工具链、根文件系统、内核和 bootloader。 |
| 6. 下载交叉编译工具链 | 从 Loongnix 下载 gcc13 工具链(13版本) |
工具链是 x86 主机上编译 LoongArch 程序的关键。脚本会下载 .tar.xz 包及其 MD5 校验文件,验证完整性后解压到 /opt,并创建一个符号链接 /opt/loongarch64-linux-gnu-gcc13.3 指向具体版本目录,方便 Buildroot 等工具引用。 |
| 7. 下载环境设置脚本 | 获取 set_env.sh |
用于设置交叉编译所需的环境变量(如 PATH、CROSS_COMPILE 等),方便后续手动编译。 |
3.2.3 set_env.sh
#!/bin/bash
set -ex
function setup_loongarch_env()
{
echo "====>setup env for LoongArch..."
CC_PREFIX=/opt/loongarch64-linux-gnu-gcc13.3
export PATH=$CC_PREFIX/bin:$PATH
export LD_LIBRARY_PATH=$CC_PREFIX/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$CC_PREFIX/loongarch64-linux-gnu/lib64:$LD_LIBRARY_PATH
export ARCH=loongarch
export CROSS_COMPILE=loongarch64-linux-gnu-
}
setup_loongarch_env
四、编译uboot
4.1 下载源码
源码位于《https://gitee.com/open-loongarch/u-boot.git》,版本为u-boot 2022.04,前面我们已经下载了;
zhengyang@ubuntu:/optcfbuild-2k0300$ ll workspace/u-boot/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:46 api/
drwxrwxr-x 16 zhengyang zhengyang 4096 3月 19 19:46 arch/
drwxrwxr-x 172 zhengyang zhengyang 4096 3月 19 19:46 board/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:46 boot/
-rwxrwxr-x 1 zhengyang zhengyang 622 3月 19 19:46 buildenv.sh*
drwxrwxr-x 9 zhengyang zhengyang 4096 3月 19 19:46 cmd/
drwxrwxr-x 5 zhengyang zhengyang 4096 3月 19 19:46 common/
-rw-rw-r-- 1 zhengyang zhengyang 2198 3月 19 19:46 config.mk
drwxrwxr-x 2 zhengyang zhengyang 65536 3月 19 19:46 configs/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:46 disk/
drwxrwxr-x 19 zhengyang zhengyang 4096 3月 19 19:46 doc/
drwxrwxr-x 71 zhengyang zhengyang 4096 3月 19 19:46 drivers/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:46 dts/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:46 env/
drwxrwxr-x 4 zhengyang zhengyang 4096 3月 19 19:46 examples/
drwxrwxr-x 15 zhengyang zhengyang 4096 3月 19 19:46 fs/
drwxrwxr-x 8 zhengyang zhengyang 4096 3月 19 19:46 .git/
drwxrwxr-x 35 zhengyang zhengyang 20480 3月 19 19:46 include/
-rw-rw-r-- 1 zhengyang zhengyang 783 3月 19 19:46 Kbuild
-rw-rw-r-- 1 zhengyang zhengyang 16610 3月 19 19:46 Kconfig
drwxrwxr-x 24 zhengyang zhengyang 4096 3月 19 19:46 lib/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:46 Licenses/
-rw-rw-r-- 1 zhengyang zhengyang 36667 3月 19 19:46 MAINTAINERS
-rw-rw-r-- 1 zhengyang zhengyang 83272 3月 19 19:46 Makefile
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:46 net/
drwxrwxr-x 5 zhengyang zhengyang 4096 3月 19 19:46 post/
-rw-rw-r-- 1 zhengyang zhengyang 135222 3月 19 19:46 README
drwxrwxr-x 6 zhengyang zhengyang 4096 3月 19 19:46 scripts/
-rwxrwxr-x 1 zhengyang zhengyang 1420 3月 19 19:46 set_env.sh*
drwxrwxr-x 15 zhengyang zhengyang 4096 3月 19 19:46 test/
drwxrwxr-x 15 zhengyang zhengyang 4096 3月 19 19:46 tools/
4.2 配置
uboot的编译分为两步:配置、编译。单板的默认配置在configs目录下,这里根据我们实际使用的板子进行选择;
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/u-boot$ ll configs/*2k*
-rw-rw-r-- 1 zhengyang zhengyang 4727 3月 19 19:46 configs/loongson_2k1000_dp_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 4495 3月 19 19:46 configs/loongson_2k300_99pi_tf_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 4499 3月 19 19:46 configs/loongson_2k300_99pi_wifi_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 4483 3月 19 19:46 configs/loongson_2k300_atk_dl2k0300b_v01_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 4586 3月 19 19:46 configs/loongson_2k300_gongkong_gbkpgk0_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 4495 3月 19 19:46 configs/loongson_2k300_mini_dp_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 4621 3月 19 19:46 configs/loongson_2k300_pai_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 4435 3月 19 19:46 configs/loongson_2k500_mini_dp_defconfig
比如:
先锋派 configs/loongson_2k300_pai_defconfig
蜂鸟板 configs/loongson_2k300_mini_dp_defconfig
久久派(wifi) configs/loongson_2k300_99pi_wifi_defconfig
这里我们使用久久派的核心板,选择configs/loongson_2k300_99pi_wifi_defconfig,如果我们想做一些配置的修改,可以参考《Rockchip RK3399 - TPL/SPL方式加载uboot》。
执行如下命令,生成.config文件:
# 彻底清理所有配置和编译产物
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/u-boot$ make distclean
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/u-boot$ source ../set_env.sh && make loongson_2k300_99pi_wifi_defconfig V=1
configs/loongson_2k300_99pi_wifi_defconfig是“顶层开关”,决定 “编译哪些功能”(如是否支持WiFi、是否启用SPL、环境变量存哪)。下面我按类别整理出最关键的部分并解释其含义;
4.2.1 芯片架构与板级配置
| 配置项 | 值 | 含义 |
|---|---|---|
CONFIG_LOONGARCH=y |
启用 | 目标架构为 LoongArch(龙芯指令集)。 |
CONFIG_SOC_LS2K300=y |
启用 | 指定 SoC 为龙芯 2K0300(内部型号 LS2K300)。 |
CONFIG_TARGET_LS2K300_99PI_WIFI=y |
启用 | 指定板级目标为 久久派 WiFi 版,与 TF 卡版配置区分。 |
CONFIG_CPU_1000MHZ=y |
启用 | CPU 主频设为 1.0 GHz。 |
4.2.2 内存布局与加载地址
| 配置项 | 值 | 含义 |
|---|---|---|
CONFIG_SYS_TEXT_BASE=0x900000000ec00000 |
地址 | uboot proper 在内存中的运行起始地址(链接地址)。 |
CONFIG_SPL_TEXT_BASE=0x9000000090000000 |
地址 | SPL 在内存中的运行地址。 |
CONFIG_SYS_LOAD_ADDR=0x9000000003000000 |
地址 | 加载内核镜像(如 uImage)的默认内存地址。 |
CONFIG_SYS_MALLOC_LEN=0x1000000 |
16 MB | uboot 动态内存分配池大小(堆空间)。 |
CONFIG_SPL_SIZE_LIMIT=0x40000 |
256 KB | SPL 的二进制大小限制(不得超过此值)。 |
4.2.3 SPL(Secondary Program Loader)配置
| 配置项 | 值 | 含义 |
|---|---|---|
CONFIG_SPL=y |
启用 | 启用 SPL 编译。SPL 负责初始化内存并加载主uboot。 |
CONFIG_SPL_SPI_FLASH_SUPPORT=y |
启用 | SPL 可以从 SPI Flash 读取数据。 |
CONFIG_SPL_SPI=y |
启用 | SPL 支持 SPI 总线。 |
CONFIG_SPL_PAYLOAD="u-boot.img" |
文件名 | SPL 加载的下一级程序为 u-boot.img(即主uboot镜像)。 |
CONFIG_SPL_STACK_R=y |
启用 | SPL 在重定位到内存后使用新的栈。 |
CONFIG_SPL_STACK_R_ADDR=0x9000000002000000 |
地址 | SPL 重定位后的栈地址。 |
4.2.4 存储介质与启动设备
| 配置项 | 值 | 含义 |
|---|---|---|
CONFIG_ENV_IS_IN_SPI_FLASH=y |
启用 | uboot 环境变量存储在 SPI Flash 中。 |
CONFIG_ENV_OFFSET=0xe7000 |
偏移 | 环境变量在 SPI Flash 中的起始偏移(924KB 之后)。 |
CONFIG_ENV_SIZE=0x4000 |
16 KB | 环境变量占用空间。 |
CONFIG_CMD_MTDPARTS=y |
启动 | 支持mtdparts命令,启用后,可以执行 mtdparts 查看当前Flash分区布局,使用mtdparts default恢复默认分区表,或者用mtdparts add动态调整分区。 |
NFIG_MTDIDS_DEFAULT="nor0=spi0.0" |
nor0=spi0.0 | 在嵌入式系统中,可能有多个Flash设备(例如Nor和 Nand),通过 MTDIDS 将每个物理设备映射到一个逻辑名称,方便在分区表中引用。这里nor0是给该设备取的逻辑名称,spi0.0 表示该设备对应SPI控制器0上的片选0(即SPI Nor Flash芯片) |
CONFIG_MTDPARTS_DEFAULT=... |
spi0.0: 924k(uboot), 32k(uboot_env), 4k(bdinfo), 52k(dtb), 4k(bdinfo_e), 8k(ddr_context) |
定义 SPI Flash 分区布局(uboot、uboot_env、dtb 等)。 |
CONFIG_MMC=y |
启用 | 支持 MMC/SD 卡。 |
CONFIG_LOONGSON_MMC_HIGH_PERFORMANCE=y |
启用 | 启用高性能 MMC 模式。 |
CONFIG_SPL_SPI_FLASH_MTD=y |
启用 | SPL 通过 MTD 层访问 SPI Flash。 |
我们首先来介绍一下什么是分区,其实linux系统下的各个分区和windows系统下的各个盘类似, 比如我们有一个硬盘,在windows系统中,我们一般会把硬盘分为四个盘,C盘为系统盘,然后D、E、F盘用来放各种类型文件。
同理,我们可以对Flash进行分盘,比如划分一个盘用来放uboot、再划分一个盘用来放uboot_env,只不过在linux系统下,这个操作叫做叫分区。
分区表信息如下:
| 分区名 | 大小 | 起始偏移(累计) | 用途说明 |
|---|---|---|---|
uboot |
924 KB | 0x00000 | 存放 uboot 镜像(包括SPL和主uboot合并后的二进制),只比我们编译出来的u-boot-with-spl.bin大一点点 |
uboot_env |
32 KB | 0xE7000 (924K) | 存放 uboot 环境变量(默认参数、启动命令等) |
bdinfo |
4 KB | 0xEF000 (956K) | 可能用于存储板卡信息(Board Info),如序列号、硬件版本等 |
dtb |
52 KB | 0xF0000 (960K) | 存放设备树二进制文件(Device Tree Blob) |
bdinfo_e |
4 KB | 0xFD000 (1012K) | 可能是 bdinfo 的备份或扩展 |
ddr_context |
8 KB | 0xFE000 (1016K) | 存储 DDR 初始化训练参数(用于快速启动或恢复) |
总占用大小 = 924+32+4+52+4+8 = 1024 KB = 1 MB。
4.2.5 启动参数与启动命令
| 配置项 | 值 | 含义 |
|---|---|---|
CONFIG_BOOTARGS=... |
console=ttyS0,115200 rw noinitrd init=/sbin/init rootfstype=ext4 rootwait |
内核启动参数。指定串口控制台、根文件系统类型、分区等。 |
CONFIG_BOOTCOMMAND=... |
setenv bootargs ${bootargs} root=/dev/mmcblk0p${syspart} mtdparts=${mtdparts} fbcon=rotate:${rotate} panel=${panel};sf probe;sf read ${fdt_addr} dtb;ext4load mmc 0:${syspart} ${loadaddr} /boot/uImage;bootm |
uboot启动时自动执行的命令。流程: 1. 设置 bootargs; 2. 从 SPI Flash 读取设备树 ( dtb);3. 从 eMMC 分区 /boot/uImage 加载内核;4. 启动内核 ( bootm)。 |
CONFIG_BOOTDELAY=0 |
0 秒 | 自动启动倒计时为 0,不等待用户干预直接启动(除非按下 c 或 m 进入菜单)。 |
CONFIG_AUTOBOOT_KEYED=y |
启用 | 允许通过按键中断自动启动。 |
CONFIG_AUTOBOOT_DELAY_STR="m" |
键 | 按住 m 键可进入uboot菜单(或手动模式)。 |
CONFIG_AUTOBOOT_STOP_STR="c" |
键 | 按住 c 键可进入uboot命令行。 |
内核启动参数CONFIG_BOOTARGS这个字符串会在内核启动时传递给内核,告诉内核如何初始化硬件、挂载根文件系统等。
| 参数 | 含义 | 详细说明 |
|---|---|---|
console=ttyS0,115200 |
控制台输出 | 使用串口0作为控制台,波特率115200。这样内核启动信息会通过串口打印,方便调试。 |
rw |
根文件系统读写挂载 | 将根文件系统以可读写模式挂载。若为 ro 则为只读。 |
noinitrd |
不使用 initrd | 告诉内核不要使用初始内存盘(initrd/initramfs),根文件系统直接由内核挂载。 |
init=/sbin/init |
指定 init 进程 | 内核启动后执行的第一个用户态程序,通常是 /sbin/init(系统初始化进程)。 |
rootfstype=ext4 |
根文件系统类型 | 明确指定根文件系统格式为 ext4,避免内核自动探测可能出错。 |
rootwait |
等待根设备就绪 | 让内核等待直到根设备(如 MMC 卡)准备好再挂载,避免因设备初始化慢导致挂载失败。 |
启动命令CONFIG_BOOTCOMMAND在启动倒计时结束后自动执行。它负责准备内核启动参数、加载设备树和内核镜像,然后启动内核;
-
setenv bootargs ${bootargs} root=/dev/mmcblk0p${syspart} mtdparts=${mtdparts} fbcon=rotate:${rotate} panel=${panel};-
修改环境变量
bootargs(内核启动参数),${bootargs}是原有的CONFIG_BOOTARGS的值; -
追加
root=/dev/mmcblk0p${syspart}:指定根文件系统所在设备。${syspart}是另一个环境变量,通常代表系统分区号(比如1或2),这里用于动态选择启动分区; -
追加
mtdparts=${mtdparts}:传递MTD分区信息,让内核知道SPI Nor Flash的分区布局; -
追加
fbcon=rotate:${rotate}:设置帧缓冲控制台旋转角度(可能用于屏幕显示方向); -
追加
panel=${panel}:指定显示屏面板类型;
-
-
sf probe:初始化SPI控制器并探测Flash芯片,由于我们使用的开发板SPI 0外接了SPI Nor Flash,因此可以探测 到该Nor Flash芯片; -
sf read ${fdt_addr} dtb;-
从
SPI Nor Flash中读取设备树二进制文件(dtb分区)到内存地址${fdt_addr}; -
${fdt_addr}通常是环境变量,预先设置好;
-
-
ext4load mmc 0:${syspart} ${loadaddr} /boot/uImage:- 从
MMC设备(第0个MMC控制器)的系统分区(${syspart})中加载/boot/uImage文件到内存地址${loadaddr}; - 内核镜像明确是
/boot/uImage,说明根文件系统的/boot目录下存放着内核镜像。
- 从
-
bootm:启动内核,bootm会根据内存中的镜像类型(uImage)自动处理,并跳转到内核入口点。内核将使用前面设置的bootargs启动,如果对启动命令有兴趣可以参考《Mini2440之uboot移植流程之linux内核启动分析(六)》。
loadaddr的值来自配置参数CONFIG_SYS_LOAD_ADDR,fdt_addr的值来自配置参数FDT_ADDR,其在板级配置头文件(具体参考include/configs/loongson_common.h)中通过 CONFIG_EXTRA_ENV_SETTINGS 宏定义的;
#define FDT_ADDR 0x900000000a000000
#define CONFIG_EXTRA_ENV_SETTINGS \
CONSOLE_STDOUT_SETTINGS \
LOONGSON_BOOTMENU \
LOONGSON_BOOTMENU_VIDEO \
LOONGSON_BOOTMENU_DELAY \
"nand_pagesize=2048\0" \
"loadaddr=" __stringify(CONFIG_SYS_LOAD_ADDR) "\0" \
"fdt_addr=" __stringify(FDT_ADDR) "\0" \
"fdt_size=" __stringify(FDT_SIZE) "\0" \
"rd_start=" __stringify(RD_ADDR) "\0" \
"rd_size=" __stringify(RD_SIZE) "\0" \
"mtdids=" CONFIG_MTDIDS_DEFAULT "\0" \
"mtdparts=" CONFIG_MTDPARTS_DEFAULT "\0" \
"splashpos=m,m\0" \
"panel=default\0" \
"rotate=0\0" \
"syspart=1\0" \
"syspart_last=4\0" \
"syspart_ch=0\0"
所以总结下来就是:
① 首先将板载的SPI Nor Flash设备dtb分区数据加载到内存地址fdt_addr;
② 接着将板载的eMMC设备${syspart}分区下的/boot/uImage文件加载到内存中;
③ 使用bootm命令启动kernel,执行 bootm 时不带参数,uboot会使用环境变量 loadaddr 的值作为内核镜像的加载地址,使用环境变量 fdt_addr 的值作为设备树的加载地址。
4.2.6 设备树
| 配置项 | 值 | 含义 |
|---|---|---|
CONFIG_DEFAULT_DEVICE_TREE="ls2k300_99pi_wifi" |
字符串 | 编译时使用的设备树文件(.dts)名称 |
CONFIG_OF_BOARD=y |
启用 | 在引导内核时不会使用编译时固定嵌入的默认设备树,而是从板载存储(如 SPI Flash、eMMC、SD 卡等)中动态读取一个设备树文件,并将其传递给内核。 |
4.2.7 外设支持
| 配置项 | 值 | 含义 |
|---|---|---|
CONFIG_DM_ETH=y |
启用 | 支持以太网(DM 驱动模型)。 |
CONFIG_ETH_DESIGNWARE=y |
启用 | 使用 Synopsys DesignWare 以太网控制器(龙芯 2K0300 内置)。 |
CONFIG_USB_EHCI_HCD=y |
启用 | 支持 USB 2.0 EHCI 主机控制器。 |
CONFIG_USB_STORAGE=y |
启用 | 支持 USB 存储设备(U 盘)。 |
CONFIG_DM_VIDEO=y |
启用 | 支持视频输出(如 HDMI 显示)。 |
CONFIG_VIDEO_LOONGSON=y |
启用 | 使用龙芯内置显示控制器。 |
CONFIG_WDT=y |
启用 | 看门狗定时器。 |
CONFIG_WDT_LS2X=y |
启用 | 龙芯 2K 系列专用看门狗驱动。 |
4.2.8 调试与信息输出
| 配置项 | 值 | 含义 |
|---|---|---|
CONFIG_LOGLEVEL=7 |
7 | 内核启动时的日志级别(最高,输出所有调试信息)。 |
CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y |
启用 | 允许覆盖控制台输出函数(便于调试)。 |
CONFIG_SPL_SHOW_ERRORS=y |
启用 | SPL 阶段输出详细错误信息。 |
CONFIG_DISPLAY_BOARDINFO=y |
启用 | 启动时打印板卡信息。 |
4.2.9 其他关键项
| 配置项 | 值 | 含义 |
|---|---|---|
CONFIG_SYS_RELOC_GD_ENV_ADDR=y |
启用 | 重定位后全局数据(gd)中环境变量地址会被更新。 |
CONFIG_PHY_LS2K_USB=y |
启用 | 龙芯 USB PHY 驱动。 |
CONFIG_LOONGSON_RECOVER=y |
启用 | 可能用于恢复模式(如通过串口刷写)。 |
CONFIG_LOONGSON_BOARD_MMC_FS=y |
启用 | 支持从 MMC 文件系统加载内核。 |
CONFIG_SPL_SIZE_LIMIT_SUBTRACT_GD=y |
启用 | 计算 SPL 大小时减去全局数据(gd)占用的空间。 |
4.3 编译
执行make命令,生成u-boot文件:
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/u-boot$ source ../set_env.sh && make
......
LD spl/u-boot-spl
OBJCOPY spl/u-boot-spl-nodtb.bin
mkdir -p spl/dts/
FDTGREP spl/dts/dt-spl.dtb
COPY spl/u-boot-spl.dtb
CAT spl/u-boot-spl-dtb.bin
COPY spl/u-boot-spl.bin
SYM spl/u-boot-spl.sym
MKIMAGE u-boot.img
COPY u-boot.dtb
MKIMAGE u-boot-dtb.img
CAT u-boot-with-spl.bin
CFGCHK u-boot.cfg
OFCHK .config
在uboot根录下生成文件有:
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/u-boot$ ll u-boot* Sys*
+ ls --color=auto -alF u-boot u-boot.bin u-boot.cfg u-boot.cfg.configs u-boot.dtb u-boot-dtb.bin u-boot-dtb.img u-boot.img u-boot.lds u-boot.map u-boot-nodtb.bin u-boot.srec u-boot.sym u-boot-with-spl.bin System.map
-rw-rw-r-- 1 zhengyang zhengyang 105909 3月 19 20:31 System.map
-rwxrwxr-x 1 zhengyang zhengyang 1029832 3月 19 20:31 u-boot*
-rw-rw-r-- 1 zhengyang zhengyang 762423 3月 19 20:31 u-boot.bin
-rw-rw-r-- 1 zhengyang zhengyang 15540 3月 19 20:28 u-boot.cfg
-rw-rw-r-- 1 zhengyang zhengyang 9438 3月 19 20:31 u-boot.cfg.configs
-rw-rw-r-- 1 zhengyang zhengyang 8647 3月 19 20:31 u-boot.dtb
-rw-rw-r-- 1 zhengyang zhengyang 762423 3月 19 20:31 u-boot-dtb.bin
-rw-rw-r-- 1 zhengyang zhengyang 762487 3月 19 20:31 u-boot-dtb.img
-rw-rw-r-- 1 zhengyang zhengyang 762487 3月 19 20:31 u-boot.img
-rw-rw-r-- 1 zhengyang zhengyang 1044 3月 19 20:31 u-boot.lds
-rw-rw-r-- 1 zhengyang zhengyang 868565 3月 19 20:31 u-boot.map
-rwxrwxr-x 1 zhengyang zhengyang 753776 3月 19 20:31 u-boot-nodtb.bin*
-rwxrwxr-x 1 zhengyang zhengyang 2261458 3月 19 20:31 u-boot.srec*
-rw-rw-r-- 1 zhengyang zhengyang 208415 3月 19 20:31 u-boot.sym
-rw-rw-r-- 1 zhengyang zhengyang 940876 3月 19 20:31 u-boot-with-spl.bin
由于开启了SPL,因此,在编译uboot时会额外单独编译SPL,编译产生的镜像文件就存放在./spl下。这下面的镜像生成方式与uboot基本是一模一样的。
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/u-boot$ ls spl
arch boot common drivers env include u-boot.cfg u-boot-spl.bin u-boot-spl-dtb.bin u-boot-spl.map u-boot-spl-pad.bin
board cmd disk dts fs lib u-boot-spl u-boot-spl.dtb u-boot-spl.lds u-boot-spl-nodtb.bin u-boot-spl.sym
这里我们稍微提一下TPL 和SPL,TPL和SPL是uboot中为了应对复杂启动环境而设计的多级引导加载程序。可以把整个启动过程想象成一场接力赛,每个Loader都是其中一棒,负责完成特定的初始化任务,然后将“接力棒”(执行权)交给下一棒。
| 启动阶段 | 通俗比喻 | 核心任务 | 运行环境限制 | 对应产物 |
|---|---|---|---|---|
| BootROM | 发令枪 | 芯片出厂固化的程序,上电即运行。它会进行最基本的检查,并从预定义的介质(如SD卡、eMMC、SPI Flash)中加载并执行下一段代码(通常是 SPL 或 TPL)。 | 容量极小(KB级别),不可修改。 | 固化在芯片内部 |
| TPL (Tertiary Program Loader) | 侦察兵 | 极早期初始化。它存在的唯一原因是,在某些复杂的芯片上,连SPL都显得太大了 。TPL的任务极其精简,例如仅初始化基本的时钟和一小部分内存,为加载稍大一些的SPL铺平道路。 | 容量要求比BootROM稍大,但仍然非常小(例如16KB以内),通常运行在芯片内部 SRAM中。 | u-boot-tpl.bin |
| SPL (Secondary Program Loader) | 工兵 | 关键初始化与加载。这是最常见的一级loader。它的主要任务是初始化系统主内存(如DDR),然后从存储设备(如eMMC、SD卡)中将完整功能的 uboot proper加载到内存中。 | 容量有严格限制(例如 64KB 左右),运行在内部SRAM或刚初始化好的内存中。 | u-boot-spl.bin |
| uboot proper | 主力部队 | 完整引导与管理。这就是我们通常说的uboot,拥有完整的命令行、文件系统驱动、网络协议栈等丰富功能。它负责加载并启动操作系统内核(如 Linux)。 | 容量较大(几百KB甚至更大),运行在完整的主内存(DDR)中。 | u-boot.bin 或 u-boot.img |
芯片刚上电时,内部资源非常有限(只有一小块SRAM可用),无法直接运行功能复杂的uboot。因此,必须通过一个或两个“轻量级”的加载程序,先把最基本的环境(尤其是内存)搭建好,才能把“大部队”请进来。
如果对uboot编译流程感兴趣,可以参考以下几篇文章的思路阅读源代码;
在编译过程中我们主要关注两块内容:
- 链接脚本
u-boot.lds; - 配置文件
configs/loongson_2k300_99pi_wifi_defconfig,在执行配置时生成.config、include/generated/autoconf.h、include/config.h文件,在执行编译时生成include/config/auto.conf;include/config/auto.conf:因为uboot支持了很多的架构和内核,在顶层Makefile引入该文件,这样在编译过程中就可以根据auto.conf中宏的定义编译不同的库文件;include/generated/autoconf.h:在编译build-in.o目标时引入,这样就可以在代码中引入相应的宏从而实现根据不同宏编译不同代码。
4.3.1 u-boot.lds
链接文件内容如下:
OUTPUT_ARCH("loongarch")
ENTRY(_start)
SECTIONS
{
. = ALIGN(4);
.text : {
__image_copy_start = .;
__text_start = .;
arch/loongarch/cpu/start.o (.text*)
*(.text*)
__text_end = .;
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : {
*(.data*)
}
. = ALIGN(4);
.sdata : {
*(.sdata*)
}
. = ALIGN(4);
.got : {
__got_start = .;
*(.got*)
__got_end = .;
}
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
. = ALIGN(4);
.plt : { *(.plt*) }
. = ALIGN(4);
__image_copy_end = .;
......
}
ENTRY指定输出可执行文件的其实入口码段是_start,_start在arch/loongarch/cpu/start.S;
/*
* Copyright (c) 2021 Loongson Technology Corporation Limited (www.loongson.cn)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Opsycon AB, Sweden.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#ifndef _KERNEL
#define _KERNEL
#endif
#include <asm-offsets.h>
#include <asm/asm.h>
#include <asm/regdef.h>
#include <asm/loongarch.h>
#include <asm/addrspace.h>
#include <config.h>
#include <mach/loongson.h>
#define PRINT_EXCEPTION_PROMPT \
li.w a0, 'e'; \
bl printchar; \
li.w a0, 'x'; \
bl printchar; \
.....
这里引入了config.h文件,即include/config.h。
4.3.2 include/config.h
configs/loongson_2k300_99pi_wifi_defconfig我们在前面已经介绍过了,我们主要来看一下include/config.h;
/* Automatically generated - do not edit */
#define CONFIG_BOARDDIR board/loongson/ls2k300
#include <config_uncmd_spl.h>
#include <configs/loongson_2k300.h>
#include <asm/config.h>
#include <linux/kconfig.h>
#include <config_fallbacks.h>
重点关注#include <configs/loongson_2k300.h>。
4.3.3 include/configs/loongson_2k300.h>
configs/loongson_2k300.h在include/configs目录下,这个文件这个主要是 “底层硬件说明书”,决定 “具体数值”(如内存地址、时钟频率、板级物理参数);
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* DEV_LS2K500 configuration
*
* Copyright (c) 2022 Loongson Technologies
* Author: Xiaochuan Mao<[email protected]>
*/
#ifndef __LOONGSON_LA_COMMON_H__
#define __LOONGSON_LA_COMMON_H__
#include <linux/sizes.h>
#include "loongson_common.h"
/* Loongson LS2K300 clock configuration. */
#define REF_120M
#ifdef REF_120M
#define REF_FREQ 120 //参考时钟固定为120MHz
#else
#define REF_FREQ 100 //参考时钟固定为100MHz
#endif
#define CORE_FREQ CONFIG_CPU_FREQ //现在CPU的时钟在 make menuconfig 里面选择
#define DDR_FREQ 800 //MEM 800Mhz
#define APB_FREQ 200 //SB 100~200MHz, for BOOT, USB, APB, SDIO
#define NET_FREQ 200 //NETWORK 200~400MHz, for NETWORK, DC
/* Memory configuration */
#define CONFIG_SYS_BOOTPARAMS_LEN SZ_64K
#define CONFIG_SYS_SDRAM_BASE (0x9000000000000000) /* cached address, use the low 256MB memory */
#define CONFIG_SYS_SDRAM_SIZE (SZ_256M)
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
#ifdef CONFIG_SPL_BUILD
#define CONFIG_SPL_MAX_SIZE SZ_256K
#define CONFIG_SPL_STACK 0x9000000090040000
#endif
/* UART configuration */
#define CONSOLE_BASE_ADDR LS_UART0_REG_BASE
/* NS16550-ish UARTs */
#define CONFIG_SYS_NS16550_CLK (APB_FREQ * 1000000) // CLK_in: 100MHz
#define CONFIG_SYS_CBSIZE 4096 /* Console I/O buffer size */
#define CONFIG_SYS_MAXARGS 32 /* Max number of command args */
#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot argument buffer size */
/* Miscellaneous configuration options */
#define CONFIG_SYS_BOOTM_LEN (64 << 20)
/* Environment settings */
// #define CONFIG_ENV_SIZE 0x4000 /* 16KB */
#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
// #define CONFIG_ENV_SIZE 0x4000 /* 16KB */
/*
* Environment is right behind U-Boot in flash. Make sure U-Boot
* doesn't grow into the environment area.
*/
//#define CONFIG_BOARD_SIZE_LIMIT CONFIG_ENV_OFFSET
#define CONFIG_BOARD_SIZE_LIMIT 0x180000
#endif
/* GMAC configuration */
#define CONFIG_DW_ALTDESCRIPTOR // for designware ethernet driver.
/* OHCI configuration */
#ifdef CONFIG_USB_OHCI_HCD
#define CONFIG_USB_OHCI_NEW
#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1
#endif
/* video configuration */
// #define DISPLAY_BANNER_ON_VIDCONSOLE
#define DBG_ASM
#endif /* __LOONGSON_LA_COMMON_H__ */
#include "loongson_common.h"引入板级通用配置。
4.3.4 宏定义查找总结
我们在阅读源代码的时候,判断一个宏有没有定义,我们重点关注以下两个文件:
include/generated/autoconf.h;include/configs/loongson_common.h;include/configs/loongson_2k300.h。
4.4 u-boot-with-spl.bin
u-boot-with-spl.bin是我们后续烧录要用到的二进制文件,其生
成命令位于.u-boot-with-spl.bin.cmd文件:
loongarch64-linux-gnu-objcopy --gap-fill=0xff -O elf64-loongarch -I binary -O binary --pad-to=0 spl/u-boot-spl.bin u-boot-with-spl.bin
cat u-boot.img >> u-boot-with-spl.bin || { rm -f u-boot-with-spl.bin; false; }
其中:
- 第一步使用
objcopy处理SPL,实际效果相当于cp spl/u-boot-spl.bin u-boot-with-spl.bin,但通过objcopy保留了将来可能的填充需求; - 第二步将
u-boot.img的内容追加到u-boot-with-spl.bin的末尾。
最终生成的 u-boot-with-spl.bin 就包含了SPL + 主uboot的完整内容。这样烧录到板子上后,启动流程就是:当芯片上电,内置的BootROM会从这个NOR Flash的固定位置读取 u-boot-spl.bin到TCM中执行,SPL初始化内存后,再从 NOR Flash的后续位置加载完整的u-boot.img到内存中,最后跳转到uboot执行。
更多细节可以参考:《U-Boot源码解析(龙芯版)_1.pdf》。
4.5 复制mkimage
复制mkimage 到/usr/bin, 后面编译内核时需要用到;
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/u-boot$ cd tools/
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/u-boot/tools$ sudo cp mkimage /usr/bin/
五、编译内核
5.1 源码下载
源码位于《clone https://gitee.com/open-loongarch/linux-6.12.git》,版本为linux-6.12.git,前面我们已经下载了;
zhengyang@ubuntu:/opt/2k0300/build-2k0300$ ll workspace/linux-6.12/
drwxrwxr-x 23 zhengyang zhengyang 4096 3月 19 19:48 arch/
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 19 19:48 block/
-rwxrwxr-x 1 zhengyang zhengyang 640 3月 19 19:48 buildenv.sh*
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:48 certs/
-rw-rw-r-- 1 zhengyang zhengyang 22878 3月 19 19:48 .clang-format
-rw-rw-r-- 1 zhengyang zhengyang 59 3月 19 19:48 .cocciconfig
-rw-rw-r-- 1 zhengyang zhengyang 496 3月 19 19:48 COPYING
-rw-rw-r-- 1 zhengyang zhengyang 105095 3月 19 19:48 CREDITS
drwxrwxr-x 4 zhengyang zhengyang 4096 3月 19 19:48 crypto/
drwxrwxr-x 75 zhengyang zhengyang 4096 3月 19 19:48 Documentation/
drwxrwxr-x 143 zhengyang zhengyang 4096 3月 19 19:48 drivers/
-rw-rw-r-- 1 zhengyang zhengyang 575 3月 19 19:48 .editorconfig
drwxrwxr-x 81 zhengyang zhengyang 4096 3月 19 19:49 fs/
-rw-rw-r-- 1 zhengyang zhengyang 194 3月 19 19:48 .get_maintainer.ignore
drwxrwxr-x 8 zhengyang zhengyang 4096 3月 19 19:49 .git/
-rw-rw-r-- 1 zhengyang zhengyang 105 3月 19 19:48 .gitattributes
-rw-rw-r-- 1 zhengyang zhengyang 2174 3月 19 19:48 .gitignore
drwxrwxr-x 32 zhengyang zhengyang 4096 3月 19 19:49 include/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:49 init/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:49 io_uring/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:49 ipc/
-rw-rw-r-- 1 zhengyang zhengyang 2573 3月 19 19:48 Kbuild
-rw-rw-r-- 1 zhengyang zhengyang 555 3月 19 19:48 Kconfig
drwxrwxr-x 22 zhengyang zhengyang 4096 3月 19 19:49 kernel/
drwxrwxr-x 20 zhengyang zhengyang 12288 3月 19 19:49 lib/
drwxrwxr-x 6 zhengyang zhengyang 4096 3月 19 19:48 LICENSES/
-rw-rw-r-- 1 zhengyang zhengyang 42849 3月 19 19:48 .mailmap
-rw-rw-r-- 1 zhengyang zhengyang 783429 3月 19 19:48 MAINTAINERS
-rw-rw-r-- 1 zhengyang zhengyang 68756 3月 19 19:48 Makefile
drwxrwxr-x 6 zhengyang zhengyang 4096 3月 19 19:49 mm/
drwxrwxr-x 72 zhengyang zhengyang 4096 3月 19 19:49 net/
-rw-rw-r-- 1 zhengyang zhengyang 726 3月 19 19:48 README
drwxrwxr-x 7 zhengyang zhengyang 4096 3月 19 19:49 rust/
-rw-rw-r-- 1 zhengyang zhengyang 369 3月 19 19:48 .rustfmt.toml
drwxrwxr-x 42 zhengyang zhengyang 4096 3月 19 19:49 samples/
drwxrwxr-x 19 zhengyang zhengyang 12288 3月 19 19:49 scripts/
drwxrwxr-x 15 zhengyang zhengyang 4096 3月 19 19:49 security/
-rw-rw-r-- 1 zhengyang zhengyang 1060 3月 19 19:49 set_env.sh
drwxrwxr-x 27 zhengyang zhengyang 4096 3月 19 19:49 sound/
drwxrwxr-x 45 zhengyang zhengyang 4096 3月 19 19:49 tools/
drwxrwxr-x 4 zhengyang zhengyang 4096 3月 19 19:49 usr/
drwxrwxr-x 4 zhengyang zhengyang 4096 3月 19 19:49 virt/
5.2 配置内核
内核的编译分为两步:配置、编译。单板的默认配置在arch/loongarch/configs目录下;
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ ll arch/loongarch/configs/*2k*
-rw-rw-r-- 1 zhengyang zhengyang 21401 3月 19 19:48 arch/loongarch/configs/loongson_2k1000_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 21327 3月 19 19:48 arch/loongarch/configs/loongson_2k300_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 21217 3月 19 19:48 arch/loongarch/configs/loongson_2k300_rt_defconfig
选择loongson_2k300_defconfig,执行如下命令,生成.config文件:
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/u-boot$ source ../set_env.sh && make loongson_2k300_defconfig V=1
5.3 编译内核
在linux内核根目录下执行如下命令:
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ source ../set_env.sh && make uImage -j$(nproc)
......
mkdir -p /opt/2k0300/build-2k0300/workspace/linux-6.12/tools/objtool && make O=/opt/2k0300/build-2k0300/workspace/linux-6.12 subdir=tools/objtool --no-print-directory -C objtool
CALL scripts/checksyscalls.sh
INSTALL libsubcmd_headers
UIMAGE arch/loongarch/boot/uImage.gz
Image Name: Linux-6.12.0.lsgd+
Created: Thu Mar 19 22:13:57 2026
Image Type: LoongArch Linux Kernel Image (gzip compressed)
Data Size: 10361077 Bytes = 10118.24 KiB = 9.88 MiB
Load Address: 00200000
Entry Point: 00f33000
Image arch/loongarch/boot/uImage is ready
编译规则定义在arch/loongarch/Makefile文件,在arch/loongarch/Makefile文件;
vmlinux.elf vmlinux.efi vmlinuz.efi uImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(bootvars-y) $(boot)/$@
其中:
- 目标(targets):
vmlinux.elf,vmlinux.efi,vmlinuz.efi,uImage这四个文件都是需要生成的目标; - 依赖(prerequisite):它们都依赖于
vmlinux(即必须先完成内核主体vmlinux的链接); - 命令(recipe):
$(Q)$(MAKE) $(build)=$(boot) $(bootvars-y) $(boot)/$@$(Q)通常是一个控制静默输出的变量(@或空);$(MAKE)调用make命令;$(build)=$(boot)是内核构建系统的一个惯用法,表示进入$(boot)目录(通常是arch/$(ARCH)/boot)并执行那里的Makefile;$(bootvars-y)是一些传递给子make的变量(如架构相关的编译选项)。$(boot)/$@指定子make的目标为当前目标在$(boot)目录下的对应文件(例如对于uImage,会去构建arch/$(ARCH)/boot/uImage);
编译成功之后在arch/loongarch/boot/下生成了uImage,这里编译出来的实际是Legacy uImage,并不是FIT uImage;
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ ll arch/loongarch/boot/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 21:54 dts/
-rw-rw-r-- 1 zhengyang zhengyang 58 3月 19 19:48 .gitignore
-rwxrwxr-x 1 zhengyang zhengyang 1244 3月 19 19:48 install.sh*
-rw-rw-r-- 1 zhengyang zhengyang 2058 3月 19 19:48 Makefile
lrwxrwxrwx 1 zhengyang zhengyang 9 3月 19 22:13 uImage -> uImage.gz
-rw-rw-r-- 1 zhengyang zhengyang 10361141 3月 19 22:13 uImage.gz
-rw-rw-r-- 1 zhengyang zhengyang 245 3月 19 22:13 .uImage.gz.cmd
-rwxrwxr-x 1 zhengyang zhengyang 28246016 3月 19 22:07 vmlinux.bin*
-rw-rw-r-- 1 zhengyang zhengyang 219 3月 19 22:07 .vmlinux.bin.cmd
-rw-rw-r-- 1 zhengyang zhengyang 10361077 3月 19 22:07 vmlinux.bin.gz
-rw-rw-r-- 1 zhengyang zhengyang 136 3月 19 22:07 .vmlinux.bin.gz.cmd
-rwxrwxr-x 1 zhengyang zhengyang 27213824 3月 19 22:07 vmlinux.efi*
-rw-rw-r-- 1 zhengyang zhengyang 239 3月 19 22:07 .vmlinux.efi.cmd
有关内核镜像格式Image、zImage、uImage可以参考《Mini2440之uboot移植流程之linux内核启动分析(六)》。
5.4 编译设备树
对于我们使用的板子需要使用的设备树文件为arch/loongarch/boot/dts/ls2k300_99pi_wifi.dts。
在内核编译过程中同时会编译设备树,编译完成会生成文件arch/loongarch/boot/dts/ls2k300_99pi_wifi.dtb。
更多有关设备树的内容可以参考以下相关博客:《linux内核设备树系列》。
5.4.1 编译流程
当你在内核根目录执行 make uImage 时,顶层Makefile会执行dtbs的编译;
dtstree := arch/$(SRCARCH)/boot/dts
PHONY += dtbs dtbs_prepare dtbs_install dtbs_chec
dtbs: dtbs_prepare
$(Q)$(MAKE) $(build)=$(dtstree) need-dtbslist=1
build定义在build := -f $(srctree)/scripts/Makefile.build obj
build := -f $(srctree)/scripts/Makefile.build obj=$(dtstree) need-dtbslist=1
最终执行的命令就是:
make -f scripts/Makefile.build obj=arch/loongarch/boot/dts need-dtbslist=1
在 arch/loongarch/boot/dts/Makefile 中,根据内核配置(如 CONFIG_DTB_MATCH_BY_BOARD_NAME)确定要编译哪些.dtb文件,最终调用 dtc 编译器生成二进制设备树。
我们定位到arch/loongarch/boot/dts/Makefile;
# SPDX-License-Identifier: GPL-2.0-only
# dtb-y = loongson-2k0500-ref.dtb loongson-2k1000-ref.dtb loongson-2k2000-ref.dtb
ifdef CONFIG_DTB_MATCH_BY_BOARD_NAME # 定义
dtb-$(CONFIG_LOONGSON_2K300) += ls2k300_mini_dp.dtb ls2k300_vanguard_pi.dtb ls2k300_gongkong_gbkpgk0.dtb \
ls2k300_alientek.dtb ls2k300_99pi_wifi.dtb ls2k300_99pi_tf.dtb
dtb-$(CONFIG_LOONGSON_2K1000) += ls2k1000_dp.dtb
obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
else
obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .dtb.o, $(CONFIG_BUILTIN_DTB_NAME))
endif
在文件arch/loongarch/Kconfig:
config DTB_MATCH_BY_BOARD_NAME
bool "dtb match by board_name which from command line"
depends on BUILTIN_DTB
default y
help
Base name (without suffix, relative to arch/loongarch/boot/dts/)
for the DTS file that will be used to produce the DTB linked into
the kernel.
support match dtb by board_name which from command line
so that bootloader given this value in command line
由于CONFIG_BUILTIN_DTB、CONFIG_LOONGSON_2K300在arch/loongarch/configs/loongson_2k300_defconfig文件中定义;
CONFIG_BUILTIN_DTB=y
CONFIG_LOONGSON_2K300=y
因此在编译内核阶段生成的.config文件中会配置CONFIG_DTB_MATCH_BY_BOARD_NAME=y,这样 dtb-y 变量会被赋值为后面列出的所有 .dtb 文件名,这样内核编译的时候就会生成这些设备树。
5.4.2 单独编译
如果需要单独编译设备树,在linux内核根目录执行如下命令:
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ source ../set_env.sh && make arch/loongarch/boot/dts/ls2k300_99pi_wifi.dts dtbs V=1
+ source ../set_env.sh
......
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ ll arch/loongarch/boot/dts/ls2k300_99pi_wifi.dtb
+ ls --color=auto -alF arch/loongarch/boot/dts/ls2k300_99pi_wifi.dtb
-rw-rw-r-- 1 zhengyang zhengyang 21862 3月 22 09:01 arch/loongarch/boot/dts/ls2k300_99pi_wifi.dtb
六、编译Buildroot
更多有关Buildroot文件系统的内容参考:
6.1 源码下载
源码位于《https://gitee.com/open-loongarch/buildroot-2024.08.git》,版本为buildroot-2024.08,前面我们已经下载了;
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace$ ll buildroot-2024.08/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:49 arch/
-rw-rw-r-- 1 zhengyang zhengyang 224 3月 19 19:49 .b4-config
drwxrwxr-x 83 zhengyang zhengyang 4096 3月 19 19:49 board/
drwxrwxr-x 22 zhengyang zhengyang 4096 3月 19 19:49 boot/
-rwxrwxr-x 1 zhengyang zhengyang 630 3月 19 19:49 buildenv.sh*
-rw-rw-r-- 1 zhengyang zhengyang 573461 3月 19 19:49 CHANGES
-rw-rw-r-- 1 zhengyang zhengyang 112456 3月 19 19:49 .checkpackageignore
-rw-rw-r-- 1 zhengyang zhengyang 17276 3月 19 19:49 .clang-format
-rw-rw-r-- 1 zhengyang zhengyang 31703 3月 19 19:49 Config.in
-rw-rw-r-- 1 zhengyang zhengyang 175069 3月 19 19:49 Config.in.legacy
drwxrwxr-x 2 zhengyang zhengyang 20480 3月 19 19:49 configs/
-rw-rw-r-- 1 zhengyang zhengyang 18767 3月 19 19:49 COPYING
-rw-rw-r-- 1 zhengyang zhengyang 1198 3月 19 19:49 .defconfig
-rw-rw-r-- 1 zhengyang zhengyang 90428 3月 19 19:49 DEVELOPERS
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:49 dl/
drwxrwxr-x 5 zhengyang zhengyang 4096 3月 19 19:49 docs/
-rw-rw-r-- 1 zhengyang zhengyang 561 3月 19 19:49 .editorconfig
-rw-rw-r-- 1 zhengyang zhengyang 96 3月 19 19:49 .flake8
drwxrwxr-x 20 zhengyang zhengyang 4096 3月 19 19:49 fs/
drwxrwxr-x 8 zhengyang zhengyang 4096 3月 19 19:49 .git/
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 19 19:49 .github/
-rw-rw-r-- 1 zhengyang zhengyang 134 3月 19 19:49 .gitignore
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 19 19:49 .gitlab/
-rw-rw-r-- 1 zhengyang zhengyang 814 3月 19 19:49 .gitlab-ci.yml
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 19 19:49 linux/
-rw-rw-r-- 1 zhengyang zhengyang 46727 3月 19 19:49 Makefile
-rw-rw-r-- 1 zhengyang zhengyang 2292 3月 19 19:49 Makefile.legacy
drwxrwxr-x 2937 zhengyang zhengyang 69632 3月 19 19:49 package/
drwxrwxr-x 2 zhengyang zhengyang 4096 3月 19 19:49 qt_test/
-rw-rw-r-- 1 zhengyang zhengyang 1075 3月 19 19:49 README
-rw-rw-r-- 1 zhengyang zhengyang 0 3月 19 19:49 .shellcheckrc
drwxrwxr-x 13 zhengyang zhengyang 4096 3月 19 19:49 support/
drwxrwxr-x 3 zhengyang zhengyang 4096 3月 19 19:49 system/
drwxrwxr-x 6 zhengyang zhengyang 4096 3月 19 19:49 toolchain/
drwxrwxr-x 4 zhengyang zhengyang 4096 3月 19 19:49 utils/
dl目录存放从互联网下载的源代码及应用软件的压缩包,比如zip、glic、busybox、alsa-lib、alsa-plugins等,这里我们直接将包拷贝过来。
从网盘中 04-文件系统-->buildroot->源码中下载dl压缩包,链接: https://pan.baidu.com/s/1FZcnFcmTGd5GcyP8ayFm5A?pwd=1234
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/buildroot-2024.08$ tar -xvf buildroot-2024.08-dl.efb8dc7-build.20250213090211.tar.xz -C dl/ --strip-components 1
6.2 配置
同内核编译有点类似,首先需要选择一个单板的配置,单板的默认配置在configs目录下;
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/buildroot-2024.08$ ll configs/ | grep 2k
-rw-rw-r-- 1 zhengyang zhengyang 8132 3月 19 19:49 loongarch64_2k1000_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 9799 3月 19 19:49 loongarch64_2k300_all_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 9701 3月 19 19:49 loongarch64_2k300_all_gcc14_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 8146 3月 19 19:49 loongarch64_2k300_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 8472 3月 19 19:49 loongarch64_2k300_opecv4_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 7978 3月 19 19:49 loongarch64_2k300_qt6_defconfig
-rw-rw-r-- 1 zhengyang zhengyang 6821 3月 19 19:49 loongarch64_2k500_defconfig
选择loongarch64_2k300_defconfig;
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/buildroot-2024.08$ rm -rf output
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/buildroot-2024.08$ make loongarch64_2k300_defconfig
......
# configuration written to /home/loongson/workspace/buildroot/.config
6.3 编译
执行编译,这个编译过程比较久,可能需要三四个小时;
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/buildroot-2024.08$ make -j$(nproc)
output:这个目录是构建输出目录,包含所有构建过程中生成的文件,如交叉编译工具链、内核映像、根文件系统等。默认情况下,这个目录不在源码树中,而是在构建时生成的,可以通过配置来改变其位置;
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/buildroot-2024.08$ ll output/
-rw-r--r-- 1 zhengyang zhengyang 82 3月 22 17:56 .br2-external.in.init
-rw-r--r-- 1 zhengyang zhengyang 82 3月 22 17:56 .br2-external.in.jpeg
-rw-r--r-- 1 zhengyang zhengyang 82 3月 22 17:56 .br2-external.in.linux
-rw-r--r-- 1 zhengyang zhengyang 82 3月 22 17:56 .br2-external.in.menus
-rw-r--r-- 1 zhengyang zhengyang 82 3月 22 17:56 .br2-external.in.openssl
-rw-r--r-- 1 zhengyang zhengyang 82 3月 22 17:56 .br2-external.in.paths
-rw-r--r-- 1 zhengyang zhengyang 82 3月 22 17:56 .br2-external.in.skeleton
-rw-r--r-- 1 zhengyang zhengyang 82 3月 22 17:56 .br2-external.in.toolchains
-rw-r--r-- 1 zhengyang zhengyang 169 3月 22 17:56 .br2-external.mk
drwxr-xr-x 311 zhengyang zhengyang 20480 3月 22 20:29 build/ # 除了交叉编译的工具链之外的所有组件
drwxr-xr-x 13 zhengyang zhengyang 4096 3月 22 20:27 host/ # 包含为主机编译的工具的安装
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 22 20:30 images/ # 有镜像(文件系统,比如ext2/4、squashfs、cpio等格式镜像)存储目录
lrwxrwxrwx 1 zhengyang zhengyang 104 3月 22 20:30 staging -> /opt/2k0300/build-2k0300/workspace/buildroot-2024.08/output/host/loongarch64-buildroot-linux-gnu/sysroot/
drwxr-xr-x 17 zhengyang zhengyang 4096 3月 19 19:49 target/ # 几乎包含了目标的完整根文件系统
其中:
build: 除了交叉编译的工具链之外的所有组件,包括Buildroot所需主机工具和选择的软件包,这个目录包含所有软件包源码;host:包含为主机编译的工具的安装,这些工具是正确执行Buildroot所必需的,包括交叉编译工具链;images:所有镜像(文件系统,比如ext2/4、squashfs、cpio等格式镜像)存储目录;staging:其中的层次结构类似于根文件系统层次结构。这个目录包含了安装交叉编译工具链和为目标选择的所有用户空间包,但是,这个目录不是用来成为目标的根文件系统:它包含许多开发文件、未剥离的二进制文件和库,这些文件和库也非常多,对嵌入式系统来说是很大的;这些开发文件用于为所依赖的目标提供编译库和应用程序需要的其他库;target: 几乎包含了目标的完整根文件系统:除了/dev/目录中的设备文件,所有需要的东西都是存在(Buildroot不能创建它们,因为Buildroot不会以root身份运行,也不希望以root身份运行)。此外,它没有正确的权限(例如,busybox二进制文件的setuid),因此,该目录不应该用于你的目标;相反,您应该使用images/目录中构建的映像之一;如果你需要在根文件系统中用NFS挂载外部镜像,必须用root用户在images/目录中生成镜像,相比对于staging/,target/只包含运行所选目标应用程序所需的文件和库:开发文件(头文件)不存在,二进制文件被剥离。
6.3.1 images
包含压缩好的根文件系统镜像文件位于output/images目录下;
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/buildroot-2024.08$ ll output/images/
-rw-r--r-- 1 zhengyang zhengyang 536870912 3月 22 20:29 rootfs.ext2 # buildroot编译生成的文件系统镜像,ext2格式
-rw-r--r-- 1 zhengyang zhengyang 157529897 3月 22 20:29 rootfs.ext2.gz # rootfs.ext2经过gz压缩的根文件系统镜像
lrwxrwxrwx 1 zhengyang zhengyang 14 3月 22 20:29 rootfs.ext4.gz -> rootfs.ext2.gz
lrwxrwxrwx 1 zhengyang zhengyang 14 3月 22 20:29 rootfs.img -> rootfs.ext2.gz
-rw-r--r-- 1 zhengyang zhengyang 418457600 3月 22 20:30 rootfs.tar # output/target经过tar打包的根文件系统镜像
-rw-r--r-- 1 zhengyang zhengyang 158378204 3月 22 20:30 rootfs.tar.gz # rootfs.tar经过gz压缩的根文件系统镜像
6.3.2 target
查看编译好的根文件系统:
zhengyang@ubuntu:/opt/2k0300/build-2k0300/workspace/buildroot-2024.08$ ll output/target/
lrwxrwxrwx 1 zhengyang zhengyang 7 3月 22 18:01 bin -> usr/bin/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 boot/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 dev/
drwxr-xr-x 28 zhengyang zhengyang 4096 3月 19 19:49 etc/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 22 18:01 home/
lrwxrwxrwx 1 zhengyang zhengyang 7 3月 22 18:01 lib -> usr/lib/
lrwxrwxrwx 1 zhengyang zhengyang 3 3月 22 18:01 lib64 -> lib/
lrwxrwxrwx 1 zhengyang zhengyang 10 3月 22 18:52 linuxrc -> /sbin/init*
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 media/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 mnt/
drwxr-xr-x 3 zhengyang zhengyang 4096 3月 22 19:44 opt/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 proc/
drwxr-xr-x 6 zhengyang zhengyang 4096 3月 19 19:49 root/
drwxr-xr-x 5 zhengyang zhengyang 4096 3月 22 19:52 run/
lrwxrwxrwx 1 zhengyang zhengyang 8 3月 22 18:01 sbin -> usr/sbin/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 22 18:01 srv/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 sys/
-rw-r--r-- 1 zhengyang zhengyang 1336 3月 22 18:01 THIS_IS_NOT_YOUR_ROOT_FILESYSTEM
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 tmp/
drwxr-xr-x 11 zhengyang zhengyang 4096 3月 22 20:29 usr/
drwxr-xr-x 7 zhengyang zhengyang 4096 3月 19 19:49 var/
七、更新固件
久久派2K0300核心板默认配套的是PMON固件以及linux 4.19的内核,这里我们打算将其替换换为uboot以及linux 6.12版本。
7.1 刷写uboot
uboot烧写参考资料:
- 龙芯
2K300-99派更新u-boot固件:《https://www.bilibili.com/video/BV1FTqPYLER2?vd_source=9e5530c6fa951aaadc66d0d7b35a6103》; - 久久派新世界系统烧录:《
https://www.bilibili.com/video/BV12tsJeXEWK?vd_source=9e5530c6fa951aaadc66d0d7b35a6103》。
7.1.1 准备工作
2K0300开发板串口连接到电脑,然后打开电脑的MobaXterm,选择串口端口,设置波特率115200,8位数据位,1位停止位。
确保开发板和电脑在一个局域网,可以通过路由器连接实现。
7.1.2 搭建tftp服务器
由于我们要通过PMON中更新PMON固件,首先需要在我们的ubuntu虚拟机搭建一个tftp服务器,具体可以参考《嵌入式Linux开发环境搭建》,这里我在/opt 目录下创建一个子目录tftpboot;
zhengyang@ubuntu:/opt$ sudo mkdir tftpboot
zhengyang@ubuntu:/opt$ sudo chmod 0777 tftpboot
并按照教程中进行搭建tftp服务器,我们需要将我们的固件u-boot-with-spl.bin放在这个目录下;
zhengyang@ubuntu:/opt$ cp /opt/2k0300/build-2k0300/workspace/u-boot/u-boot-with-spl.bin ./tftpboot/
7.1.3 进入PMON命令行
给2K0300开发板复位上电,疯狂按c进入进入PMON命令行模式;
直到出现 PMON> 提示符,首先给开发板配置一个与tftp服务器同网段的IP地址:
PMON> ifaddr syn0 172.23.34.188
PMON> ping 172.23.34.187
把IP设置为172.23.34.188 。这样,开发板 (172.23.34.188) 和ubuntu虚拟机 (172.23.34.187) 就在同一个网段上,可以开始传文件刷机了。
7.1.4 烧录
从tftp服务器下载指定的固件文件(u-boot-with-spl.bin),并直接将其烧录到当前开发板的引导闪存SPI Nor Flash的起始位置:
PMON> fload tftp://172.23.34.187/u-boot-with-spl.bin
此过程中,务必保持板卡通电,严禁断电。耐心等待加载及烧录完成,直至界面依次出现Erase end!、Programming end、
Verifying FLASH所有提示,且PMON命令行再次出现,即表示PMON烧录完成。
按开发板重启按钮,等待终端出现大大的LOONGSON和SOC#字样说明更新uboot固件成功。
7.1.5 uboot ip网关等设置
接着设置久久派ip ,网关等,根据自己网段修改, 保证局域网内没有其他设备使用;
=> setenv ipaddr 172.23.34.188
=> setenv netmask 255.255.128.0
=> setenv gatewayip 172.23.0.1
设置网关,根据自己局域网设置;
=> setenv serverip 172.23.34.186
7.1.5 测试
在uboot启动阶段按c即可进入uboot命令行,这里可以执行许多命令,我们只介绍部分,有兴趣可以查看《Rockchip RK3399 - TPL/SPL方式加载uboot》。
7.1.5.1 查看板子信息
=> bdinfo
7.1.5.2 查看环境变量
=> printenv
重点关注 loadaddr、fdt_addr、bootcmd 。
7.1.5.3 mmc命令测试
在命令行输入mmc list命令用于来查看当前开发板一共有几个MMC设备:
mmc list
需要查看eMMC信息,运行如下命令:
=> mmc info
可以使用命令mmc part来查看其分区,比如查看eMMC的分区情况,输入如下命令:
=> mmc part
7.1.5.4 sf
用于操作SPI Flash的命令集,支持探测、擦除、读写SPI NOR Flash芯片,是嵌入式开发中烧录固件、更新uboot、操作环境变量分区的核心工具;
| 子命令 | 语法 | 作用 |
|---|---|---|
| probe | sf probe | 初始化 SPI 控制器并探测 Flash 芯片。在使用任何其他 sf 命令前必须先执行,以检测 Flash 是否存在并获取其大小、型号等信息。 |
| read | sf read <内存地址> <Flash偏移> <长度> | 将 Flash 中指定偏移和长度的数据读入内存指定地址。 |
| write | sf write <内存地址> <Flash偏移> <长度> | 将内存中的数据写入 Flash 指定偏移(必须先擦除)。 |
| erase | sf erase <Flash偏移> <长度> | 擦除 Flash 指定区域(以扇区为单位)。擦除后区域变为 0xFF。 |
| update | sf update <内存地址> <Flash偏移> <长度> | 比较内存和 Flash 内容,仅更新不同的部分(节省时间)。常用于升级固件。 |
| test | sf test <Flash偏移> <长度> | 对 Flash 区域进行读写测试,用于验证硬件是否正常。 |
在进行读、写、擦除时,如果已配置mtdparts,可以直接用分区名代替偏移和长度,比如:
sf read ${fdt_addr} dtb # 从 dtb 分区读取设备树
7.1.5.5 mtdparts
mtdparts 是用于管理MTD分区表的命令。它可以为为SPI Nor Flash、Nand Flash等MTD设备定义逻辑分区,之后就可以用分区名来替代具体的偏移地址和长度,让操作更直观、更安全。
| 命令 | 说明 |
|---|---|
| mtdparts | 列出当前所有 MTD 设备及其分区 |
| mtdparts default | 恢复默认分区表(由 CONFIG_MTDPARTS_DEFAULT 定义) |
| mtdparts add <设备名> <分区列表> | 动态添加或修改分区(例如 mtdparts add nor0 1m(data)) |
| mtdparts del <设备名> | 删除该设备的所有分区定义 |
参考文字:《linux驱动移植-Nand Flash ONFI标准和MTD子系统》。
7.2 更新设备树
7.2.1 tftp下载
在ubuntu虚拟机,我们需要将设备树放在这个tftp根目录下;
zhengyang@ubuntu:/opt$ cp /opt/2k0300/build-2k0300/workspace/linux-6.12/arch/loongarch/boot/dts/ls2k300_99pi_wifi.dtb /opt/tftpboot/
使用tftp命令将设备树下载到内存地址${fdt_addr},fdt_addr的值来自配置参数FDT_ADDR,值为0x900000000a000000;
=> tftp ${fdt_addr} ls2k300_99pi_wifi.dtb
7.2.2 烧录
擦除板载SPI Nor Flash的dtb分区,并将内存中的设备树数据写入到板载SPI Nor Flash的dtb分区;
=> sf probe
=> sf erase dtb
=> sf write ${loadaddr} dtb 0xd000
7.3 NFS启动系统
7.3.1 NFS服务器
由于我们要通过nfs来挂载根文件系统rootfs,因此需要搭建NFS服务器,具体参考《NFS服务器》。
这里我在/opt 目录下创建一个子目录nfs_root;
zhengyang@ubuntu:/opt$ sudo mkdir nfs_root
zhengyang@ubuntu:/opt$ sudo chmod 0777 nfs_root
并按照教程中进行搭建NFS服务器。
接着我们需要将根文件系统复制到nfs共享路径下:
zhengyang@ubuntu:/opt$ cd nfs_root
zhengyang@ubuntu:/opt$ sudo mkdir buildroot_rootfs
zhengyang@ubuntu:/opt/nfs_root$ sudo cp -a /opt/2k0300/build-2k0300/workspace/buildroot-2024.08/output/target/* ./buildroot_rootfs
zhengyang@ubuntu:/opt/nfs_root$ ll buildroot_rootfs/
lrwxrwxrwx 1 zhengyang zhengyang 7 3月 22 18:01 bin -> usr/bin/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 boot/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 dev/
drwxr-xr-x 28 zhengyang zhengyang 4096 3月 19 19:49 etc/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 22 18:01 home/
lrwxrwxrwx 1 zhengyang zhengyang 7 3月 22 18:01 lib -> usr/lib/
lrwxrwxrwx 1 zhengyang zhengyang 3 3月 22 18:01 lib64 -> lib/
lrwxrwxrwx 1 zhengyang zhengyang 10 3月 22 18:52 linuxrc -> /sbin/init*
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 media/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 mnt/
drwxr-xr-x 3 zhengyang zhengyang 4096 3月 22 19:44 opt/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 proc/
drwxr-xr-x 6 zhengyang zhengyang 4096 3月 19 19:49 root/
drwxr-xr-x 5 zhengyang zhengyang 4096 3月 22 19:52 run/
lrwxrwxrwx 1 zhengyang zhengyang 8 3月 22 18:01 sbin -> usr/sbin/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 22 18:01 srv/
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 sys/
-rw-r--r-- 1 zhengyang zhengyang 1336 3月 22 18:01 THIS_IS_NOT_YOUR_ROOT_FILESYSTEM
drwxr-xr-x 2 zhengyang zhengyang 4096 3月 19 19:49 tmp/
drwxr-xr-x 11 zhengyang zhengyang 4096 3月 22 20:29 usr/
drwxr-xr-x 7 zhengyang zhengyang 4096 3月 19 19:49 var/
7.3.2 uboot设置启动参数
设置通过网络挂在根文件系统:
setenv bootargs "console=ttyS0,115200 root=/dev/nfs rw rootwait nfsroot=172.23.34.186:/opt/nfs_root/buildroot_rootfs ip=172.23.34.188:172.23.34.186:172.23.0.1:255.255.128.0::eth0:off"
其中:
root:表示使用/dev/nfs这个设备作为根文件系统,rw表示可读可写的;nfsroot:表示服务器中rootfs所在路径,注意需要跟上服务器的ip地址;rootwait表示在根文件系统就绪之前无限等待。主要用于等待那些反应速度较慢的异步检测的设备就绪(例如USB/MMC/FireWire);172.23.34.188:是板子启动之后的ip地址;172.23.34.186:是nfs服务器的ip地址;172.23.0.1:是板子网关地址;255.255.128.0:是板子子网掩码;
eth0表示板子上的网络设备。 off表示关闭动态获取ip地址。 注意:eth0前面有两个冒号,那是因为这里还可以填写一个板子的主机名,这里没有设置,所以为空。
具体可以参考《NFS根文件系统支持》。
7.3.3 烧写内核
我们需要将我们的内核镜像uImage放在/opt/tftpboot目录下;
zhengyang@ubuntu:/opt$ cp /opt/2k0300/build-2k0300/workspace/linux-6.12/arch/loongarch/boot/uImage ./tftpboot/
久久派设置启动命令:
setenv bootcmd 'tftp ${loadaddr} uImage;sf probe;sf read ${fdt_addr} dtb;bootm'
这里在开发板启动的时候,将uImage从tftp服务器下载到内核的加载地址${loadaddr},值来自配置参数CONFIG_SYS_LOAD_ADDR;
CONFIG_SYS_LOAD_ADDR=0x9000000003000000
7.3.4 保存及查看
保存环境变量,并查看环境变量:
saveenv
printenv
7.3.5 启动系统
执行boot命令,启动内核:
boot
读取环境变量 bootcmd 并执行其中定义的启动流程。
7.4 烧录系统到eMMC
7.4.1 ubuntu虚拟机
输入密码root进入系统,在ubuntu虚拟机中将项目中rootfs.tar.gz拷贝至/opt/nfs_root/buildroot_rootfs/root;
zhengyang@ubuntu:/opt$ cp /opt/2k0300/build-2k0300/workspace/buildroot-2024.08/output/images/rootfs.tar.gz /opt/nfs_root/buildroot_rootfs/root/
将项目中uImage拷贝至/opt/nfs_root/buildroot_rootfs/boot;
zhengyang@ubuntu:/opt$ cp /opt/2k0300/build-2k0300/workspace/linux-6.12/arch/loongarch/boot/uImage /opt/nfs_root/buildroot_rootfs/boot/
7.4.2 久久派
在久久派中使用mkfs.ext4格式化eMMC;
root@buildroot:~$ mkfs.ext4 /dev/mmcblk0
格式化eMMC设备,将其格式化成ext4文件系统,和我们windows上格式u盘非常类似;
输入y确认格式化,接着挂载eMMC;
root@buildroot:~$ mount /dev/mmcblk0 /mnt
在久久派解压:
root@buildroot:~$ tar -zxvf /root/rootfs.tar.gz -C /mnt
将新内核拷贝到eMMC中:
root@buildroot:~$ cp /boot/uImage /mnt/boot
取消emmc挂载:
root@buildroot:~$ umount /mnt
此时已经成功将内核和系统烧写至eMMC。
7.5 uboot设置eMMC启动
reboot重新启动系统:
root@buildroot:~$ reboot
在启动阶段,按c即可进入uboot命令行,设置启动参数:
setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0 rw rootwait rootfstype=ext4 init=/sbin/init
设置启动命令:
setenv bootcmd 'ext4load mmc 0:0 ${loadaddr} /boot/uImage; bootm ${loadaddr}'
从ext4文件系统中读取内核镜像到内存,并启动启动位于内存指定地址的内核镜像,其中
ext4load:用于从ext4文件系统中加载文件;mmc:设备类型,表示操作对象是MMC设备(包括eMMC和SD卡);0:0:设备编号:分区编号。第一个0表示第0个MMC设备(通常是板载eMMC或唯一的SD卡);第二个0表示该设备上的第0个分区(对于ext4,通常对应第一个分区,即/dev/mmcblk0p1);${loadaddr}:环境变量,指定将文件加载到的内存起始地址;/boot/uImage:要加载的文件在ext4文件系统中的绝对路径。内核镜像文件uImage存放在根目录下的boot文件夹中。
保存环境变量并启动系统:
saveenv
boot
boot读取环境变量 bootcmd 并执行其中定义的启动流程。
参考文章
[1] Rockchip RK3399 - NanoPC-T4开发板介绍
[2] Rockchip RK3588 - NanoPC-T6开发板介绍
[6] Loongson-2K0300-99PAI(久久派资料,推荐)
[8] open-loongarch(官方仓库)
[10] WwuSama/21届智能车走马观碑开源仓库
[11] NCNN模型推理资料链接 提取码: tihd
[12] 开源库地址:https://gitee.com/lq-tech/Loongson_2k300_301_Library
[13] 龙邱Gitee仓库地址

浙公网安备 33010602011771号