Linux系统移植
Linux系统移植一、环境搭建1.1、嵌入式Linux开发1.2、嵌入式Linux环境开发的搭建二级目录三级目录一、环境搭建1.1、嵌入式Linux开发1.1.1、嵌入式系统定义(1)、一般定义以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统,对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。(2)、广义定义凡是带有微处理器的专用软硬件系统都可称为嵌入式系统。1.1.2、特点
Linux系统移植
统一声明:
博客转载 声 明 : 本博客部分内容来源于网络、书籍、及各类手册。
内容宗旨为方便查询、总结备份、开源分享。
部分转载内容均有注明出处,如有侵权请联系博客告知并删除,谢谢!
百度云盘提取码:统一提取码: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
三、内核移植
3.1、linux内核
(1)、将底层硬件抽象向上提供统一的接口;
(2)、文件系统fs:将用户数据转化成文件格式存储,向下将文件转为二进制字节流存储在硬件上;
(3)、进程线程:提升性能
(4)、MMU:虚拟内存,用户不需要关心物理内存
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
重新启动开发板查看能否正常启动
练习:
- /etc的 profile init.d inittab fstab写一下,参考roofs的etc
转载:/etc/inittab,/etc/init.d/rcS和/etc/profile分析 可参考链接:https://blog.csdn.net/Qiuoooooo/article/details/79300739 - rootfs做成ramdisk.img
转载:制作rootfs文件 ramdisk 可参考链接:http://blog.chinaunix.net/uid-24148050-id-95542.html
跳转:上一篇、ARM体系结构!
跳转:下一篇、Linux驱动开发!
更 新 中 . . .
更多推荐
所有评论(0)