S5PV210开发1.0.5----重定位relocate与SDRAM

目录

1.5.1.关看门狗
1.5.2.设置栈、调用C语言
1.5.3.开iCache
1.5.4.重定位及其代码实战
1.5.5 SDRAM介绍

1.用汇编关看门狗

1.1 什么是看门狗?
watch dog timer,定时器,Soc的内部外设,看门狗可相当于闹钟,系统在闹钟响铃前必须把闹钟时间往后调,否则会响铃(不希望响铃,响铃会复位),往后调就不会响铃,系统正常工作时,具备自动将时间往后调这种能力。系统非正常,不会调时间,则响铃,看门狗把系统自动复位。

1.2 物理特性、原理图、数据手册
1.Soc内部外设
2.无原理图,外部外设才有原理图,看门狗不予外设相连接

1.3 特殊功能寄存器
在这里插入图片描述
在这里插入图片描述
显然,WTCON地址为0xE270_0000,控制它的Watchdog timer(bit 5),0代表关,1代表开
1.4 代码

#define WTCON	0xE2700000
	ldr r0, =WTCON
	ldr r1, =0x0
	str r1, [r0]

2.用汇编设置栈

2.1 C语言运行时需要
——2.1.1为什么要设置栈?
——C语言局部变量在栈存放
——2.1.2单片机、应用程序C程序为什么不需要设置?
——单片机C51有默认栈,C程序在链接时,编译器会自动设置栈

2.2 CPU模式和各种模式下的栈
复位后默认SVC模式,当前CPU刚复位(刚启动),外部的DRRAM尚未初始化,目前可用的内存只有内部的SRAM(因为它不需初始化即可使用)。因此我们只能在SRAM中找一段内存来作为SVC的栈。

2.3 查阅文档并设置栈指针至合法位置
在这里插入图片描述

设置栈(满减栈):
#define SVC_STACK	0xd0037d80
ldr sp, =SVC_STACK

2.4 栈的类型:
在这里插入图片描述

2.5 汇编调用C语言
2.5.1相关代码:

bl led.c //短跳转

makefile:
led.bin: start.o led.o //添加led.o

//C语言访问寄存器(内存地址)
unsigned int *p = (unsigned int *)0x0xE0200240;
*p = 0x11111111;
上面这两句其实可以简化为1句:*((unsigned int *)0x0xE0200240) = 0x11111111;

2.5.2 start.S

#define WTCON		0xE2700000
#define SVC_STACK	0xd0037d80

.global _start					// 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:
	// 第1步:关看门狗(向WTCON的bit5写入0即可)
	ldr r0, =WTCON
	ldr r1, =0x0
	str r1, [r0]
	
	// 第2步:设置SVC栈
	ldr sp, =SVC_STACK

	// 从这里之后就可以开始调用C程序了
	bl led_blink	// led_blink是C语言实现的一个函数
	
// 汇编最后的这个死循环不能丢
	b .

#define GPJ0CON		0xE0200240
#define GPJ0DAT		0xE0200244
void delay(void);

// 该函数要实现led闪烁效果
void led_blink(void)
{
	// led初始化,也就是把GPJ0CON中设置为输出模式
	unsigned int *p = (unsigned int *)GPJ0CON;
	unsigned int *p1 = (unsigned int *)GPJ0DAT;
	*p = 0x11111111;
	
	while (1)
	{
		// led亮
		*p1 = ((0<<3) | (0<<4) | (0<<5));
		// 延时
		delay();
		// led灭
		*p1 = ((1<<3) | (1<<4) | (1<<5));
		// 延时
		delay();
	}
}

void delay(void)
{
	volatile unsigned int i = 900000;		// volatile 让编译器不要优化,这样才能真正的减
	while (i--);							// 才能消耗时间,实现delay
}

3.开iCache

3.1 什么是cache
从容量来说:CPU < 寄存器 < cache < DDR
从速度来说:CPU > 寄存器 > cache > DDR

3.2 icache的作用
icache存放一些DDR的指令,cpu要执行时直接从icache里面取指令,不需要从DDR里面取,速度快

3.3 cache的操作
1.icache的一切动作都是自动的,不需人为干预。我们所需要做的就是打开/关闭icache。
2. 在210的iROM中BL0已经打开了icache。所以之前看到的现象都是icache打开时的现象。

3.4 用代码开关icache

mrc p15,0,r0,c1,c0,0;			// 读出cp15的c1到r0中
bic r0, r0, #(1<<12)			// bit12 置0  关icache
orr r0, r0, #(1<<12)			// bit12 置1  开icache
mcr p15,0,r0,c1,c0,0;

4.重定位及其代码实战

4.1 位置有关码与位置无关码
.S转变成的.elf,与位置(内存地址)有/无关

4.2 链接地址和运行地址
链接地址:希望程序执行的地址(指定方式为:Makefile中用-Ttext,或者链接脚本)
运行地址:程序执行时的地址(dnw中就是下载地址)

4.3 S5PV210的启动过程
三星推荐:(假设bootloader为80KB)
1.上电
2.BL0初始化
3.BL0程序执行控制BL1(16KB)加载到SRAM中
4.BL1程序执行控制BL2(80KB-16KB),加载到SRAM中
5.BL2程序执行,1.初始化DDR 2.OS加载到DDR

uboot:

1.上电
2.BL0初始化
3.BL0程序执行控制BL1(16KB)加载到SRAM中
4.BL1运行时会初始化DDR,然后将整个uboot搬运到DDR中
5.长跳转(从SRAM跳转到DDR),执行完剩下的uboot,完成启动

4.4 链接地址和运行地址的决定因素
运行地址:编译链接时是无法绝对确定运行时地址的
链接地址:1.Makefile中-Ttext xxx 2.链接脚本

4.5 程序段
先天性段名:
代码段:(.text),又叫文本段,代码段其实就是函数编译后生成的东西
数据段:(.data),数据段就是C语言中有显式初始化为非0的全局变量
bss段:(.bss),又叫ZI(zero initial)段,就是零初始化段,对应C语言中初始化为0的全局变量。
后天性段名:
段名由程序员自己定义,段的属性和特征也由程序员自己定义。

4.6 链接脚本
链接:把编译后的.o文件按照一定规则处理,生成一个.elf

SECTIONS
{
	. = 0xd0024000;
	
	.text : {
		start.o
		* (.text)
	}
    		
	.data : {
		* (.data)
	}
	
	bss_start = .; 
	.bss : {
		* (.bss)
	}
	
	bss_end  = .;	
}

4.7 代码重定位思路

  1. 用链接脚本来确定链接地址(运行位置有关码)
  2. 确定运行地址(执行位置无关码、拷贝、长跳转)

4.8 代码重定位实战

/*
 * 文件名:	led.s	
 * 作者:	朱老师
 * 描述:	演示重定位(在SRAM内部重定位)
 */

#define WTCON		0xE2700000
#define SVC_STACK	0xd0037d80

.global _start	// 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:
	// 第1步:关看门狗(向WTCON的bit5写入0即可)
	ldr r0, =WTCON
	ldr r1, =0x0
	str r1, [r0]
	
	// 第2步:设置SVC栈
	ldr sp, =SVC_STACK
	
	// 第3步:开/关icache
	mrc p15,0,r0,c1,c0,0;			// 读出cp15的c1到r0中
	//bic r0, r0, #(1<<12)			// bit12 置0  关icache
	orr r0, r0, #(1<<12)			// bit12 置1  开icache
	mcr p15,0,r0,c1,c0,0;
	
	// 第4步:重定位
	// adr指令用于加载_start当前运行地址
	adr r0, _start  		// adr加载时就叫短加载		
	// ldr指令用于加载_start的链接地址:0xd0024000
	ldr r1, =_start // ldr加载时如果目标寄存器是pc就叫长跳转,如果目标寄存器是r1等就叫长加载	
	// bss段的起始地址
	ldr r2, =bss_start	// 就是我们重定位代码的结束地址,重定位只需重定位代码段和数据段即可
	cmp r0, r1			// 比较_start的运行时地址和链接地址是否相等
	beq clean_bss		// 如果相等说明不需要重定位,所以跳过copy_loop,直接到clean_bss
						// 如果不相等说明需要重定位,那么直接执行下面的copy_loop进行重定位
						// 重定位完成后继续执行clean_bss。

// 用汇编来实现的一个while循环
copy_loop:
	ldr r3, [r0], #4    // 源
	str r3, [r1], #4	// 目的   这两句代码就完成了4个字节内容的拷贝
	cmp r1, r2			// r1和r2都是用ldr加载的,都是链接地址,所以r1不断+4总能等于r2
	bne copy_loop

	// 清bss段,其实就是在链接地址处把bss段全部清零
clean_bss:
	ldr r0, =bss_start					
	ldr r1, =bss_end
	cmp r0, r1				// 如果r0等于r1,说明bss段为空,直接下去
	beq run_on_dram			// 清除bss完之后的地址
	mov r2, #0
clear_loop:
	str r2, [r0], #4		// 先将r2中的值放入r0所指向的内存地址(r0中的值作为内存地址),
	cmp r0, r1				// 然后r0 = r0 + 4
	bne clear_loop

run_on_dram:	
	// 长跳转到led_blink开始第二阶段
	ldr pc, =led_blink				// ldr指令实现长跳转
	
	// 从这里之后就可以开始调用C程序了
	//bl led_blink					// bl指令实现短跳转
	
// 汇编最后的这个死循环不能丢
	b .
	

4.8 重定位总结

  1. 大多数代码是位置有关码
  2. 210的BL1执行时固定从0xD002_0010默认开始,假设某些位置有关码需要在0xd0024000运行,所以就需要用一段位置无关码来实现重定位
  3. 设置完重定位之后,PC指针还是在0xD002_0010地址,需要用长跳转指令来让PC在0xd002_4000的链接地址的某位置执行指令。
  4. 重定位思路:1.判断是否需要重定位,2.拷贝 3.判断是否需要清bss段 4.长跳转

1.5.5 SDRAM

1 什么是SDRAM

  1. SDRAM和DDR差不多
  2. SDRAM不等于SRAM,前者需要初始化,后者直接上电运行

在这里插入图片描述
2.SDRAM原理图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结:

  1. DRAM0:内存地址范围:0x20000000~0x3FFFFFFF(512MB),对应引脚是Xm1xxxx
    DRAM1: 内存地址范围:0x40000000~0x7FFFFFFF(1024MB),对应引脚是Xm2xxxx
  2. 1.5GB,实际上210只占用了521MB(DRAM0 = DRAM1 = 256MB)
  3. 所以合理地址为:
    DRAM0:内存地址范围:0x20000000~0x2FFFFFFF(256MB)
    DRAM1: 内存地址范围:0x40000000~0x4FFFFFFF(256MB)
    在这里插入图片描述
  4. 每个DDR连接着
    1.地址总线14根
    2.数据总线16根(两片拼接就是32位)
    3 控制线

5.一片DDR有128MB

1片内存8bank
1bank里面有row address(14位) + column address(10位)
1bank = 2^14*2^10 = 2 ^24 = 16MB= 128Mb
8bank(128Mbit * 8)合在一起就是1片内存(128MB)

6.汇编初始化SDRAM

	// 第4步:初始化ddr
	bl sdram_asm_init //sdram_init.S
	
 //sdram_init.S
 27步初始化SDRAM
 .
 .
DMC0_MEMCONTROL
	burst length=41chip,···对应值是0x00202400
DMC0_MEMCONFIG_0
	DRAM0通道中memory chip0的参数设置寄存器
DMC0_MEMCONFIG_1
	DRAM0通道中memory chip1的参数设置寄存器
DMC_DIRECTCMD
这个寄存器是个命令寄存器,我们210通过向这个寄存器写值来向DDR芯片发送命令(通过命令总线),这些命令应该都是用来配置DDR芯片工作参数。

总结:

总结:

  1. 三星设定:
    DRAM0 = 256MB+256MB = memory chip0 + memory chip1
    memory chip0:0x20000000到0x2FFFFFFF = 256MB
    memory chip1:0x30000000~0x3FFFFFFF = 256MB

  2. 210只用了chip0,chip0里面由两片128MB内存并联,只算一片

  3. DMC0_MEMCONFIG_0有用,而DMC0_MEMCONFIG_1无用,所以我直接给他了默认值。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值