本文主要是介绍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 0xE2700000ldr r0, =WTCONldr r1, =0x0str 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, =WTCONldr r1, =0x0str 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 代码重定位思路
- 用链接脚本来确定链接地址(运行位置有关码)
- 确定运行地址(执行位置无关码、拷贝、长跳转)
4.8 代码重定位实战
/** 文件名: led.s * 作者: 朱老师* 描述: 演示重定位(在SRAM内部重定位)*/#define WTCON 0xE2700000
#define SVC_STACK 0xd0037d80.global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:// 第1步:关看门狗(向WTCON的bit5写入0即可)ldr r0, =WTCONldr r1, =0x0str r1, [r0]// 第2步:设置SVC栈ldr sp, =SVC_STACK// 第3步:开/关icachemrc p15,0,r0,c1,c0,0; // 读出cp15的c1到r0中//bic r0, r0, #(1<<12) // bit12 置0 关icacheorr r0, r0, #(1<<12) // bit12 置1 开icachemcr p15,0,r0,c1,c0,0;// 第4步:重定位// adr指令用于加载_start当前运行地址adr r0, _start // adr加载时就叫短加载 // ldr指令用于加载_start的链接地址:0xd0024000ldr 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总能等于r2bne copy_loop// 清bss段,其实就是在链接地址处把bss段全部清零
clean_bss:ldr r0, =bss_start ldr r1, =bss_endcmp 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 + 4bne clear_looprun_on_dram: // 长跳转到led_blink开始第二阶段ldr pc, =led_blink // ldr指令实现长跳转// 从这里之后就可以开始调用C程序了//bl led_blink // bl指令实现短跳转// 汇编最后的这个死循环不能丢b .
4.8 重定位总结
- 大多数代码是位置有关码
- 210的BL1执行时固定从0xD002_0010默认开始,假设某些位置有关码需要在0xd0024000运行,所以就需要用一段位置无关码来实现重定位
- 设置完重定位之后,PC指针还是在0xD002_0010地址,需要用长跳转指令来让PC在0xd002_4000的链接地址的某位置执行指令。
- 重定位思路:1.判断是否需要重定位,2.拷贝 3.判断是否需要清bss段 4.长跳转
1.5.5 SDRAM
1 什么是SDRAM
- SDRAM和DDR差不多
- SDRAM不等于SRAM,前者需要初始化,后者直接上电运行
2.SDRAM原理图
总结:
- DRAM0:内存地址范围:0x20000000~0x3FFFFFFF(512MB),对应引脚是Xm1xxxx
DRAM1: 内存地址范围:0x40000000~0x7FFFFFFF(1024MB),对应引脚是Xm2xxxx - 1.5GB,实际上210只占用了521MB(DRAM0 = DRAM1 = 256MB)
- 所以合理地址为:
DRAM0:内存地址范围:0x20000000~0x2FFFFFFF(256MB)
DRAM1: 内存地址范围:0x40000000~0x4FFFFFFF(256MB)
- 每个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步:初始化ddrbl sdram_asm_init //sdram_init.S//sdram_init.S27步初始化SDRAM..
DMC0_MEMCONTROLburst length=4,1chip,···对应值是0x00202400
DMC0_MEMCONFIG_0DRAM0通道中memory chip0的参数设置寄存器
DMC0_MEMCONFIG_1DRAM0通道中memory chip1的参数设置寄存器
DMC_DIRECTCMD
这个寄存器是个命令寄存器,我们210通过向这个寄存器写值来向DDR芯片发送命令(通过命令总线),这些命令应该都是用来配置DDR芯片工作参数。
总结:
总结:
-
三星设定:
DRAM0 = 256MB+256MB = memory chip0 + memory chip1
memory chip0:0x20000000到0x2FFFFFFF = 256MB
memory chip1:0x30000000~0x3FFFFFFF = 256MB -
210只用了chip0,chip0里面由两片128MB内存并联,只算一片
-
DMC0_MEMCONFIG_0有用,而DMC0_MEMCONFIG_1无用,所以我直接给他了默认值。
这篇关于S5PV210开发1.0.5----重定位relocate与SDRAM的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!