at91sam9g25处理器uboot移植 个人笔记一

1 生成补丁 与 打补丁

生成补丁 diff -upNr old/ new/ > patch-x.y.z

diff -upNr u-boot-2014.07/ u-boot-2014.07_moveto9g25/ > moveto9g25-2015.08.25-ok.patch

打补丁   cd old

patch -p1 < ../patch-x.y.z

----------------------------------------------------------------------------------------------

2 修改boards.cfg 与 Makefile

Status, Arch, CPU:SPLCPU, SoC, Vendor, Board name,    Target,        Options, Maintainers

Active  arm   arm926ejs  at91  atmel   at91sam9g25jzq at91sam9g25jzq_nandflash

at91sam9g25jzq:AT91SAM9G25,SYS_USE_NANDFLASH    Zhaigch <[email protected]>

修改Makefile,指定CROSS_COMPILE = arm-linux-

拷贝board/atmel/at91sam9x5ek 为 at91sam9g25jzq对应配置文件里的Board name

拷贝include/configs/at91sam9x5ek.h 为 at91sam9g25jzq.h

生成配置头文件 make <Target>_config

make at91sam9g20ek_nandflash_config

make at91sam9g25jzq_nandflash_config

make

make u-boot.dis //生成反汇编文件

----------------------------------------------------------------------------------------------

3 搜索字符串命令

grep -nR "xx" ./

使用4.3.2交叉编译器编译时出错 armv5te指令集不兼容,使用arm-none-gnueabi-4.7.3编译顺利通过。

修改 configs/at91sam9g25jzq.h 里的宏定义为“CONFIG_SYS_TEXT_BASE
0x22000000”

使程序编译后的运行地址为22000000开始,将nand中拷贝出的程序放到该地址后,直接跳转执行。

发现源码做的太好了,直接就跑起来了!

----------------------------------------------------------------------------------------------

4 启动分析一

arch/arm/lib/vectors.S    //中断向量表,跳转到 reset,即:

arch/arm/cpu/arm926ejs/start.S //这里如果没有分两级引导的话,这里需要进行一些必要的初始化操作

//如关闭内部看门狗,初始化系统时钟,初始化ddr2内存,从nand中拷贝程序到内存中等操作。

//由于我们是二级启动uboot,以上这些已经被1级引导程序完成,因此 通过宏CONFIG_SKIP_LOWLEVEL_INIT

//直接跳过这些过程直接调用 _main

arch/arm/lib/crt0.S  // _main在该文件中定义

//初始化sp为 CONFIG_SYS_INIT_SP_ADDR = 0x20000000 + 4096 - GENERATED_GBL_DATA_SIZE

//sub sp, sp, #GD_SIZE   ,接着在sp上方又分配出 GD_SIZE大小的内存

//mov r9, sp,此时r9保存的就是GD_SIZE大小的内存的起始地址,也可以认为是某个全局变量结构体的指针

//调用 board_init_f,根据配置头文件中的宏 CONFIG_SYS_GENERIC_BOARD,common/board_f.c被编译

#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9")

common/board_f.c  //如果没有该宏,arm/lib/board.c会被编译,该文件以后会被踢出源码,尽量不要链接它

bl board_init_f //板初始化,完成什么操作呢?

----------------------------------------------------------------------------------------------

5 启动分析二

board_init_f

gd = &data; // gd全局数据指针指向在堆栈里定义的结构体,这里不使用上一步在堆栈外分配的内存

// 为什么?以后再分析

initcall_run_list(init_sequence_f) //调用init_sequence_f数组中的全部函数

setup_mon_len,     //填充 gd->mon_len 程序长度

setup_fdt,         //填充 gd->fdt_blob = 0

trace_early_init,  //空

arch_cpu_init,     //调用at91_clock_init,填充gd->arch 时钟相关数据

mark_bootstage,    //"board_init_f"字符串放入record[]数组记录表中

timer_init,        //初始化pit,填充gd->arch.timer_rate_hz gd->arch.tbu = gd->arch.tbl = 0

env_init,          //根据配置文件中宏 CONFIG_ENV_IS_IN_NAND, env_nand.c被编译连接

//env_init被调用,填充gd->env_addr环境变量存放地址

//填充gd->env_valid环境变量有效标识

init_baud_rate,
  //填充gd->baudrate

serial_init,
/* serial communications setup */

console_init_f,    //填充gd->have_console = 1,初始化print缓冲,从此可以使用printf打印功能

display_options,   //console中打印 uboot版本信息与编译日期

display_text_info,
/* show debugging info if required */

print_cpuinfo,     //打印处理器型号,主时钟,系统时钟,外设时钟

announce_dram_init,//puts("DRAM:  ");

dram_init,         //填充gd->ram_size = 0x4000000

setup_dest_addr,   //填充gd->relocaddr = gd->ram_top = 0x24000000

reserve_round_4k,  //4k对齐gd->relocaddr &= ~(4096 - 1);

reserve_trace,     //null

reserve_uboot,     //gd->relocaddr -= gd->mon_len;留出uboot的代码空间

//gd->relocaddr &= ~(4096 - 1);4K对齐

//gd->start_addr_sp = gd->relocaddr;堆栈空间

setup_machine,     //gd->bd->bi_arch_number = CONFIG_MACH_TYPE 设置板号

reserve_global_data,//gd->start_addr_sp -= sizeof(gd_t);堆栈下移,分配空间gd_t

//gd->new_gd = gd->start_addr_sp 指向新分配的内存地址

reserve_fdt,       //gd->start_addr_sp -= gd->fdt_size; 为fdt分配内存空间

//gd->new_fdt = gd->start_addr_sp 指向新分配的fdt内存空间

reserve_stacks,    //2字节对齐,为IRQ中断分配内存

setup_dram_config, //null

show_dram_config,  //打印出dram的大小

display_new_sp,    //调试时打印 gd->start_addr_sp

reloc_fdt,         //重定位fdt,进行数据拷贝

setup_reloc,       //gd->reloc_off = gd->relocaddr - 0x22000000;

//memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); 将gd内的数据拷贝到新的地址

----------------------------------------------------------------------------------------------

6 启动分析三

在调用board_init_f()完成板卡与全局结构体变量 gd 的初始化后将其拷贝到在代码段下重新分配的全局结构

体中。接下来进行sp的重新设置,将r9指向重新分配的全局变量gd,然后进行代码的重定位。

ldr sp, [r9, #GD_START_ADDR_SP]
/* sp = gd->start_addr_sp */

bic sp, sp, #7
/* 8-byte alignment for ABI compliance */

ldr r9, [r9, #GD_BD]
/* r9 = gd->bd */

sub r9, r9, #GD_SIZE

修改代码返回值,使其值为重定位后的地址

adr lr, here

ldr r0, [r9, #GD_RELOC_OFF]
/* r0 = gd->reloc_off */

add lr, lr, r0

ldr r0, [r9, #GD_RELOCADDR]
/* r0 = gd->relocaddr */

拷贝代码到重定位的地址空间去

b relocate_code

arch/arm/lib/relocate.S

将链接脚本中代码段从 __image_copy_start 到 __image_copy_end之间的 代码段、数据段和命令行段

拷贝到重定位的地址 gd->relocaddr 处

拷贝完成后,还需要将从 __rel_dyn_start到 __rel_dyn_end之间的 .rel.dyn段(代码重定位时使用,默认应该

是由编译器产生的相关寻址相关的数据)

完成代码的重定义后,返回到重定位后的代码中

bl c_runtime_cpu_setup //arch/arm/cpu/arm926ejs/start.S 无其它需要初始化的操作,直接返回

接下来初始化bss段

接下来调用board_init_r函数

mov r0, r9 //将重定位后新的gd指针作为参数0传入函数

ldr r1, [r9, #GD_RELOCADDR] //重定位后代码段的起始地址作为参数1传入函数

ldr pc, =board_init_r //绝对地址跳转,由于代码重定位后,同时根据重定位后相对于之前程序的偏移值

对程序的运行地址进行了修正,从而保证重定位后,通过绝对地址跳转时的正确运行。

----------------------------------------------------------------------------------------------

7 启动分析四

board_init_r

initcall_run_list(init_sequence_r) //循环调用结构体 init_sequence_r 中的全部函数

initr_caches //打开处理器的数据和指令cache,需要自己添加

board_init //与具体的板卡相关的外设的初始化,以及gd->bd相关的元素进行初始设置,需要移植修改

initr_serial //再次初始化串口

initr_malloc //初始化分配的堆空间内存,

bootstage_relocate //启动阶段重定位,干嘛的 未知

power_init_board //空,如果需要自定义相关操作

initr_flash // nor flash的初始化,如果板上没有Nor flash需要配置宏 CONFIG_SYS_NO_FLASH

initr_nand //nand flash的初始化,需要配置宏 CONFIG_CMD_NAND

initr_env //初始化环境变量

set_default_env() //如果从flash中没有读到环境变量则使用默认的的环境变量default_environment

"bootargs=" CONFIG_BOOTARGS "\0"

"bootcmd=" CONFIG_BOOTCOMMAND "\0"

"nfsboot=" CONFIG_NFSBOOTCOMMAND
"\0"

"bootdelay=" __stringify(CONFIG_BOOTDELAY)
"\0"

"baudrate=" __stringify(CONFIG_BAUDRATE)
"\0"

"ethaddr=" __stringify(CONFIG_ETHADDR)
"\0"

"ipaddr=" __stringify(CONFIG_IPADDR)
"\0"

"serverip=" __stringify(CONFIG_SERVERIP)
"\0"

"gatewayip=" __stringify(CONFIG_GATEWAYIP)
"\0"

"netmask=" __stringify(CONFIG_NETMASK)
"\0"

initr_secondary_cpu //空,__weak标记的虚弱函数,如果编译的程序里有相同函数名的函数则用它代替自己

stdio_init //标准输入输出初始化

initr_jumptable //初始化跳转表,干嘛的 未知

console_init_r //控制命令行相关的初始化操作,不需要移植,不用关心它。

interrupt_init //中断初始化,不关心中断,能引导linux内核就行了,

initr_ethaddr  //初始化网卡地址,需要配置宏 CONFIG_CMD_NET

initr_net      //初始化网卡,需要配置宏 CONFIG_CMD_NET

run_main_loop  //主循环,死循环中运行main_loop,去解析用户输入的命令行,或系统自动运行的命令

main_loop

----------------------------------------------------------------------------------------------

8 启动分析五

由于在9g25处理器的引导过程中,在uboot之前有一个初始的引导程序,该程序完成了 中断向量表的初始化

fiq irq的中断场景记录和sp的设置,ddr内存初始化,系统时钟工作在399Mhz,外设时钟工作在133Mhz,调试

串口bps为115200,然后将nand的0x40000开始的0x80000(512k)长的数据拷贝到ddr内存0x23000000处,然后

通过ldr pc,=0x23000000 绝对地址跳转到23000000地址运行拷贝到些处的uboot程序.

由于在uboot中会执行一些关于协处理的操作(MMU、Icache、Dcache)指令MRC(读协处理器),MCR(写协处理器),

这两条指令必须在特权模式下执行,因此在跳转到uboot前先让处理器工作在svc管理模式,否则在执行到这

样的命令时会触发 未定义 指令的中断。

打补丁测试

tar xjf u-boot-2014.07.tar.bz2

cd u-boot-2014.07/

patch -p1 < ../moveto9g25-2015.08.25-ok.patch

make at91sam9g25jzq_nandflash_config

make

make u-boot.dis

nfs 22000000 192.168.0.1:/home/terminal/workspace/nfs/image/uImage_1

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-11 21:36:13

at91sam9g25处理器uboot移植 个人笔记一的相关文章

I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之u-boot移植

前段时间就开始学习I.MX6Q了,但是最近工作实在是忙,间断了一些时间了.为了提高移植效率,还是考虑移植Freescale维护的3.10版本的内核. 源码获取 Freescale维护的3.10的内核是使用git管理的,但是直接使用git下载代码会比较慢,下面是我下载好的uboot和kernel: I.MX6Q BSP源码(Freescale官方维护) 代码下载好后,先将u-boot解压到工作目录,然后在终端下切换到uboot根目录.由于这个版本的bsp是使用git管理的,因此,需要切换到指定分支

uboot移植总结

1.uboot的介绍及体系结构 1.1 uboot的介绍 Uboot是德国DENX小组的开发用于多种嵌入式CPU的bootloader程序, UBoot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系统.UBoot除了支持PowerPC系列的处理器外,还能支持MIPS. x86.ARM.NIOS.XScale等诸多常用系列的处理器. 1.2 uboot的体系结构 目录树 |--board |--c

uboot移植——uboot源码目录分析

uboot移植(一)--uboot源码目录分析 本文分析的uboot是九鼎官方提供的,是对应s5pv210开发板x210bv3的uboot 一:uboot的概念及移植的原理. uboot就是在内核运行前的一段小程序,用来初始化硬件设备,建立内存空间映射图.从而将系统的软硬件带到合适的状态,主要功能就是为了启动内核,它将内核从flash中拷贝到ddr中,然后跳转到内核入口中,交由内核控制权,uboot严重依赖硬件,因此一个通用的uboot不太可能. 移植原理:uboot中有很多平行代码,各自属于各

PowerPC平台 u-boot 移植

PowerPC功能很强的通信处理器,支持1000M以太网接口,以Freescale的P1010处理器为开发平台,讲述移植linux的整个过程,与大家分享. 1.配置交叉编译链 网上下载交叉编译工具,配置环境变量 sudo gedit /etc/environment 在末尾添加交叉编译链路径 :/home/freescale/work/tools/freescale/bin log out(不需要重启),输入如下,验证交叉编译是否安装成功: [email protected]:~/work/u-

uboot移植之前的工作

1.1计算机系统的主要部件:计算机系统是有cpu来做核心进行运行的系统.典型的计算机系统有:pc机,嵌入式设备(手机.平板电脑.游戏机),单片机(家用电器). 1.2计算机系统组件部件非常多,不同的计算机系统组成部件也不同.但是所有的计算机系统运行时需要的主要核心部件都是3个东西:cpu+外部存储器(Flash/硬盘) + 内部存储器(DDR SDRAM/SDRAM/SRAM). 1.3pc机的启动过程:(1)典型的pc部署:BIOS程序部署在pc机主板上(随主板出厂时已经预制了),操作系统部署

嵌入式linux开发uboot移植(三)——uboot启动过程源码分析

嵌入式linux开发uboot移植(三)--uboot启动过程源码分析 一.uboot启动流程简介 与大多数BootLoader一样,uboot的启动过程分为BL1和BL2两个阶段.BL1阶段通常是开发板的配置等设备初始化代码,需要依赖依赖于SoC体系结构,通常用汇编语言来实现:BL2阶段主要是对外部设备如网卡.Flash等的初始化以及uboot命令集等的自身实现,通常用C语言来实现. 1.BL1阶段 uboot的BL1阶段代码通常放在start.s文件中,用汇编语言实现,其主要代码功能如下:

嵌入式linux开发uboot移植(二)——uboot工程源码目录分析

嵌入式linux开发uboot移植(二)--uboot工程源码目录分析 本文分析的uboot为uboot_smdkv210,是三星官方发布的基于S5PV210评估开发板对应的uboot. 一.uboot源码目录结构解析 1.cpu 本文件夹下的子文件与处理器相关,每个文件夹代表一种CPU系列.每个子目录中都包括cpu.c.interrupts.c.start.S文件. cpu.c主要用于初始化CPU.设置指令Cache和数据Cache等 interrupt.c主要用于设置系统的各种中断和异常 s

嵌入式linux开发uboot移植(一)——uboot项目简介

嵌入式linux开发uboot移植(一)--uboot项目简介 一.uboot简介 U-Boot,全称 Universal Boot Loader,是遵循GPL条款的从FADSROM.8xxROM.PPCBOOT逐步发展演化而来的开放源码项目. 在操作系统方面,U-Boot不仅支持嵌入式Linux系统的引导,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS, android嵌入式操作系统.目前支持的目标操作系统是OpenBSD, NetBSD, Fre

U-Boot移植之前期分析(上)

老是看别人移植uboot,用别人移植好的uboot,今天终于下定决心自己移植一个uboot来玩玩,好歹我也是个软件开发人员啊. 第一步:去ftp://ftp.denx.de/pub/u-boot/网站下载个uboot工程源码,为了防止环境出问题,我决定用个老一点的,于是就下了:u-boot-1.1.6.tar.bz2. 第二步:解压源码:tar  jxvf  u-boot-1.1.6.tar.bz2. 第三步:建立source insight工程 好了完成以上三步之后,我们需要的前提条件都准备好