历史上的今天
今天是:2024年10月11日(星期五)
2018年10月11日 | OK6410裸机片内内存中重定位代码
2018-10-11 来源:eefocus
start.S源码:
.globl _start
_start:
// 硬件相关的设置
// Peri port setup
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)
// 关看门狗
// 往WTCON(0x7E004000)写0
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
// 重定位
adr r0, _start // 伪指令,取_start的当前地址
ldr r1, =_start // _start的链接地址:在连接脚本中划分的地址
ldr r2, =bss_start //bss_start的链接地址
cmp r0, r1 //比较当前地址和链接地址是否相同,即代码是否已经在链接地址处运行
beq clean_bss //相等的话直接去清BSS段
copy_loop: //不相等重定位代码
ldr r3, [r0], #4 //把r0对应的值给r3,再把r0加4
str r3, [r1], #4 //把r3的值给r1对应的空间,再把r1加4
cmp r1, r2 //比较r1和r2,_start地址拷贝到bss_start为止,看代码段有没有拷贝完成
bne copy_loop //不相等继续循环
// 清bss段
clean_bss:
ldr r0, =bss_start // bss_start的链接地址
ldr r1, =bss_end // bss_end的链接地址
mov r2, #0
clean_loop:
str r2, [r0], #4
cmp r0, r1
bne clean_loop
// 设置栈
ldr sp, =8*1024
ldr pc, =main //跳到链接地址处运行
//bl main //依然在原地址处运行
halt:
b halt
====================================================================
led.c源码:
void delay()
{
volatile int i = 0x10000;
while (i--);
}
volatile int i = 0;
volatile int j = 0x12345678;
volatile int k = 0;
volatile int g;
int main(void)
{
volatile unsigned long *gpmcon = (volatile unsigned long *)0x7F008820;
volatile unsigned long *gpmdat = (volatile unsigned long *)0x7F008824;
// gpm0,1,2,3设为输出引脚
*gpmcon = 0x1111;
if (k != 0)
return;
while (1)
{
*gpmdat = i;
i++;
if (i == 16)
i = 0;
delay();
}
return 0;
}
====================================================================
Makefile:
led.bin: start.o led.o
arm-linux-ld -T leds.lds -o led.elf start.o led.o
arm-linux-objcopy -O binary led.elf led.bin
arm-linux-objdump -D led.elf > led.dis
start.o : start.S
arm-linux-gcc -o start.o start.S -c
led.o : led.c
arm-linux-gcc -o led.o led.c -c
clean:
rm *.o led.elf led.bin led.dis -f
====================================================================
leds.lds:
SECTIONS
{
. = 0x1000; //链接地址在片内内存4096的位置
.text : {
start.o
* (.text)
}
.data : {
* (.data)
}
bss_start = .; // 0x1150
.bss : {
* (.bss)
}
bss_end = .;
}
====================================================================
注意:
s3c6410启动时自动拷贝nand flash前4页的内容到片内内存执行,而且拷贝时只拷每页中的前2KByte好像是为了兼容2k页的 所有copy2ddr函数中不要把所有数据全部照搬过去,只搬每页的前2k到ddr连接起来 。
下一篇:OK6410启动分析
史海拾趣
|
目前对于UPS、EPS、逆变电源等的大功率产品,开发设计者设计的蓄电池逆变电压往往很高。面对由很多蓄电池串联而成的高电压蓄电池组,设计者对蓄电池组的充电往往以市电经过变压器升压后整流或市电整流后经高频电子BOOST升压的传统方式来实现。前者 ...… 查看全部问答> |
|
【讨论】“嵌入式裸奔”、“嵌入式OS”、“OS”各适合什么场合? 如果你只能用的心: A)如果你手上是4位MCU? B)如果你手上是8位MCU? C)如果你手上是16位MCU? D)如果你手上是外设不多的32位MCU? E)如果你手上是外设丰富的32位MCU? F)如果你手上是外设极其丰富的64位MCU? 你要做什么产品: a)如果你 ...… 查看全部问答> |
|
两路CMOS摄像头同时输入到TI DM6446 的方法请教讨论 HI,大家好,想在TI DM6446平台上,同时输入两路CMOS摄像头的方法,请教下可否用以下方法实现: 硬件上,两个CMOS数据输入到一个二选一的高速转换器的输入口中,输入直接到 DM6446 的视频输入口 软件上,在RAM里面 建立两个 视频流的区域,即A区和B区,程序 ...… 查看全部问答> |
|
Bitmap bmp = new Bitmap(\"\\\\pics\\\\a.jpg\"); IntPtr hBitmap = bmp.GetHbitmap(); pictureBox1.Image = System.Drawing.Image.FromHbitmap(hBitmap); 如果不及时删除hBitmap 所指向的GDI对象,调用次数多了,内存会溢出。 msdn中的例 ...… 查看全部问答> |




