统一声明:
博客转载 声 明 : 本博客部分内容来源于网络、书籍、及各类手册。
        内容宗旨为方便查询、总结备份、开源分享。
        部分转载内容均有注明出处,如有侵权请联系博客告知并删除,谢谢!

百度云盘提取码:统一提取码: ziyu

Linux系统移植(推荐★★★★★) 最新更新+强化+个人网站:http://www.baiziqing.cn/index.php/archives/78/

在这里插入图片描述

百度云 Linux系统移植思维导图 下载链接:https://pan.baidu.com/s/1xTvwE9o8VlmnkBFh5oSOtg

一、环境搭建

在这里插入图片描述

1.1、嵌入式Linux开发

1.1.1、嵌入式系统定义
(1)、一般定义
以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统,对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。

(2)、广义定义
凡是带有微处理器的专用软硬件系统都可称为嵌入式系统。

(3)、特点
三低:成本、体积、功耗
三高:可靠性 安全性

1.1.2、通用嵌入式系统组成
(1)、硬件
Coretex-A9开发板:
   核心板:4片内存 1片EMMC
   外围板:外部IO

启动方式:
   EMMC: 0111
   SD卡:1000

(2)、软件
无os的嵌入式系统
   应用层
   驱动层
   硬件层
在这里插入图片描述
有os的嵌入式系统
   应用层
   内核层
   驱动层
   硬件层
在这里插入图片描述
1.1.3、基本组成与开发流层
Cross-complier:交叉编译器 --> arm-none-linux-gnueabi-gcc
bootloader: u-boot
kernel: 内核
rootfs: 根目录及目录下的所有文件统称根文件系统;
在这里插入图片描述
1.1.4、内核结构
应用层
系统调用
内核层
驱动层
硬件层
在这里插入图片描述

1.2、嵌入式Linux环境开发的搭建

硬件:主机、目标机、连接介质(RS232、网线、USB)

软件:交叉编译器

1.2.1、Linux环境下载与安装

转载 最新超详细VMware虚拟机下载与安装 链接:https://blog.csdn.net/qq_40950957/article/details/80467513

转载 VMware虚拟机安装Linux系统(详解版) 链接:http://c.biancheng.net/view/714.html

Ubuntu系统 下载 链接:https://cn.ubuntu.com/download

推荐:Ubuntu低版本可能不能上网下载,可以推荐我配置好的 Ubuntu 64_20.04 可上网高版本,直接解压打开使用VM打开即可。
在这里插入图片描述
Ubuntu 64_20.04 阿里云链接:https://www.aliyundrive.com/s/DWUDBP5KZsU
Ubuntu 64_20.04 百度云链接:https://pan.baidu.com/s/1OEYYSHQ1eTVJE-iHjWb7WQ

转载 VMware Workstation Ubuntu 20.04 LTS无法连接网络问题 参考链接:https://blog.csdn.net/qq_36393978/article/details/106472278

1.2.2、安装交叉编译器

百度云盘 交叉编译器 下载链接:https://pan.baidu.com/s/1E05MEdMvoUXh7S6ii7Nb-g

详情可参考上一章 《ARM系统移植 》5.3.1、环境搭建及第一个汇编 链接地址:https://blog.csdn.net/qq_43498137/article/details/119761322

(1)、解压交叉编译器到工作目录
解压命令:
tar -xvf gcc-4.6.4.tar.xz

(2)、添加交叉编译器到环境变量
vi /etc/bash. bashrc
最后一行添加:
export PATH=$PATH:/home/hqyj/gcc-4.6.4/bin

(3)、生效命令
source /etc/bash. bashrc

(4)、验证是否搭建成功
arm-linux-gcc -v

1.2.2、tftp
【服务器 -> Ubuntu端】

(1)、下载安装tftp服务器
需要高版本可上网的Ubuntu,才可下载
sudo apt-get install tftpd-hpa
在这里插入图片描述
(2)、验证
vi /etc/default/tftpd-hpa
有内容证明成功了
在这里插入图片描述
(3)、修改tftp服务器的配置文件
sudo vi /etc/default/tftpd-hpa
在这里插入图片描述
1 # /etc/default/tftpd-hpa
2
3 TFTP_USERNAME=“tftp”
4 TFTP_DIRECTORY="/home/hqyj/tftpd"   //指定tftp服务器的目录;自己创建的路径
5 TFTP_ADDRESS=“0.0.0.0:69”
6 TFTP_OPTIONS="-l -c -s"
在这里插入图片描述
修改好之后保存并提出即可:wq

(4)、重启服务
sudo service tftpd-hpa restart

【客户端 -> 开发板】

(1)、查看服务器端网络接口命令: ifconfig
在这里插入图片描述
(2)、开发板串口连接电脑
在这里插入图片描述

如果未显示端口或者读取不出端口号,可能未安装驱动 或 更新。
阿里云 串口驱动 下载链接:https://www.aliyundrive.com/s/NdJPk7ygj1F

(3)、打开串口工具

百度云 超级终端 下载链接:https://pan.baidu.com/s/12uwJeO1fOHJXsegW4K98uQ

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(4)、启动
开发板网络接口(网线)连接上电脑接口(网线)
选择开发板启动模式,(我这里选择的是TF/SD模式下启动)
启动开发板:打开开发板电源开关,迅速按电脑ENTER键(电脑任意键都可以),否则会进入Linux系统
在这里插入图片描述
(5)、打印环境信息:pri
在这里插入图片描述
(6)、设置参数的:set
设置开发板的ip:set ipaddr 192.168.7.210         /* ip可自行设置 */
设置服务器(Ubuntu)的ip:set serverip 192.168.7.28    /*需要与服务器(Ubuntu ip一样),Ubuntu 查看命令:ifconfig */
设置网关:set gatewayip 192.168.7.1           /*ip可自行设置 */
设置子网掩码:set netmask 255.255.255.0        /*需要与服务器(Ubuntu ip一样),Ubuntu 查看命令:ifconfig */
保存:save
在这里插入图片描述
(7)、测试服务器和客户端网络是否ping通
ping [服务器地址ip]
eg:ping 192.168.7.28
在这里插入图片描述
若ping通,则显示下列信息:
host 192.168.7.28 is alive

百度云 myled.bin 源文件下载链接:https://pan.baidu.com/s/1YLlUAIGiEHpbn4j7bIfcng

(8)、下载 文件
tftp 0x41000000 [文件名]

在这里插入图片描述
(9)、运行
go 41000000
在这里插入图片描述
补充:删除多余的设置
在这里插入图片描述
1.2.4、nfs配置
nfs配置见本章:4.1、【NFS】 网络文件系统

1.2.5、开发板烧写系统
下载内核(uImage) 、设备树(exynos4412-fs4412.dtb)、根文件系统(ramdisk.img)

(1)、测试服务器和客户端网络是否ping通
详细步骤参考上一节
在这里插入图片描述
(2)、下载
下载没有顺序要求,启动运行必须有要求。
把三个烧写系统源文件放在自己创建的服务器(Ubuntu)文件夹下

百度云 三个烧写系统源文件 下载链接:https://pan.baidu.com/s/1SYGyCBFaPvX7nQ_dFRD7qQ
在这里插入图片描述

下载内核:tftp 41000000 uImage
下载设备树:tftp 42000000 exynos4412-fs4412.dtb
下载根文件系统:tftp 43000000 ramdisk.img
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(3)、启动
启动顺序1.下载内核(uImage) -> 2.根文件系统(ramdisk.img) -> 3.设备树(exynos4412-fs4412.dtb)
启动运行:bootm 41000000 43000000 42000000
在这里插入图片描述
在这里插入图片描述
补充:启动失败的可能原因及解决办法
在这里插入图片描述
解决方法set bootargs root=/dev/ram rw console=ttySAC2,115200 init=/linuxrc clk_ignore_unused

1.2.6、编译生成的可执行文件下载到开发板
实现在ubuntu编辑c文件并编译,将编译生成的可执行文件下载到开发板运行

【Ubuntu】
(1)、新建一个 .c文件
创建文件: vi hello.c
编译文件:arm-none-linux-gnueabi-gcc hello.c
      arm-linux-gcc hello.c
拷贝文件:cp a.out /home/hqyj/tftpd    //拷贝到自己创建的服务器文件夹位置
在这里插入图片描述
在这里插入图片描述
补充:Linux下给文件权限
在这里插入图片描述
【开发板】
(1)、给开发板设置ip
ifconfig eth0 192.168.7.123    //ip可自定义
在这里插入图片描述
(2)、测试开发板与ubuntu是否网络连通
服务器(ubuntu) ip
测试开发板与ubuntu是否网络连通: ping 192.168.7.28
从服务器下载可执行文件: tftp -g -r a.out 192.168.7.28
在这里插入图片描述
(3)、运行可执行程序
给权限:chmod 777 a.out
运行:./a.out
在这里插入图片描述

1.3、GNU命令

1.3.1、readelf
显示elf格式可执行文件的信息

1.3.2、as
功能类似:gcc -c

1.3.3、size
size列出目标文件每一段的大小以及总体的大小

eg:
	size a.out
	
	text	   data	    bss	    dec	    hex	filename
	1526	    600	      8	   2134	    856	a.out

1.3.4、strip / arm-linux-strip --> 重点
用来丢弃目标文件中的全部或者特定符号,减小文件体积

eg:
	gcc main.c 
	objdump -Sl a.out > t_g 	//反汇编 将a.out反汇编成汇编
	strip a.out    				//去掉a.out中的调试符号
	objdump -Sl a.out > t_s

1.3.5、objdump / arm-linux-objdump --> 重点
将二进制文件反汇编成汇编文件

eg:
	gcc -g main.c
	sudo dmesg -c  			//记录日志信息
	./a.out
	dmesg  					//查看日志,得到错误信息出现的地址
	objdump -Sl a.out > t   //反汇编 直接定位到错误地址处查看错误原因

1.3.6、objcopy/arm-linux-objcopy --> 重点
将elf格式文件转bin格式

eg:
	objdump -O binary -S start.elf start.bin

1.3.7、addr2line
通过指令地址定位到指令的行号

二、U-Boot

在这里插入图片描述
Das U-Boot 是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算机系统结构,包括PPC、ARM、AVR32、MIPS、x86、68k、Nios与MicroBlaze。这也是一套在GNU通用公共许可证之下发布的自由软件。

2.1、Bootloader 简介

2.1.1、Bootloader 概念

  • Bootloader是硬件启动的引导程序,是运行操作系统的前提

  • 在操作系统内核或用户应用程序运行之前运行的一小段代码。
    对软硬件进行相应的初始化和设定,为最终运行操作系统准备好环境;

  • 在嵌入式系统中,整个系统的启动加载任务通常由 Bootloader来完成。

2.1.2、Bootloader 特点

  • Bootloader不属于操作系统,一般采用汇编语言和语言开发。
  • 在移植系统时,首先为开发板移植 Bootloader。
  • Bootloader不但依赖于CPU的体系结构,而且依赖于嵌入式系统板级设备的配置。
  • 定制化。

2.1.3、操作模式
(1)、自启动
适用于后期的开发人员 (内核 应用)

(2)、交互模式
使用u-boot移植的人员

2.1.4、Bootloader 两个阶段
(1)、第一个阶段:汇编阶段

  • 初始化基本的硬件(内存 时钟 …)
  • 把 bootloader 自搬运到内存中;
  • 设置堆栈指针并将bss段清零。为后续执行C代码做准备;
  • 跳转到第二阶段代码中

(2)、第二个阶段:c阶段

  • 初始化本阶段使用到的硬件(串口 gpio 网卡 …)
  • 等待命令
  • 执行命令

2.1.5、Bootloader 分类
GRUB:适用于x86平台 装双系统Ware

u-boot:受众广适用于各大平台

2.2、U-Boot 特点

代码结构清晰、易于移植(见目录结构)
支持多种处理器体系结构(见arch目录)
支持众多开发板(目前官方包中有200多种,见board目录)
命令丰富 --> 例如:set pri
支持网络协议 --> 例如:tftp网络协议
支持文件系统

2.3、U-Boot 命令

显示所有环境变量:pri / printenv

设置新的环境变量:set / setenv
   |–> set ipaddr 192.168.1.100

保存环境变量的值:save / saveenv

通过网络下载程序:tftp
   |–> tftp 地址 文件名 eg: tftp 0x4000000 uImage

通过串口 kermit办议下载二进制数据:loadb
   |–> loadb 0x4000000

movi 命令(不是 Ubuntu命令)
   |–> movi read/write kernel/uboot 内存地址
   |–> movi write rootfs addr size 写roofs到EMMC

自启动命令:bootcmd
  |–> set bootcmd tftp 41000000 uImage;tftp 42000000 exynos4412-fs4412.dtb;tftp 43000000 ramdisk.img;bootm 41000000 43000000 42000000
   bootm kernel-addr ramdisk-addr dtb-addr

给内核传递启动参数:bootargs
   |–> bootargs root=/dev/ram rw console=ttySAC2,115200 init=/linuxrc clk_ignore_unused
     |–> root=/dev/ram 根文件系统运行在内存
     |–> rw 根文件系统可读可写
     |–> console 串口2
     |–> init 进程为/linuxrc

SD – EMMC切换
SD卡:(1000)
   tftp 0x40000000 u-sd.bin
   movi write u-boot 0x40000000
EMMC:(0111)
   上电看效果
在这里插入图片描述

2.4、U-Boot 移植

【准备】
2.4.1、明确需求
将内核加载起来即可

2.4.2、准备:资料
uboot下载地址ftp://ftp.denx.de/pub/u-boot/
下载适合的即可,我下载的版本是:u-boot-2013.10.tar.bz2

解压命令:tar -xvf u-boot-2013.01.tar.bz2
在这里插入图片描述
2.4.3、uboot支不支持芯片
(1) 、支持: goto 4
(2) 、不支持: 下最新的uboot 芯片厂商 老板

2.4.4、uboot支不支持板子
(1)、 支持: goto 5
(2)、 不支持: 找最近的uboot 板子厂商要 借鉴:同芯片的板子

2.4.5、uboot启动流程
(1)、找入口地址
   Makefile -> 链接脚本(arch/arm/cpu/u-boot.lds) -> start.S(_start)(arch/arm/cpu/armv7/start.S)
     |–>_start
       |–> 切换cpu模式为SVC 关中断 设置向量表
       |–> bl cpu_init_cp15(关MMU caches)
       |–> bl cpu_init_crit
         |–> b lowlevel_init (board/samsung/fs4412/lowlevel_init.S)
            |–>if(uboot is not ram)
              |–> 初始化时钟 初始化内存

            |–> bl uart_asm_init (串口初始化)
            |–> bl tzpc_init (trust zone初始化:保存比较重要的数据)
       |–>bl _main (arch/arm/lib/crt0.S )
         |–> 设置堆栈 清空bss
         |–>board_init_r (arch/arm/lib/board.c)
            |–> 各种设备的初始化(电源 串口 中断 网络 控制台 日志…)
            |–>死循环
              for ( ; ; )
              {
                main_loop(); //等待命令 执行命令
              }

2.4.6、移植
(1)、借鉴:同芯片的板子(origen)
   cp -a board/samsung/origen/ board/samsung/fs4412/
   cp include/configs/origen.h include/configs/fs4412.h

(2)、在Makefile中指定交叉编译头

	#ifeq ($(HOSTARCH),$(ARCH))
	185 CROSS_COMPILE ?= arm-none-linux-gnueabi-
	186 #endif
	
	编译文件:arm-none-linux-gnueabi-gcc hello.c
    		 arm-linux-gcc hello.c

(3)、make distclean //清除其他板子生成的文件
   清除一次即可

(4)、make fs4412_config
   vi boards.cfg 添加我们自己的板子
     |–> fs4412 arm armv7 fs4412 samsung exynos
在这里插入图片描述
(5)、make //编译

2.4.7、将u-boot.bin拷贝到tftp目录
cp u-boot.bin /home/farsight/tftpboot

2.4.8、SD卡烧写

百度云 SD卡烧写文件 下载链接:https://pan.baidu.com/s/1cDCGik_aj68Z2PgAbGUIjA

(1)、将sd卡插入电脑pc端
在这里插入图片描述
(2)、将sd卡格式化
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(2)、烧写系统
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.4.9、验证
SD卡启动:
   tftp 0x41000000 u-boot.bin
   tftp 0x41000000 u.bin
   movi write uboot 0x41000000
在这里插入图片描述
断电切换启动方式到EMMC,上电。

2.4.10、将tftp下载到板子,看效果
【现象】
板子变板砖。。。

【原因】
硬件:利用测试工具测试硬件 --> 没有问题
软件:
   死循环
   程序没有执行
   …

【验证】

百度云 系统移植代码 下载链接:https://pan.baidu.com/s/1m3NV9BkLtGngXyXvk19N5g

点灯大法
在程序最开始位置点灯(arch/arm/cpu/armv7/start.S)添加点灯程序:
在这里插入图片描述

	/*点LED2  GPX2_7  GPX2CON GPX2DAT */
	ldr r1,=0x11000c40
	ldr r2,[r1]
	bic r2,#0xf0000000
	orr r2,#0x10000000
	str r2,[r1]
	
	ldr r1,=0x11000c44
	ldr r2,[r1]
	orr r2,#0x80
	str r2,[r1]

【现象】
板子依然是板砖。。。

百度云 booting sequence 下载链接:https://pan.baidu.com/s/1tJcVGNIjm3FyqlwpEG_rMg

Ubuntu 没有执行 --> booting sequence (芯片手册)
   |–> 先执行iROM,简单的初始化,例如:时钟 内存
   |–> iROM将1BL1加载到SRAM(内部256k内存)中执行,并做check校验,BL1做芯片级的初始化
   |–> BL1将BL2加载到SRAM中执行,BL2做DRAM的初始化,例如:DRAM的初始化
   |–> BL2将u-boot.bin加载DRAM中执行
BL1:由Samsung 提供,一般由芯片厂商提供
BL2:Samsung 不提供,一般由板子厂商提供

SD卡启动:
   512B + BL1(8k) + BL2(16k) + u-boot.bin
EMMC启动:
   BL1(8k) + BL2(16k) + u-boot.bin

【验证】
修改
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
编译
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
将BL1+BL2+u-boot.bin --> u.bin

SD卡启动 --> tftp 41000000 u.bin -> movi write uboot 41000000 -> EMMC启动

【现象】
板子上的灯终于亮了。。。。但在闪烁,表示板子在重启

百度云 系统移植点亮LED 源代码下载链接:https://pan.baidu.com/s/1dac3smdsiv9idJ_PBA9z5Q

【分析】
(1)、异常(野指针 段错误…)
(2)、看门狗 --> 关 板子还是复位
在这里插入图片描述
(3)、复位 <- 电源模块 <- 接收到了复位信号 <- 谁发送复位信号给电源模块
   解决:不让电源模块接收手动复位信号 --> ONO拉高 --> GPX0_2管脚拉高

百度云 S5M8767A01 / 数据手册 下载链接:https://pan.baidu.com/s/1BO1z0N8QTvUZxagNxxK7ZQ

在这里插入图片描述
在这里插入图片描述
在start.S添加以下代码:

/*关闭电源模块手动复位功能  GPX0_2管脚输出高电平*/
ldr r1,=0x11000c00
ldr r2,[r1]
bic r2,#0xf00
orr r2,#0x100
str r2,[r1]

ldr r1,=0x11000c04
ldr r2,[r1]
orr r2,#0x4
str r2,[r1]

在这里插入图片描述
【现象】
LED 常亮,不闪烁了!
板子终于不复位了,但是串口没显示。。。

【分析】
串口没有显示的原因:
   硬件:没问题
   软件:
      1)、串口初始化不成功
      2)、波特率不是115200bps

【验证】
(1)、查看初始化有没有有问题
vi board/samsung/fs4412/lowlevel_init.S
在这里插入图片描述

uart_asm_init:
/*GPA0组管脚功能配置为串口管脚*/
	ldr	r7, =EXYNOS4_GPIO_PART1_BASE     		-->  0x11400000
	/* setup UART0-UART3 GPIOs (part1) */
	mov	r0, r7                           		--> r0 = 0x11400000
	ldr	r1, =EXYNOS4_GPIO_A0_CON_VAL     		--> r1 = 0x22222222
	str	r1, [r0, #EXYNOS4_GPIO_A0_CON_OFFSET]  	--> *(0x11400000) = 0x22222222
/*GPA1组管脚功能配置为串口管脚*/
	ldr	r1, =EXYNOS4_GPIO_A1_CON_VAL		   	--> r1 = 0x222222
	str	r1, [r0, #EXYNOS4_GPIO_A1_CON_OFFSET]  	--> *(0x11400020) = 0x222222

/*串口uart2配置*/
	ldr r0, =EXYNOS4_UART_BASE					--> r0 = 0x13800000
	add r0, r0, #EXYNOS4_DEFAULT_UART_OFFSET    --> r0 = 0x13800000+0x020000 = 0x13820000

	ldr	r1, =ULCON_VAL 							--> r1 = 0x3						
	str	r1, [r0, #ULCON_OFFSET]					--> *(0x13820000) = 0x3
	ldr	r1, =UCON_VAL							--> r1 = 1 << 9 | 1 << 8 | 1 << 7 | 1 << 6 | 1 << 2 | 1 << 0
	str	r1, [r0, #UCON_OFFSET]                  --> *(0x13820004) = r1
	ldr	r1, =UFCON_VAL							--> r1 = 1<<8 | 1<<4 | 1<<0
	str	r1, [r0, #UFCON_OFFSET]				   -->*(0x13820008) = r1
	ldr	r1, =UBRDIV_VAL							-->	0x35
	str	r1, [r0, #UBRDIV_OFFSET]			  --> *(0x13820028)
	ldr	r1, =UFRACVAL_VAL						--> 0x4
	str	r1, [r0, #UFRACVAL_OFFSET]            --> *(0x1382002c)
	

在这里插入图片描述
(2)、看波特率是否是115200bps --> 确定时钟为100MHZ --> 确定时钟源+分频值

ldr	r0, =EXYNOS4_CLOCK_BASE   	--> r0 = 	0x10030000
/* UART[0:4] */
ldr	r1, =CLK_SRC_PERIL0_VAL   	-->  r1 = 6<<8 
ldr	r2, =CLK_SRC_PERIL0_OFFSET 	--> r2 = 0xC250
str	r1, [r0, r2]               	--> *(0x1003c250) = 6<<8   时钟源:SCLKMPLL_USER_T

/* CLK_DIV_PERIL0: UART Clock Divisors */
ldr	r1, =CLK_DIV_PERIL0_VAL   	--> r1 = 7<<8
ldr	r2, =CLK_DIV_PERIL0_OFFSET 	-->r2 = 0xC550
str	r1, [r0, r2]               	-->*(0x1003c550) = 7<<8
uart时钟:
		SCLK_UART2 = MOUTUART2/(UART2_RATIO + 1) = SCLKMPLL_USER_T/(7+1) = 800M/8 = 100M
	

【修改】
串口时钟有可能没有初始化,在 uart_asm_init(board/samsung/fs4412/lowlevel_init.S)中添加串口的时钟初始化

/*串口时钟初始化*/
ldr	r0, =EXYNOS4_CLOCK_BASE   
/* UART[0:4] */
ldr	r1, =CLK_SRC_PERIL0_VAL  
ldr	r2, =CLK_SRC_PERIL0_OFFSET 
str	r1, [r0, r2]              

/* CLK_DIV_PERIL0: UART Clock Divisors */
ldr	r1, =CLK_DIV_PERIL0_VAL   
ldr	r2, =CLK_DIV_PERIL0_OFFSET 
str	r1, [r0, r2]         

同时屏蔽trustzone初始化,即:
   @ bl tzpc_init /初始化非trustzone 而uboot里边有trustzone数据/
在这里插入图片描述
在这里插入图片描述
【效果】
超级终端命令:
   tftp 0x41000000 u.bin
   movi write uboot 0x41000000

断电切换启动方式到EMMC模式,上电。
在这里插入图片描述
修改串口输出信息
vi board/samsung/fs4412/origen.c
在这里插入图片描述
在这里插入图片描述
vi include/configs/fs4412.h
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
超级终端命令:
   tftp 0x41000000 u.bin
   movi write uboot 0x41000000

断电切换启动方式到EMMC模式,上电。
在这里插入图片描述

百度云 系统移植串口 源代码下载链接:https://pan.baidu.com/s/1ZjA1Us9q2uk1CMK8ADVjbw

串口能够正常显示了,但是不认识网络命令
在这里插入图片描述
【修改】
vi include/configs/fs4412.h
   #undef CONFIG_CMD_PING --> #define CONFIG_CMD_PING
   #undef CONFIG_CMD_NET --> #define CONFIG_CMD_NET
在这里插入图片描述
【编译看效果】
ping tftp命令认识了,但是卡住了
在这里插入图片描述
【分析】
>可参考 网络 文档下载链接:https://pan.baidu.com/s/1zkI4Fmh5qyKMysj5OrcBbw
网卡出问题 --> 网卡初始化出问题 --> ???
   |–> 死循环
   |–> 网卡驱动有问题 -> 网卡初始化(arch/arm/lib/board.c)
     |–> eth_initialize(gd->bd);
       |–>board_eth_init(bis) (board/samsung/fs4412/origen.c定义) 借鉴其他板子
         |–> dm9000_initialize(bd_t *bis) //板子的网卡初始化
在这里插入图片描述
【验证】
(1)、在 include/configs/fs4412.h文件中添加以下头文件
在这里插入图片描述

#ifdef CONFIG_CMD_NET
#define CONFIG_DRIVER_DM9000		1
#define CONFIG_DM9000_BASE		0x05000000            /*DM9000的基地址 芯片访问DM9000的基地址(即SMC bank1的基地址)*/
#define DM9000_IO			 CONFIG_DM9000_BASE       /*总线传输数据之前先指定地址*/
#define DM9000_DATA			(CONFIG_DM9000_BASE+4)    /*指定数据*/

#define CONFIG_ETHADDR      11:22:33:44:55:66
#define CONFIG_IPADDR		192.168.7.213
#define CONFIG_SERVERIP     192.168.7.31
#define CONFIG_GATEWAYIP	192.168.7.1
#define CONFIG_NETMASK		255.255.255.0
#endif

在这里插入图片描述
(2)、在 board/samsung/fs4412/origen.c 添加以下代码 --> 借鉴其他板子
在这里插入图片描述

#ifdef CONFIG_DRIVER_DM9000
int board_eth_init(bd_t *bis)
{
	return dm9000_initialize(bis);
}
#endif

在这里插入图片描述
【现象】
ping有反应了,但是报0x05000000错误
error:
   dm9000 not found at 0x05000000 id: 0x00000000
在这里插入图片描述
【分析】
0x0x05000000错误 --> SROM驱动有问题 --> srom配置文件

借鉴 s59板子:

void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf)
{
	u32 tmp;
	struct s5p_sromc *srom =
		(struct s5p_sromc *)samsung_get_base_sromc();

	/* Configure SMC_BW register to handle proper SROMC bank */
	tmp = srom->bw;
	tmp &= ~(0xF << (srom_bank * 4));
	tmp |= srom_bw_conf;
	srom->bw = tmp;

	/* Configure SMC_BC register */
	srom->bc[srom_bank] = srom_bc_conf;
}

static void smc9115_pre_init(void)
{
	u32 smc_bw_conf, smc_bc_conf;

	struct s5pc100_gpio *const gpio =
		(struct s5pc100_gpio *)samsung_get_base_gpio();

	/* gpio configuration GPK0CON */
	s5p_gpio_cfg_pin(&gpio->k0, CONFIG_ENV_SROM_BANK, GPIO_FUNC(2));

	/* Ethernet needs bus width of 16 bits */
	smc_bw_conf = SMC_DATA16_WIDTH(CONFIG_ENV_SROM_BANK);
	smc_bc_conf = SMC_BC_TACS(0x0) | SMC_BC_TCOS(0x4) | SMC_BC_TACC(0xe)
			| SMC_BC_TCOH(0x1) | SMC_BC_TAH(0x4)
			| SMC_BC_TACP(0x6) | SMC_BC_PMC(0x0);

	/* Select and configure the SROMC bank */
	s5p_config_sromc(CONFIG_ENV_SROM_BANK, smc_bw_conf, smc_bc_conf);
}

int board_init(void)
{
	smc9115_pre_init();

	gd->bd->bi_arch_number = MACH_TYPE_SMDKC100;
	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;

	return 0;
}

跟踪:
方式1:
   board_eth_init()
     |–>s5p_config_sromc()

方式2:(建议)
   board_init() --> 定义 board/samsung/fs4412/origen.c
     |–>exynos4412_pre_init() --> 自己定义
       |–>exynos4412_config_sromc() -->自己定义

【验证】
在文件 --> vi board/samsung/fs4412/origen.c 添加以下代码:
在这里插入图片描述

struct exynos4_gpio_part1 *gpio1;
struct exynos4_gpio_part2 *gpio2;

#ifdef CONFIG_DRIVER_DM9000
#define EXYNOS4412_SROMC_BASE 0X12570000

#define DM9000_Tacs     (0x1) 
#define DM9000_Tcos     (0x1) 
#define DM9000_Tacc     (0x5) 
#define DM9000_Tcoh     (0x1) 
#define DM9000_Tah      (0xC) 
#define DM9000_Tacp     (0x9)   
#define DM9000_PMC      (0x1)  

struct exynos_sromc {
unsigned int bw;
unsigned int bc[6];
};

void exynos_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf)
{
	u32 tmp;
	struct exynos_sromc *srom =(struct exynos_sromc *)(EXYNOS4412_SROMC_BASE);

	/* Configure SMC_BW register to handle proper SROMC bank */
	tmp = srom->bw;
	tmp &= ~(0xF << (srom_bank * 4));
	tmp |= srom_bw_conf;
	srom->bw = tmp;

	/* Configure SMC_BC register */
	srom->bc[srom_bank] = srom_bc_conf;
}

static void dm9000aep_pre_init(void)
{
	unsigned int tmp;
	unsigned char smc_bank_num = 1;
	unsigned int     smc_bw_conf=0;
	unsigned int     smc_bc_conf=0;

	/* gpio configuration */
	writel(0x00220020, 0x11000000 + 0x120);
	writel(0x00002222, 0x11000000 + 0x140);
	/* 16 Bit bus width */
	writel(0x22222222, 0x11000000 + 0x180);
	writel(0x0000FFFF, 0x11000000 + 0x188);
	writel(0x22222222, 0x11000000 + 0x1C0);
	writel(0x0000FFFF, 0x11000000 + 0x1C8);
	writel(0x22222222, 0x11000000 + 0x1E0);
	writel(0x0000FFFF, 0x11000000 + 0x1E8);              
	smc_bw_conf &= ~(0xf<<4);
	smc_bw_conf |= (1<<7) | (1<<6) | (1<<5) | (1<<4);
	smc_bc_conf = ((DM9000_Tacs << 28)
			| (DM9000_Tcos << 24)
			| (DM9000_Tacc << 16)
			| (DM9000_Tcoh << 12)
			| (DM9000_Tah << 8)
			| (DM9000_Tacp << 4)
			| (DM9000_PMC));
	exynos_config_sromc(smc_bank_num,smc_bw_conf,smc_bc_conf);
}
#endif

#ifdef CONFIG_DRIVER_DM9000
int board_eth_init(bd_t *bis)
{
	return dm9000_initialize(bis);
}
#endif

int board_init(void)
{
	gpio1 = (struct exynos4_gpio_part1 *) EXYNOS4_GPIO_PART1_BASE;
	gpio2 = (struct exynos4_gpio_part2 *) EXYNOS4_GPIO_PART2_BASE;

#ifdef CONFIG_DRIVER_DM9000
	dm9000aep_pre_init();
#endif

	gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);

	return 0;
}

在这里插入图片描述
【效果】
tftp终于is alive 了
在这里插入图片描述
自启动:
EMMC 模式下上电不管,让开发板自启动。
set bootcmd tftp 41000000 uImage; tftp 42000000 exynos4412-fs4412.dtb;tftp 43000000 ramdisk.img;bootm 41000000 43000000 42000000
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

百度云 本节源码链接:https://pan.baidu.com/s/19eAUK4idBExs1v_2HPWmfg

三、内核移植

在这里插入图片描述

3.1、linux内核

(1)、将底层硬件抽象向上提供统一的接口;

(2)、文件系统fs:将用户数据转化成文件格式存储,向下将文件转为二进制字节流存储在硬件上;

(3)、进程线程:提升性能

(4)、MMU:虚拟内存,用户不需要关心物理内存

内核官网:https://www.kernel.org/

3.2、内核移植

3.2.1、将内核源码解压 linux-3.14.tar.xz --> linux-3.14目录

百度云 linux-3.14.tar.xz 下载链接:https://pan.baidu.com/s/1ZCKoLlG4doNaC0bUoq_yVA

自己创建一个文件夹,解压在Linux下
解压命令:tar -xvf linux-3.14.tar.xz
在这里插入图片描述
3.2.2、目录介绍
arch:不同架构的芯片
Documentation:文档
init:内核初始化
lib:内核用到的库文件
sound:音频
block:块设备(比较重要 磁盘时块设备)
driver:驱动
ipc:进程间通信方式
tools:工具
firmware:固件 -> 芯片起来之前预先烧写的东西
samples:示例
user:用户的东西
fs:文件系统
mm:内存管理
scripts:脚本文件所在目录(很有用)
virt:内核的虚拟机的东西在里边
include:头文件
kernel:内核的逻辑
net:网络相关的
security:安全加密的一些东西
security:安全加密的一些东西

3.2.3、编译内核
(1)、make menuconfig //选择需要添加/删除的模块
make menuconfig
在这里插入图片描述
如果报错可能:1、缺库。2、把Linux窗口页面拉大一些即可。
下载库:sudo apt-get install libncurses5-dev

<Enter> 	进入子菜单
---> 		有子目录
<N> 		不选中
<Y> 		选中
</> 		搜索
<ESC>		退出

(2)、修改Makefile
vi Makefile
在这里插入图片描述
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-

(3)、修改配置文件为ARM平台的
make exynos_defconfig //文件位置目录:(arch/arm/configs)
make exynos_defconfig
在这里插入图片描述
在这里插入图片描述
(4)、编译内核
make uImage
在这里插入图片描述
第一次编译比较久,以上编译报
【问题】
问题:“mkimage” command not found - U-Boot images will not be built
   解决1:
     sudo apt-get install uboot-mkimage //安装mkimage命令
     sudo apt-get install u-boot-tools

   解决2:
     cp u-boot-2013.01/tools/mkimage /usr/bin //将uboot中的mkimage工具添加到环境变量

     注意:
       默认生成zImage

重新编译:make uImage
在这里插入图片描述
在这里插入图片描述
(5)、拷贝uImage到tftp(服务器)目录
cp uImage /home/farsight/tftpboot
cp uImage /home/hqyj/tftpd
在这里插入图片描述
在这里插入图片描述
3.2.4、编译设备树
设备树
  树形结构描述设备

(1)、借鉴origen板子
cp exynos4412-origen.dts exynos4412-fs4412.dts
在这里插入图片描述
在这里插入图片描述
(2)、添加我们自己的板子设备树到Makefile
vi arch/arm/boot/dts/Makefile
在这里插入图片描述
在文件中添加:
   exynos4412-fs4412.dtb
在这里插入图片描述
(3)、编译设备树(内核主目录编译)
make dtbs
DTC arch/arm/boot/dts/exynos4412-fs4412.dtb
在这里插入图片描述
(4)、拷贝exynos4412-fs4412.dtb到tftp目录
cp exynos4412-fs4412.dtb /home/farsight/tftpboot
cp arch/arm/boot/dts/exynos4412-fs4412.dtb /home/hqyj/tftpd/
在这里插入图片描述
在这里插入图片描述
(5)、下载内核与设备树
板子EMMC启动

【现象】
ifconfig不能配置ip,tftp不能下载文件
在这里插入图片描述
在这里插入图片描述
【解决】
make menuconfig
   Location:
   -> Device Drivers
     -> Network device support (NETDEVICES [=y])
       -> Ethernet driver support (ETHERNET [=y])
         |–> DM9000 (DM9000 [=y])
在这里插入图片描述
保存,esc退出即可!

make uImage
cp uImage /home/hqyj/tftpd

下载开发板,emmc启动

【现象】
ifconfig还是不能配置ip,tftp还是不能下载文件,驱动准备好了,设备还没有。
在这里插入图片描述
错误:网络不可达

【分析】
有可能没有网卡设备,借鉴:arch/arm/boot/dts/s3c6410-mini6410.dts
在这里插入图片描述
在这里插入图片描述
【解决】
在设备树添加DM9000网卡设备,vi arch/arm/boot/dts/exynos4412-fs4412.dts 添加以下代码:

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>

	  srom-cs1@0x05000000 {
      compatible = "simple-bus";
      #address-cells = <1>;
      #size-cells = <1>;
      reg = <0x05000000 0x1000000>;  /*0x05000000:SROM1的地址   0x1000000:SROM1的大小*/
      ranges;

      ethernet@0x05000000 {
         compatible = "davicom,dm9000";
         reg = <0x05000000 0x2 0x05000004 0x2>;
          interrupt-parent = <&gpx0>; /*DM9000的中断管脚 GPX0_6*/
          interrupts = <6 IRQ_TYPE_LEVEL_HIGH>;
          davicom,no-eeprom;
       };
   };

在这里插入图片描述
在这里插入图片描述
make dtbs
cp arch/arm/boot/dts/exynos4412-fs4412.dtb /home/hqyj/tftpd/
在这里插入图片描述
开发板emmc启动
启动:boot
在这里插入图片描述
uboot设置bootargs:
set bootargs root=/dev/ram rw console=ttySAC2,115200 init=/linuxrc clk_ignore_unused
在这里插入图片描述
自动获取ip:
udhcpc
在这里插入图片描述
下载文件:
在这里插入图片描述

百度云 3.2内核移植 源码下载链接:https://pan.baidu.com/s/1u-0sgAszxlkpw0f4Mf58tg

【内核自动获取ip】
set bootargs root=/dev/ram rw console=ttySAC2,115200 init=/linuxrc clk_ignore_unused ip=192.168.7.213(板子)
在这里插入图片描述
【自动配置ip】
make menuconfig //自动配置ip
   |–>Networking support > Networking options > IP: kernel level autoconfiguration [ y ]
在这里插入图片描述
内核移植,文件可以成功下载!

四、根文件系统

在这里插入图片描述

4.1、【NFS】 网络文件系统

服务器端:【ubuntu】
sudo apt-get install nfs-kernel-server   //下载安装nfs网络服务器
在这里插入图片描述
mkdir /home/farsight/nfs/rootfs     //在家目录下创建nfs服务器目录
在这里插入图片描述

vi /etc/exports           //修改配置文件
   /home/farsight/nfs/rootfs *(rw,sync,no_root_squash,no_subtree_check)
在这里插入图片描述
在这里插入图片描述
启动服务:sudo service nfs-kernel-server restart
在这里插入图片描述
解压 rootfs到nfs目录
在这里插入图片描述

百度云 rootfs.tar.xz 源文件下载链接:https://pan.baidu.com/s/1cnX0FJ53DawQ1h-RBIZKbw

客户端:【内核】

百度云 Linux-3.14 源码下载链接:https://pan.baidu.com/s/1u-0sgAszxlkpw0f4Mf58tg

在这里插入图片描述
make menuconfig

	|-> File systems
			|->Network File Systems
				|->  <*>   NFS client support
				|->  [*]   Root file system on NFS

在这里插入图片描述
make uImage
cp uImage /home/farsight/tftpboot
cp arch/arm/boot/uImage /home/hqyj/tftpd/
在这里插入图片描述
修改bootargs/bootcmd:
set bootcmd tftp 41000000 uImage;tftp 42000000 exynos4412-fs4412.dtb;bootm 41000000 - 42000000

set bootargs root=/dev/nfs nfsroot=(服务器IP)192.168.7.143:/home/farsight/nfs/rootfs(nfs目录),v3 rw console=ttySAC2,115200 clk_ignore_unused init=/linuxrc ip=192.168.7.213(板子IP)
在这里插入图片描述
可sd卡;emmc启动
在这里插入图片描述
在这里插入图片描述
后续不需要TFTP下载,直接就在根文件系统下

4.2、【linux系统常用调试方法】

4.2.1、内核和驱动的调试
kgdb
printk --> 驱动开发里边打印用到
LED点灯大法 --> 内核最开始的代码
串口打印 --> 内核起来之前用puts或printk打印信息
   |–> puts
   |–>printk 用于内核启动起来之后调试
查看日志信息工具:通过内核的日志信息查看程序出现问题的地方
   oops panic --> 错误报告
   oops异常:会导致内核异常
   panic异常:也会导致内核异常
硬件调试器:
   BDI或JTAG工具调试

4.2.2、应用程序的调试
gdb
printf
strace:可以跟踪程序执行流程 可以跟踪到封装的库里边

4.2.3、printk有8种打印级别
分级别的原因:
   内核的代码为了后续定位问题方便,会加printk的打印输出,这些输出不能加太多,因为内核一直在运行,长时间之后输出的日志文件就会非常大,所以需要控制打印。
   在产品发布时指定打印级别,内核就会按照级别打印,优先级比指定级别高的打印,低的不打印;

4.3、【根文件系统】

4.3.1、概念
根目录即目录下所有文件统称根文件系统;

4.3.2、目录文件遵循FHS标准
/bin
/sbin
/etc
/lib
/root
/tmp
/mnt
linuxrc
/proc 进程的信息

4.3.3、linux系统启动流程(重点)

bootloader
	|
	|
   内核
	|
	|
挂载roofs
	|
	|
init(第三方)  --> inittab --> /etc/init.d/rcS
	|
	|
shell(终端) 执行各种linux命令

4.3.4、inittab (/etc/inittab)–> 指定内核的行为规则
::sysinit:/etc/init.d/rcS 指定内核执行的第一个文件 /etc/init.d/rcS
::askfirst:-/bin/sh 询问方式登录shell

4.3.5、/etc/init.d/rcS
#!/bin/sh
#This is the first script called by init process
/bin/mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev>/proc/sys/kernel/hotplug
mdev -s

/bin/mount -a 把/etc/fstab里边的东西挂载 cat fstab
       |–> /sys 与 内核的 sysfs挂载起来
       |–> /proc 与 内核的 proc挂载起来
     ssh登录需要的东西
     支持设备的热插拔:usb插拔时不用重启系统

4.4、【BusyBox】制作根文件系统

百度云 busybox-1.22.1.tar.bz2 源码下载链接:https://pan.baidu.com/s/1_kcfiXMJ_P-narkdxS_eYA

(1)、解压:tar -xvf busybox-1.22.1.tar.bz2
在这里插入图片描述
(2)、make menuconfig
   Busybox Settings —>
     Build Options —>
       |–>[*] Build BusyBox as a static binary (no shared libs)
       |–> (arm-linux-) Cross Compiler prefix
在这里插入图片描述
在这里插入图片描述
(3)、make 编译
在这里插入图片描述
(4)、make install.o展开成具体命令*
在这里插入图片描述
(5)、cd _install
在这里插入图片描述
(6)、创建文件夹:mkdir dev etc lib mnt proc root sys tmp
在这里插入图片描述
(7)、cp /home/farsight/nfs/rootfs/etc/ etc -a //借鉴roofs下边的etc目录文件*
cp -a /home/hqyj/nfs/rootfs/etc/ *./
在这里插入图片描述

(8)、cp /home/farsight/gcc-4.6.4/arm-arm1176jzfssf-linux-gnueabi/lib/ ./ -a **
cp -a /home/hqyj/gcc-4.6.4/arm-arm1176jzfssf-linux-gnueabi/lib/
./ -a
在这里插入图片描述
在这里插入图片描述
(9)、arm-none-linux-gnueabi-strip * //压缩lib的体积
在这里插入图片描述

百度云 根文件系统制作 源码下载链接:https://pan.baidu.com/s/1NHfkJ0qYh0bTEFOutqDd0w

4.5、【ramdisk.img <-- rootfs】

通过NFS测试以后,就可以制作 ramdisk文件系统了,具体如下:

(1)、制作一个大小为8M的镜像文件
$ cd ~
$ dd if-/dev/zero of-ramdisk bs=lk count=8192 (ramdisk 8M)

(2)、格式化这个镜像文件为ext2
$ mkfs.ext2 -F ramdisk

(3)、在 mount下面创建 initrd目录作为挂载点
$ sudo mkdir /mnt/initrd

(4)、将这个磁盘镜像文件挂载到/ mnt/initrd下
注意这里的 ramdisk不能存放在 rootfs目录中
$ sudo mount -t ext2 ramdisk /mnt/initrd

(5)、将我们的文件系统复制到 ramdisk中
将测试好的文件系统里的内容全部拷贝到/mnt/ initrd目录下面
$ sudo cp /source/rootfs/* /mnt/initrd - a

(6)、卸载 initrd
$ sudo umount /mnt/initrd

(7)、压缩 ramdisk为 ramdisk.gz并拷贝到/ tftpboot下
$ gzip --best -c ramdisk > ramdisk.gz

(8)、格式化为 uboot识别的格式
$ mkimage -n “ramdisk” -A arm-O linux -T ramdisk-C gzip-d ramdisk.gz ramdisk.img
$ cp ramdisk.img /tftpboot

(9)、配置内核支持 RAMDISK
制作完 ramdisk. img后,需要配置内核支持 RAMDISK作为启动文件系统

make menuconfig
File systems  -->
	<*> Second extended fs support
Device drivers
	SCSI device support -->
		<*> SCSI disk support
	Block devices -->
		<*>raM block device support
	(16) Default number of RaM disks
	(8192) Default ram disk size( kbytes)(修改为8M
General setup	-->
	[*]Initial RAM filesystem and ram disk (initramfs/initrd) support

重新编译内核,复制到 tftpboot

转载 制作Ramdisk文件系统 可参考链接:https://blog.csdn.net/u014213012/article/details/51582826

(10)、在U-BOOT命令行重新设置启动参数
setenv bootcmd tftp 41000000 ulmage; tftp 42000000 exynos4412-fs44 12 dtb; titp 43000000
ramdisk. img; bootm410000004300000042000000
saveenv
重新启动开发板查看能否正常启动

练习:

  1. /etc的 profile init.d inittab fstab写一下,参考roofs的etc
    转载:/etc/inittab,/etc/init.d/rcS和/etc/profile分析 可参考链接:https://blog.csdn.net/Qiuoooooo/article/details/79300739
  2. rootfs做成ramdisk.img
    转载:制作rootfs文件 ramdisk 可参考链接:http://blog.chinaunix.net/uid-24148050-id-95542.html

跳转:上一篇、ARM体系结构!

跳转:上一篇、ARM体系结构!

跳转:下一篇、Linux驱动开发!

更 新 中 . . .

跳转:开头

Logo

更多推荐