news 2026/9/8 18:42:03

1.系统移植

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
1.系统移植

启动流程

pc机

BIOS(基本输入输出系统)

  1. 初始化时钟;初始化内存;基本硬件初始化
  2. 判断启动方式(usb 硬盘 光驱):区别系统存放位置和读取方式

引导程序

  1. 固化在硬盘(存储数据)最前面的部分
  2. 识别对应的操作系统(选择,默认第一个)
  3. 加载对应操作系统

操作系统(无图形化界面)
文件系统(NTFS/FAT(16/32)):规定数据如何组成为文件/文件夹,记录内存使用情况
应用程序(桌面图形化)

嵌入式

iRom code(厂家固化)

  1. 基本硬件配置(需要的时钟和设备)
  2. 判断启动方式(emmc USB ad卡)
  3. 将bootloader第一个阶段的代码加载到IRAM(芯片内部RAM)

IRAM中运行bootloader第一阶段(SPL)代码

  1. 初始化整个系统的时钟
  2. 初始化内存
  3. 将完整的bootloader搬运到内存中

内存中运行bootloader第二阶段代码

  1. 初始化开发版硬件设备(网卡,串口 usb)
  2. 加载对应操作系统(内存)

运行操作系统
挂载文件系统(EXT(2,3,4))
启动应用程序

问:为啥bootloader分两个阶段运行
答:芯片内部存储空间有限,如果内部空间做大,成本提高

环境搭建

交叉编译器(可执行)

不同架构涉及不同的编译器 arm-->arm-linux-gcc x86-->gcc
临时环境变量(当前终端有效):export PATH=$PATH:交叉编译器地址
永久环境变量
(当前用户有效):~/.bashrc配置文件中添加export PATH=$PATH:交叉编译器地址
(所以用户有效):/etc/bash.bashrcp配置文件添加export PATH=$PATH:交叉编译器地址

tftp 传输文件

开发板与pc进行文件传输===串口(速度过慢)==网络通信(tftp协议)

  1. 在linux中搭建对应环境
    sudo apt-get install tftpd-hpa(服务器程序)
    sudo apt-get install tftp-hpa(客户端程序)(用来进行对应测试)
  2. 创建tftpdoot文件夹,保存对于tftp服务器文件
  3. 配置对于tftp的设置(文件夹路径)
    vi /etc/default/tftp-hpa
    TFTP_DIRTORY="路径"
    权限“sudo chmod 777 -R 目录”
  4. 重启tftp的服务
    sudo service tftp-hpa resever
  5. 测试:本都回环测试 tftp 127.0.0.1 get *.c quit
  6. 下载到内存 tftp 内存地址 文件名

uboot的参数(通过tftp下载对应的文件(镜像)到开发板)

print:打印当前的参数

setenvserverip(tftp服务器虚拟机ip)
setenvipaddr(开发板ip)
setenvgatewayip(网关的ip)
setenvethaddr(mac地址)

saveenv(保存对应参数到emmc)

测试:ping192.168.2.1(ping网关)
ping192.168.2.25(ping服务器)

tftp 0x41000000 uImage(下载linux镜像文件到内存(运行内存RAM))
tftp 0x43000000 ramdisk.img(下载文件系统镜像文件到内存(运行内存RAM))
tftp 0x42000000 exynos4412-fs4412.dtb(下载设备树文件到内存(运行内存RAM))

运行对应的Linux操作系统Linux操作系统(解析设备树文件,挂载文件系统)
bootm Linux镜像地址 文件系统地址 设备树的地址

bootcmd:设置开发板启动后,自动执行的命令
setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-fs4412.dtb\;tftp 43000000 ramdisk.img\;bootm 41000000 43000000 42000000

通过网络方式去挂载文件系统
bootcmd 没有下载文件系统
bootargs(uboot向linux内核传递的参数) 告诉操作系统去哪里挂载文件系统

U-boot bootargs参数:

bootcmd参数:

U-boot启动流程分析

  1. iRom code(厂家固化的代码) IRom
    • 基本硬件配置(需要的时钟和设备)
    • 判断启动方式(emmc USB ad卡)
    • 将bootloader第一个阶段的代码(SPL)加载到IRAM(芯片内部RAM)
    • BL1代码是由三星提供,irom的代码在读取BL1的时候,会对他做验证,如果验证通过就运行它
  2. SPL(U-boot第一阶段代码) IRam
    • 设置为SVC特权模式
    • 设置异常向量表,告诉内核异常向量表基址
    • 关闭Cache(CPU内置高速小容量存储器)和MMU
    • 初始化整个系统的时钟
    • 初始化内存
    • 将完整的bootloader搬运到内存中
  3. U-boot第二阶段代码 LPDDR
    • 设置为SVC特权模式
    • 设置异常向量表,告诉内核异常向量表基址
    • 关闭Cache(CPU内置高速小容量存储器)和MMU
    • 执行_main函数:设置栈指针sp,清理bss段,调用board_init_f
    • arch/arm/lib/board.c (板子第一阶段初始化)
      指针数组存储操作函数
      init_fnc_t *init_sequence[] = { /*获取cpu id*/ arch_cpu_init, /* basic arch cpu dependent setup */ /*定时器初始化*/ timer_init, /* initialize timer */ /*环境变量初始化:指定了一个默认的环境变量*/ env_init, /* initialize environment */ /*初始化波特率*/ init_baudrate, /* initialze baudrate settings */ /*初始化串口:确定哪一个串口设备输出(默认的输出是哪一个串口)*/ serial_init, /* serial communications setup */ /*控制台一级初始化*/ console_init_f, /* stage 1 init of console */ /*打印u_boot版本信息*/ display_banner, /* say that we are here */ /*打印cpu的信息*/ print_cpuinfo, /* display cpu info (and speed) */ /*记录内存的大小*/ dram_init, /* configure available RAM banks */ NULL, };

      为U-boot重定向做准备,在内存最顶端划分空间(后面要加载 zImage 内核、设备树 dtb,内核会占用 DDR 低地址区域)

    • 重定向U-boot,防止被覆盖

    • 清BSS段,准备运行第二阶段C语言代码

    • board_init_r(第二阶段初始化)
      初始化标准输入输出设备stdio_init();
      从存储介质中读取环境变量的值env_relocate();

    • main_loop()

硬件信息
SOC :三星 exynos4412(4个cortex-A9 ARM核) 主频 1.4GHZ
board :origen<->fs4412
u-boot版本 :u-boot-2013.01

nfs(网络文件系统)

通过网络的方式进行映射把一台主机上文件映射到另一台主机上,它可以使用者访问网络上别处的文件就像在使用自己的计算机一样

  1. 搭建:sudo apt-get install nfs-kernel-server (nfs服务器)
  2. 解压对应的文件系统(rootfs.tar.gz)tar-xvf rootfs.tar·
  3. 修改对应的配置(/etc/export)nfs服务器可以被完成访问的目录
    /home/linux/fs4412/rootfs*(rw,sync,no_root_squash)(路径)
  4. 重启nfs的服务
    sudo service nfs-kernel-server restart
  5. 测试
    找一块空目录
    sudo mount 127.0.0.1:/home/linux/fs4412/rootfs 空目录的路径
    创建一个文件,在源文件查看是否存在,如果存在,代表环境没有任何问题
    解挂
    sudo umount --lazy 空目录的路径

Linux操作系统编译

  1. arch —— 保存对应架构
    arch/arm/configs ----- linux 是通用 我们需要进行对应的配置(芯片厂家配置)exynos_defconfig
    arch/arm/boot/dts ----- 设备树信息
    arch/arm/compressed ----- 自解压的代码
    arch/arm/kernel/head.s ----- linux启动最开始的代码
  2. driver —— 驱动
  3. net —— 网络协议栈的代码
  4. 编译
    1. //导入默认配置
      make ARCH=arm exynos_defconfig
    2. //进行编译(编译架构)
      make ARCH=arm CROSS_COMPILE=arm-linux-
  5. 生成四个镜像文件
    (最上面)vmlinux:.头部信息+Linux镜像文件
    image:去掉头部的信息镜像文件
    zImage:自解压的代码+去掉头部的信息镜像文件压缩
    uImage(arch/arch/arm/compressed):自解压的代码+包含头部信息的Linux镜像文件压缩
  6. 生产uboot专属的镜像文件
    make ARCH-arm CROSS_COMPILE-arm-linux- uImage
    sudo apt-get installuboot-tools
  7. 测试uImage
    1. 找不到文件系统
      bootargs参数传递有没有问题
      (虚拟机)nfs服务有没有生效
      网络通不通
      当前开发板(1inux镜像)要配置对应的nfs的功能
    2. 网卡驱动移植
      我们Linux内核包含对应的网卡驱动
      我们只需要选择配置
      menuconfig====菜单====选择Linux镜像支持哪些功能
      DM9000
    3. nfs
      TCP/IP
      内核级网络配置
      nfs服务
    4. 屏蔽不需要的时钟信号

Image,zImage,uImage区别:
Image为zImage的内核的一种映像解压缩文件,为了节省系统容量,采用zImag文件(其开头自带解压代码),uImage为U-boot的专用映像文件,U-boot的bootm命令无法启动zImage,需要使用mkimage工具加上64字节的头文件(内核版本,加载位置,生成时间,大小等)

menuconfig ;.config ;Kconfig ;Makefile 关系
menuconfig:linux内核提供菜单选项(表示Linux内核支持哪些功能)(去餐馆里面的菜单)
.config:linux内核当前选择哪些功能 (点菜的凭证)
Kconfig:给Linux内核提供对应菜单选项 (当前餐馆所有厨师会做的菜)
Makefiie:管理Linux内核编译 (靠对应.config里面宏的配置)

Makefig:obj -$(宏)+=xxx.o
Kconfig:
名称:config <标识符>:标识符为省略"CONFIG_"的配置项
类型:<type> bool: y(静态编译)和n(不选择)
tristate: y、m(动态加载)、n
string: ASCII码串
hex: 16进制字符串
int: 10进制字符串
输出提示:prompt <提示符> [if <依赖表达式>]
数字范围:限制int/hex类型配置项 range(范围)
默认值原.config中不存在本配置项,且用户未设置新值时,使用默认项 default(初始值)
依赖:决定配置项是否可见 depends on <值>:值可为宏或语法&&、||等
选择:依赖项被强制配置 select 配置选项名

帮助---help---
帮助信息
source 路径 :包含该路径下所有Kconfig代码

设备树

包含当前开发板的设备信息(DM9000地址,led地址,蜂鸣器地址)
文件地址:arch/arm/boot/dts
三星:exynos4412-origen.dts母版 ---->exynos4412-fs4412.dts
.dts===源文件
.dtsi===头文件
.dtb===生成的文件(类似于可执行文件)

文件Makefile中加上对应设备树文件:exynos4412-fs4412.dtb \
在linux顶层的makefile去进行编译:make ARCH=arm CROSS_COMPILE=arm-linux- dtbs
添加对应的设备信息(DM9000)

文件系统

制作工具:
busybox ==== 文件系统(快速)
buildroot ==== 文件系统 linux内核 bootloader
yocto ====== 文件系统 linux内核 bootloader

linux启动过程分析

linux内核自解压

入口 start,保存参数,关中断
计算运行偏移,修复GOT:全局变量、函数地址
BSS 段清零:存放程序未初始化的全局变量、静态变量
初始化 C 运行环境,打开 Cache:设置栈,分配堆
安全检查后进行解压,搬移数据
关闭 cache,恢复机器 ID、atags,跳转到真正 vmlinux 内核入口执行

挂载根目录

执行init程序

init===linuxrc===bin/busybox===会去读取inittab,并加载和运行里面的内容

sysinit:在系统启动之后最先执行,只执行一次,init必须要等着结束之后在继续执行
wait:在sysinit进程执行完之后执行,只执行一次,init必须要等着结束之后在继续执行
once:在wait进程执行完之后执行,只执行一次,init不会等着结束之后在执行
respawn:在once进执行完之后执行,init进程一旦发现它死掉,会进行对应重启
askfirst:先打印press Enter to activate this console按回车之后,才启动 shell 终端
restart:在init进程收到SIGHUP信号后,重载 inittab 配置,执行 restart 对应的程序。
ctrlaltdel:组合键(ctrl+Alt+Del)重启

/etc/inittab

/etc/init.d/rcS

/etc/fsatb

配置自启动

  1. 在bootargs参数中指定自己的程序
    init=/linuxrc------>init=自己的程序
    缺点:无法启动init程序
  2. 默认启动init程序,修改/etc/inittab,使用sysinit,wait,once,respawn
  3. 修改/etc/init.d/rcS脚本文件,添加程序
    例子:/hello& &:后台运行
  4. 修改/etc/profile脚本文件,添加程序(同3)

    注意:
    很多时候我们会选择在(2)或(4)中添加。
    (2)可以让自己的进程死掉后,重新启动
    (4)可以让自己的程序在执行的时候,执行的环境比较好。

制作ramdisk文件

  1. 制作镜像文件
    dd if=/dev/zero of=ramdisk bs=1k count=8192(大小为8M)
  2. 格式化这个镜像为ext2
    mkfs.ext2 -F ramdisk
  3. 拷贝对应文件系统文件到镜像
    1.创建对应文件夹
    mkdir FileSystem
    2.挂载对应的ramdisk到新建的文件中
    sudo mount ramdisk FileSystem
    3.拷贝对应的文件到挂载目录
    sudo cp ./fs4412/rootfs/* ./ -a
  4. 卸载对应挂载
    sudo umount FileSystem/
  5. 压缩ramdisk为ramdisk.gz
    gzip --best -c ramdisk > ramdisk.gz
  6. 将格式化为uboot识别的格式并拷贝到/tftpnoot下
    mkimage -n "ramdisk" -A arm -O linux -T ramdisk -C gzip -d ramdisk.gz ramdisk.img
    - A 指定CPU体系结构
    - O 指定操作系统类型
    - T 指定镜像类型
    - C 指定镜像压缩方式

    -a 指定镜像在内存中的加载地址,镜像下载到内存中时,要按照用mkimage制作镜像时,这 个参数所指定的地址值来下载。
    -e 指定镜像运行的入口点地址,这个地址就是-a参数指定的值加上0x40。(因为前面有个 mkimage添加的0x40个字节的头)
    -n 指定镜像名。
    -d 指定制作镜像的源文件
    cp ramdisk.img fs4412/tftpboot/

问:库是什么,动态库和静态库有什么区别,编译器如何链接库和操作系统如何知道加载库的路径
库:编译好的二进制目标代码集合,供其他程序使用
静态库.a:需要将库代码整个拷贝到可执行程序中,升级库:需要重新编译整个程序
动态库.so:只记录符号,不拷贝代码,程序运行的时候才加载库;更新库:直接替换 so 文件,程序不用重新编译
如何链接:
-L:指定库的搜索路径(去哪里找.a/.so)
-lxxx:指定链接libxxx.so或者libxxx.agcc 优先找动态库.so;想强制静态链接加‑static

操作系统如何找到动态库路径:

  1. /etc/ld.so.conf配置文件,写入库路径,执行ldconfig更新缓存。(最常用)
  2. 环境变量LD_LIBRARY_PATH,临时指定库搜索路径,终端生效。
  3. 可执行程序内部写死 rpath 路径(编译时-Wl,-rpath=xxx)。
  4. 系统默认库目录/lib/usr/lib

问:如果让你写一个程序被杀死后,在自动启动起来,该如何做

  1. shell 脚本监控​(/etc/init.d/rcS)​​​​​​
    #!/bin/sh while true do ./myapp sleep 1 done
  2. Linux 系统 init 进程守护(/etc/inittab)
    ::respawn
  3. 父进程守护(PID不变)
    while(1) { pid_t pid = fork(); if(pid == 0){ execl("./myapp","./myapp",NULL); exit(0); } wait(NULL); //等待子进程死亡 }

网卡移植

显示无网卡信息:net dm9000
查找报错代码:grep "Net:" * -nR

在include/configs/origen.h中添加宏定义:#define CONFIG_CMD_NET
显示网卡被跳过:grep "Net Initialization Skipped" * -nR


board_etc_init未实现(跳转发现该函数为一个弱函数)
搜索三星其他板子是怎么样实现这个代码的:grep "board_eth_init" * -nR | grep samsung

试着查看其他板子有没有使用dm9000网卡,以及使用方法:



将函数复制到board/samsung/origen/origen.c的endif后(不加宏编译,否则需要在origen.h里定义)
再次编译后发现并未出现.o文件,进当前目录的Makefile

在include/configs/origen.h定义宏:#define CONFIG_DRIVER_DM9000
再次编译,发现dm9000.data和dm9000.io未定义,再次在include/configs/origen.h

再次编译,无法ping通,再次加入宏定义,#define CONFIG_CMD_PING

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 18:39:14

【计算几何 十五章】可见性图:求最短路径

本文涉及知识点 数学 几何 预备知识 直线与线段的交点在射线的投影是连续函数。 假定直线和射线不平行。 假定射线起点是原点&#xff0c;弧度是α\alphaα&#xff0c;直线是&#xff1a;P:(x0,y0)kvP: (x_0,y_0)kvP:(x0​,y0​)kv。 令交点距离原点t&#xff0c; k和t α…

作者头像 李华
网站建设 2026/9/8 18:39:10

原生多模态・极致性价比|GLM‑5.3‑Flash 上线魔乐社区

8月26日&#xff0c;智谱正式上线并开源 GLM-5.3-Flash&#xff08;320B-A18B&#xff09;——这是 GLM-5 系列的首个原生多模态模型。 320B 总参数&#xff0c;能力超越 GLM-5.2&#xff0c;在全球权威的Artificial Analysis Intelligence Index&#xff08;AA 综合智能指数&…

作者头像 李华
网站建设 2026/9/8 18:39:09

终端AI编程代理opencode实践指南:安装、模型接入与Skills配置

最近大半年&#xff0c;我把主力编程环境从IDE的AI插件&#xff0c;慢慢挪到了终端里的AI Agent上。前后试了Claude Code、Codex CLI&#xff0c;最后日常用得最多的反而是opencode。这项目是SST团队开源的&#xff0c;在GitHub上叫sst/opencode&#xff0c;主打一个“终端里的…

作者头像 李华
网站建设 2026/9/8 18:38:37

opencode:开源终端AI编程助手安装配置与实战指南

如果你跟我一样&#xff0c;习惯在终端里用 AI 干活&#xff0c;最近一定绕不开一个名字&#xff1a;opencode。它不是一个 IDE 插件&#xff0c;也不只是"另一个 ChatGPT 壳子"&#xff0c;而是一个真正跑在命令行里、能读你代码、改你文件、执行你命令的开源 AI 编…

作者头像 李华
网站建设 2026/9/8 18:38:14

CodeGraph 安装部署指南:给 AI 编码助手装上本地代码知识图谱

CodeGraph 安装部署指南&#xff1a;给 AI 编码助手装上本地代码知识图谱 【免费下载链接】codegraph Pre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — f…

作者头像 李华
网站建设 2026/9/8 18:37:30

爱享素材下载器:5分钟抓取视频号短视频存到电脑

爱享素材下载器&#xff1a;5分钟抓取视频号短视频存到电脑 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader 爱享素材下载器&a…

作者头像 李华