1.点灯测试(OK6410):#define GPMCON (*(volatile unsigned long*)0x7F008820)
#define GPMDAT (*(volatile unsigned long*)0x7F008824)
#define GPM0_CON (1<<0) //rGPBCON[0:3]对应第GPM0
#define GPM1_CON (1<<4) //rGPBCON[4:7]对应第GPM1
#define GPM2_CON (1<<8) //rGPBCON[8:11]对应第GPM2
#define GPM3_CON (1<<12) //rGPBCON[12:15]对应第GPM3
void led_init()
{
GPMCON &= ~(0xFFFF);
GPMCON |= GPM0_CON | GPM1_CON | GPM2_CON | GPM3_CON;
}
void delay(int counter)
{
int i;
for (; counter > 0; counter--)
for (i = 0; i < 100; i++)
;
}
void led_display(int n)
{
n &= 0xf;
GPMDAT &= ~0xf;
GPMDAT |= (~n);
}
void main()
{
int i = 0;
led_init();
while(1)
{
for (;;) {
delay(5000);
led_display(i);
if (++i == 16)
i = 0;
}
}
}
该点灯可以在裸机环境下使用,使用如下:
reset:
mrs r0,cpsr @复制cpsr到寄存器r0中
bic r0,r0,#0x1f @清除r0中的0~4位
orr r0,r0,#0xd3 @r0位或0xd3 放到r0中
msr cpsr,r0 @复制r0到cpsr
bl set_peri_port
ldr sp,=8*1024
bl disable_watchdog
bl led_init
bl init_clock
mov r0 ,#1
bl led_display
bl init_sdram
mov r0 ,#2
bl led_display
bl init_uart
mov r0 ,#3
bl led_display
bl creat_page_table
mov r0 ,#4
bl led_display
bl init_stack
mov r0 ,#5
bl led_display
bl enable_system_IRQ
bl check_position
bl copy_to_sdram
bl clean_bss
ldr pc, =on_sdram
可以根据led灯的点亮情况(1,2,3,4,5,)一次性诊断错误的位置,方便实用;注意不要再bl跳转的函数内部使用,因为会修改lr指针导致不能跳回来。
2.保存lr的值,lr寄存器用于存放bl跳转的返回地址:
str lr, [sp, #-4]! @保存lr的值用于跳回
bl xxxxxxxxxxxx @将nand代码拷贝到内存
ldr lr, [sp], #4 @load lr的值
mov pc, lr
3.中断设置堆栈:
init_stack:
mrs r0, cpsr @转换到中断模式
bic r0, r0, #0x1f
orr r0, r0, #0x12
msr cpsr, r0 @复制r0到cpsr
ldr sp, =0x56000000 @设置IRQ模式下的堆栈
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0x53
msr cpsr, r0
ldr sp, =0x57000000 @设置SVC模式下的堆栈
mov pc, lr