1.系统移植

发布时间:2026/9/8 18:42:04
1.系统移植 启动流程pc机BIOS(基本输入输出系统)初始化时钟初始化内存基本硬件初始化判断启动方式usb 硬盘 光驱区别系统存放位置和读取方式引导程序固化在硬盘存储数据最前面的部分识别对应的操作系统选择默认第一个加载对应操作系统操作系统无图形化界面文件系统NTFS/FAT(16/32):规定数据如何组成为文件/文件夹记录内存使用情况应用程序桌面图形化嵌入式iRom code(厂家固化)基本硬件配置需要的时钟和设备判断启动方式emmc USB ad卡将bootloader第一个阶段的代码加载到IRAM芯片内部RAMIRAM中运行bootloader第一阶段SPL代码初始化整个系统的时钟初始化内存将完整的bootloader搬运到内存中内存中运行bootloader第二阶段代码初始化开发版硬件设备(网卡串口 usb)加载对应操作系统内存运行操作系统挂载文件系统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协议在linux中搭建对应环境sudo apt-get install tftpd-hpa(服务器程序)sudo apt-get install tftp-hpa(客户端程序)用来进行对应测试创建tftpdoot文件夹保存对于tftp服务器文件配置对于tftp的设置文件夹路径vi /etc/default/tftp-hpaTFTP_DIRTORY路径权限“sudo chmod 777 -R 目录”重启tftp的服务sudo service tftp-hpa resever测试本都回环测试 tftp 127.0.0.1 get *.c quit下载到内存 tftp 内存地址 文件名uboot的参数通过tftp下载对应的文件镜像到开发板print打印当前的参数setenvserverip(tftp服务器虚拟机ip)setenvipaddr(开发板ip)setenvgatewayip(网关的ip)setenvethaddr(mac地址)saveenv(保存对应参数到emmc)测试ping192.168.2.1(ping网关)ping192.168.2.25ping服务器tftp 0x41000000 uImage下载linux镜像文件到内存运行内存RAM)tftp 0x43000000 ramdisk.img下载文件系统镜像文件到内存运行内存RAMtftp 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启动流程分析iRom code(厂家固化的代码) IRom基本硬件配置需要的时钟和设备判断启动方式emmc USB ad卡将bootloader第一个阶段的代码SPL加载到IRAM芯片内部RAMBL1代码是由三星提供irom的代码在读取BL1的时候会对他做验证如果验证通过就运行它SPL(U-boot第一阶段代码 IRam设置为SVC特权模式设置异常向量表告诉内核异常向量表基址关闭CacheCPU内置高速小容量存储器和MMU初始化整个系统的时钟初始化内存将完整的bootloader搬运到内存中U-boot第二阶段代码 LPDDR设置为SVC特权模式设置异常向量表告诉内核异常向量表基址关闭CacheCPU内置高速小容量存储器和MMU执行_main函数设置栈指针sp清理bss段调用board_init_farch/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 三星 exynos44124个cortex-A9 ARM核 主频 1.4GHZboard origen-fs4412u-boot版本 u-boot-2013.01nfs(网络文件系统)通过网络的方式进行映射把一台主机上文件映射到另一台主机上它可以使用者访问网络上别处的文件就像在使用自己的计算机一样搭建sudo apt-get install nfs-kernel-server nfs服务器解压对应的文件系统rootfs.tar.gztar-xvf rootfs.tar·修改对应的配置/etc/exportnfs服务器可以被完成访问的目录/home/linux/fs4412/rootfs*(rw,sync,no_root_squash)(路径重启nfs的服务sudo service nfs-kernel-server restart测试找一块空目录sudo mount 127.0.0.1:/home/linux/fs4412/rootfs 空目录的路径创建一个文件在源文件查看是否存在如果存在代表环境没有任何问题解挂sudo umount --lazy 空目录的路径Linux操作系统编译arch —— 保存对应架构arch/arm/configs ----- linux 是通用 我们需要进行对应的配置芯片厂家配置exynos_defconfigarch/arm/boot/dts ----- 设备树信息arch/arm/compressed ----- 自解压的代码arch/arm/kernel/head.s ----- linux启动最开始的代码driver —— 驱动net —— 网络协议栈的代码编译//导入默认配置make ARCHarm exynos_defconfig//进行编译(编译架构)make ARCHarm CROSS_COMPILEarm-linux-生成四个镜像文件(最上面)vmlinux:.头部信息Linux镜像文件image去掉头部的信息镜像文件zImage自解压的代码去掉头部的信息镜像文件压缩uImage(arch/arch/arm/compressed)自解压的代码包含头部信息的Linux镜像文件压缩生产uboot专属的镜像文件make ARCH-arm CROSS_COMPILE-arm-linux- uImagesudo apt-get installuboot-tools测试uImage找不到文件系统bootargs参数传递有没有问题虚拟机nfs服务有没有生效网络通不通当前开发板1inux镜像要配置对应的nfs的功能网卡驱动移植我们Linux内核包含对应的网卡驱动我们只需要选择配置menuconfig菜单选择Linux镜像支持哪些功能DM9000nfsTCP/IP内核级网络配置nfs服务屏蔽不需要的时钟信号Image,zImage,uImage区别Image为zImage的内核的一种映像解压缩文件为了节省系统容量采用zImag文件其开头自带解压代码uImage为U-boot的专用映像文件U-boot的bootm命令无法启动zImage需要使用mkimage工具加上64字节的头文件内核版本加载位置生成时间大小等menuconfig .config Kconfig Makefile 关系menuconfiglinux内核提供菜单选项表示Linux内核支持哪些功能去餐馆里面的菜单.configlinux内核当前选择哪些功能 点菜的凭证Kconfig给Linux内核提供对应菜单选项 当前餐馆所有厨师会做的菜Makefiie管理Linux内核编译 (靠对应.config里面宏的配置Makefigobj -$(宏)xxx.oKconfig名称config 标识符标识符为省略CONFIG_的配置项类型type bool y(静态编译)和n(不选择)tristate y、m(动态加载)、nstring 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 ARCHarm CROSS_COMPILEarm-linux- dtbs添加对应的设备信息DM9000文件系统制作工具busybox 文件系统快速buildroot 文件系统 linux内核 bootloaderyocto 文件系统 linux内核 bootloaderlinux启动过程分析linux内核自解压入口 start保存参数关中断计算运行偏移修复GOT:全局变量、函数地址BSS 段清零存放程序未初始化的全局变量、静态变量初始化 C 运行环境打开 Cache:设置栈分配堆安全检查后进行解压搬移数据关闭 cache恢复机器 ID、atags跳转到真正 vmlinux 内核入口执行挂载根目录执行init程序initlinuxrcbin/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组合键ctrlAltDel重启/etc/inittab/etc/init.d/rcS/etc/fsatb配置自启动在bootargs参数中指定自己的程序init/linuxrc------init自己的程序缺点无法启动init程序默认启动init程序修改/etc/inittab,使用sysinitwaitoncerespawn修改/etc/init.d/rcS脚本文件添加程序例子/hello 后台运行修改/etc/profile脚本文件添加程序同3注意很多时候我们会选择在2或4中添加。2可以让自己的进程死掉后重新启动4可以让自己的程序在执行的时候执行的环境比较好。制作ramdisk文件制作镜像文件dd if/dev/zero oframdisk bs1k count8192大小为8M格式化这个镜像为ext2mkfs.ext2 -F ramdisk拷贝对应文件系统文件到镜像1.创建对应文件夹mkdir FileSystem2.挂载对应的ramdisk到新建的文件中sudo mount ramdisk FileSystem3.拷贝对应的文件到挂载目录sudo cp ./fs4412/rootfs/* ./ -a卸载对应挂载sudo umount FileSystem/压缩ramdisk为ramdisk.gzgzip --best -c ramdisk ramdisk.gz将格式化为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。操作系统如何找到动态库路径/etc/ld.so.conf配置文件写入库路径执行ldconfig更新缓存。最常用环境变量LD_LIBRARY_PATH临时指定库搜索路径终端生效。可执行程序内部写死 rpath 路径编译时-Wl,-rpathxxx。系统默认库目录/lib/usr/lib。问如果让你写一个程序被杀死后在自动启动起来该如何做shell 脚本监控​/etc/init.d/rcS​​​​​​#!/bin/sh while true do ./myapp sleep 1 doneLinux 系统 init 进程守护/etc/inittabrespawn父进程守护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 * -nRboard_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

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询