简易bootloader重定位问题

单板选择NandFlash启动,则硬件上电后,系统会自动将NandFlash中的前4K内容拷贝到STEPSTONE即4K SRAM中,然后从SRAM中的0X0地址启动。基于mini2440的简易bootloader制作方法在上一篇文章中有提到,它编译出的boot.bin只有1.96KB,小于STEPSTONE的4KB,因此我们可以考虑将bootloader从nandflash拷贝到内存这一步给省略掉。

一、编辑start.S:

.text
.global _start
_start:

/* close the watchdog */
	ldr r0, =0x53000000
	mov r1, #0
	str r1, [r0]
/* close the watchdog */
@关闭看门狗
@数据手册:WTCON 0x53000000 R/W Watchdog timer control register

/*   set the clock    */
	ldr r0, =0x4c000014
	mov r1, #0x03;            @ FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
	str r1, [r0]

	mrc	p15, 0, r1, c1, c0, 0		/* read */
	orr	r1, r1, #0xc0000000			/* set asynchronous bus mode */
	mcr	p15, 0, r1, c1, c0, 0		/* write */

	ldr r0, =0x4c000004
	ldr r1, =((0x5c<<12)|(0x01<<4)|(0x02)) @MPLL:200MHz
	str r1, [r0]
/*   set the clock    */
@设置系统时钟
@如果HDIVN不是0,CPU的总线模式应该设置成asynchronous bus mode

/* enable the ICACHE  */
	mrc p15, 0, r0, c1, c0, 0	@ read control register
	orr r0, r0, #(1<<12)
	mcr	p15, 0, r0, c1, c0, 0   @ write back
/* enable the ICACHE  */
@使能高速缓存,为系统提速,此段可不要,但程序执行速度要慢

/*   init the SDRAM   */
	ldr r0, =0x48000000   @MEM_CTL_BASE
	adr r1, config     /* sdram config address */
	add r3, r0, #(52)       @13*4
1:
	ldr r2, [r1], #4
	str r2, [r0], #4
	cmp r0, r3
	bne 1b
/*   init the SDRAM   */
@初始化SDRAM
@根据数据手册对与SDRAM有关的13个寄存器进行配置

/*      relocate      */
	ldr sp, =0x34000000
	bl nand_init

/*	mov r0, #0
	ldr r1, =_start
	ldr r2, =__bss_start
	sub r2, r2, r1

	bl copy_code_to_sdram  */
	bl clear_bss
/*      relocate      */
@把bootloader本身的代码从nandflash复制到它的链接地址去	

/*     go to main     */
	ldr lr, =halt
	ldr pc, =main
halt:
	b halt
/*     go to main     */
@跳转到main函数执行

config:
	.long 0x22011110	 @BWSCON
	.long 0x00000700	 @BANKCON0
	.long 0x00000700	 @BANKCON1
	.long 0x00000700	 @BANKCON2
	.long 0x00000700	 @BANKCON3
	.long 0x00000700	 @BANKCON4
	.long 0x00000700	 @BANKCON5
	.long 0x00018005	 @BANKCON6
	.long 0x00018005	 @BANKCON7
	.long 0x008C04F4	 @REFRESH
	.long 0x000000B1	 @BANKSIZE
	.long 0x00000030	 @MRSRB6
	.long 0x00000030	 @MRSRB7

注释掉:

/*	mov r0, #0
	ldr r1, =_start
	ldr r2, =__bss_start
	sub r2, r2, r1

	bl copy_code_to_sdram  */

二、编辑boot.lds:

SECTIONS {
    . = 0x00000000;
    .text : { *(.text) }

    . = ALIGN(4);
    .rodata : {*(.rodata*)} 

    . = ALIGN(4);
    .data : { *(.data) }

    . = ALIGN(4);
    __bss_start = .;
    .bss : { *(.bss)  *(COMMON) }
    __bss_end = .;
}

将0x33f80000改为0x00000000。

三、make之后将生成的boot.bin下载到nandflash中,可以成功引导内核。

简易bootloader重定位问题

时间: 2024-10-25 08:34:07

简易bootloader重定位问题的相关文章

mini2440之动手写简易bootloader

Bootloader 它的终极使命就是启动内核,它的主要工作:在上电之后在硬件上进行一系列的初始化,为Linux内核启动铺路.具体的就是设置看门狗.设置系统时钟.初始化SDRAM与NANDflash控制器.代码重定位等,最后将内核从nandflash上拷贝到内存中,传递参数,跳转执行. 一.创建start.S文件 .text .global _start _start: /* close the watchdog */ ldr r0, =0x53000000 mov r1, #0 str r1,

浅谈编译过程和符号表重定位问题

对于代码的编译问题千头万绪从何说起呢,首先来说一下计算机是如何处理应用程序的,实质上应用程序是通过操作系统来应用机器指令操控硬件设施完成各种任务的,就从编译的环节开始谈起吧,众所周知,程序开发人员所写的代码实际上计算机是没有办法去认识的,那么就必须通过编译将其转换为计算机可以认识的机器指令,在有操作系统根据具体指令从硬件上分配内存处理程序段.以下从预编译,编译,汇编,链接,来简单的说一下程序的编译过程. 2.1编译预处理 在这个阶段主要是宏定义的展开,以及头文件的递归处理,即展开所有的以#开头的

简易bootloader的LCD白屏问题(mini2440)

上次的简易bootloader虽然下载验证成功,可以成功引导内核启动linux,但是LCD一直处于白屏状态,没有显示.而mini2440的vivi就没有这情况,所以问题可能出在一些与LCD有关的初始化上.经过查看原理图和对照源代码,做了一些修改,最后LCD可以正常工作. 修改工作主要就是将对应LCD控制线和数据线的GPIO口进行初始化: 主要代码如下: void port_init(void) { GPACON = 0x7fffff; GPBCON = 0x044555; GPBUP = 0x7

S5PV210开发系列三_简易Bootloader的实现

S5PV210开发系列三 简易Bootloader的实现 象棋小子          1048272975 Bootloader是嵌入式系统上电后第一段执行的代码.对于功能简单的处理器,可能并没有Bootloader的概念,但对于应用处理器,有不同的启动方式,不同的存储设备(Nand flash.sd/mmc.DDR2.SRAM等),不同的操作系统等,往往需要一个Bootloader先初始化CPU和相关的硬件,建立内存空间映射,把内核或应用程序加载到相应的内存执行位置,最后调用内核或应用程序,释

ELF修复重定位问题

参考:Linux动态库原理(二)重定位https://blog.csdn.net/hudaliquan/article/details/50055523ELF文件格式(中文版)https://blog.csdn.net/yayong/article/details/178160linux二进制分析 pdf他有俩种结构体 typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; } Elf32_Rel; typedef struct { El

程序地址重定位和模块绑定

1.程序的构建 在构建程序的时候,链接器都会给程序设置一个默认的加载地址,即首选基地址,它表示该模块被映射到进程地址空间时最佳的内存地址.默认情况下,对于EXE程序而言,windows链接器会将它的首选基地址设置为0X400000(四十万),而DLL程序的首选基地址则被设置为0X10000000(1千万),然后链接器将该地址以及一些相关数据和代码的地址写入到PE文件中.首选基地址的是为了系统程序加载器设计的,作用是告诉加载器把程序优选加载到该首选基地址,然后就可以直接将其他的数据和代码加载到内存

Linux的内存管理机制

内存管理的一些基本概念: 地址 1)逻辑地址:指由程序产生的与段相关的偏移地址部分.在C语言指针中,读取指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址. 2)线性地址:段中的偏移地址(逻辑地址),加上相应段的基地址就生成了一个线性地址. 3)物理地址:放在寻址总线上的地址. 4)虚拟地址:保护模式下段和段内偏移量组成的地址,而逻辑地址就是代码段内偏移量,或称进程的逻辑地址. 内存管理主要解决以下问题: 进程的地址空间隔离: 提高内存的使用效率: 程序运行时重

32位汇编第四讲,干货分享,汇编注入的实现,以及快速定位调用API的数量(OD查看)

32位汇编第四讲,干货分享,汇编注入的实现,以及快速定位调用API的数量(OD查看) 昨天,大家可能都看了代码了,不知道昨天有没有在汇编代码的基础上,实现注入计算器. 如果没有,今天则会讲解,不过建议把昨天代码熟悉一遍(课程是紧跟着来的,请不要拉下任何一天,因为今天的知识, 可能就和昨天的知识挂钩,昨天的知识,和前天的挂钩.....,当然你如你懂汇编,不是新手,那么则可以直接往下看) 一丶远程线程注入,和汇编远程注入的区别 昨天的代码,大家可能看了(没看也没有关系,就是远程线程注入的代码,开发角

linux中的分段和分页

觉得这篇文章写分段和分页机制还是挺清晰的,在此转载一下. 前一段时间看了<深入理解Linux内核>对其中的内存管理部分花了不少时间,但是还是有很多问题不是很清楚,最近又花了一些时间复习了一下,在这里记录下自己的理解和对Linux中内存管理的一些看法和认识. 我比较喜欢搞清楚一个技术本身的发展历程,简而言之就是这个技术是怎么发展而来的,在这个技术之前存在哪些技术,这些技术有哪些特点,为什么会被目前的技术所取代,而目前的技术又解决了之前的技术所存在的哪些问题.弄清楚了这些,我们才能比较清晰的把握某