本帖最后由 lr2131 于 2014-4-18 15:09 编辑
最近有些小空闲,想学学bootloader,在MDK + JLINK + S3C2440这样的配置下,我写了些简单的代码,出了些问题,实在不知道怎么进行下去。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;startup.s 汇编启动代码;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SVC_STACK_LEGTH EQU 0
FIQ_STACK_LEGTH EQU 0
IRQ_STACK_LEGTH EQU 256
ABT_STACK_LEGTH EQU 0
UND_STACK_LEGTH EQU 0
NoInt EQU 0x80
NoFIQ EQU 0x40
USR32Mode EQU 0x10
SVC32Mode EQU 0x13
SYS32Mode EQU 0x1f
IRQ32Mode EQU 0x12
FIQ32Mode EQU 0x11
; IMPORT __use_no_semihosting_swi
; IMPORT FIQ_Exception
; IMPORT __main
IMPORT SystemInit
IMPORT LowLevelInit
EXPORT bottom_of_heap
EXPORT StackUsr
EXPORT Reset
EXPORT __user_initial_stackheap
PRESERVE8
;CODE32
AREA os,CODE,READONLY
ARM
; ENTRY
Reset
LDR PC, ResetAddr
LDR PC, UndefinedAddr
LDR PC, SWI_Addr
LDR PC, PrefetchAddr
LDR PC, DataAbortAddr
DCD 0xb9205f80
LDR PC, [PC, #-0xff0]
LDR PC, FIQ_Addr
ResetAddr DCD ResetInit
UndefinedAddr DCD Undefined
SWI_Addr DCD SoftwareInterrupt
PrefetchAddr DCD PrefetchAbort
DataAbortAddr DCD DataAbort
Nouse DCD 0
IRQ_Addr DCD 0
FIQ_Addr DCD FIQ_Handler
Undefined
B Undefined
SoftwareInterrupt
CMP R0, #4
LDRLO PC, [PC, R0, LSL #2]
MOVS PC, LR
SwiFunction
DCD IRQDisable ;0
DCD IRQEnable ;1
DCD FIQDisable ;2
DCD FIQEnable ;3
IRQDisable
MRS R0, SPSR
ORR R0, R0, #NoInt
MSR SPSR_c, R0
MOVS PC, LR
IRQEnable
MRS R0, SPSR
BIC R0, R0, #NoInt
MSR SPSR_c, R0
MOVS PC, LR
FIQDisable
MRS R0, SPSR
ORR R0, R0, #NoFIQ
MSR SPSR_c, R0
MOVS PC, LR
FIQEnable
MRS R0, SPSR
BIC R0, R0, #NoFIQ
MSR SPSR_c, R0
MOVS PC, LR
PrefetchAbort
B PrefetchAbort
DataAbort
B DataAbort
FIQ_Handler
STMFD SP!, {R0-R3, LR}
; BL FIQ_Exception ;先简单的注释掉这个,不管了,以后再搞
LDMFD SP!, {R0-R3, LR}
SUBS PC, LR, #4
InitStack
MOV R0, LR
MSR CPSR_c, #0xd3
LDR SP, StackSvc
MSR CPSR_c, #0xd2
LDR SP, StackIrq
MSR CPSR_c, #0xd1
LDR SP, StackFiq
MSR CPSR_c, #0xd7
LDR SP, StackAbt
MSR CPSR_c, #0xdb
LDR SP, StackUnd
MSR CPSR_c, #0xdf
LDR SP, =StackUsr-512
MOV PC, R0 ;BX R0; 不能使用LR返回,LR可能已经被修改了,所以借由R0中保存的LR原值返回
ResetInit
BL LowLevelInit
BL InitStack ;在这之后,堆栈指针已初始化,可以调用C函数
STMFD SP!, {R0-R3, LR}
BL SystemInit
LDMFD SP!, {R0-R3, LR}
B .
; BL TargetResetInit
; B __main
__user_initial_stackheap
LDR r0,=bottom_of_heap
; LDR r1,=StackUsr
MOV pc,lr ; BX LR;
StackSvc DCD SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4
StackIrq DCD IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4
StackFiq DCD FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4
StackAbt DCD AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4
StackUnd DCD UndtStackSpace + (UND_STACK_LEGTH - 1)* 4
AREA MyStacks, DATA, NOINIT, ALIGN=2
SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;Stack spaces for Administration Mode 管理模式堆栈空间
IrqStackSpace SPACE IRQ_STACK_LEGTH * 4 ;Stack spaces for Interrupt ReQuest Mode 中断模式堆栈空间
FiqStackSpace SPACE FIQ_STACK_LEGTH * 4 ;Stack spaces for Fast Interrupt reQuest Mode 快速中断模式堆栈空间
AbtStackSpace SPACE ABT_STACK_LEGTH * 4 ;Stack spaces for Suspend Mode 中止义模式堆栈空间
UndtStackSpace SPACE UND_STACK_LEGTH * 4 ;Stack spaces for Undefined Mode 未定义模式堆栈
AREA Heap, DATA, NOINIT
bottom_of_heap SPACE 1
AREA Stacks, DATA, NOINIT
StackUsr
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;LowLevelInit.s 底层初始化,在初始化各模式堆栈指针前调用;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INTMSK EQU 0x4A000008
INTSUBMSK EQU 0X4A00001C
WTCON EQU 0x53000000
EXPORT LowLevelInit
AREA init,CODE,READONLY
LowLevelInit
;1.关闭全部中断
MOV R0,#0
LDR R1,=INTMSK
LDR R2,=INTSUBMSK
STR R0,[R1]
STR R0,[R2]
;2.关闭看门狗
LDR R1,=WTCON
STR R0,[R1]
;3.关闭MMU
;4.关闭I-Cache
;5.关闭D-Cache
MOV PC, LR ;BX R0;
END
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////SystemInit.c 在初始化完各模式堆栈之后,在bl __main之前,初始化某些部件///////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "SystemInit.h"
extern void SystemInit(void)
{
// 1.初始化时钟,建议第一次初始化在加载运行域之前做,这样速度会快一些
ClockInit();
// 2.关闭一些不用的外设时钟源,如果可以关闭不用外设的供电就也关闭。只需要在模块初始化中自己开启。
// PowerOffPeripherals();
// 3.初始化中断系统,目前暂时不实现
LedInit();//希望通过眼观Led在不同MPLL频率设置下运行时的闪烁频率差异来初步验证MPLL设置的正确
#if 1
while(1){
Delay(10);
LedOn();
Delay(10);
LedOff();
}
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////clock.c ///////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "clock.h"
extern void ClockInit(void)
{
#if 0 // 本来是想验证系统时钟设置的,结果发现代码直接跑出问题了,就先把时钟初始化这段屏蔽掉,缩小和排查问题的范围
unsigned long temp;
S3C_CLOCK -> LOCKTIME = 0xFFFFFFFF;
S3C_CLOCK -> MPLLCON = MPLLCON_VAULE;
S3C_CLOCK -> UPLLCON = S3C_CLOCK -> UPLLCON;
S3C_CLOCK -> CLKCON = 0;// 关闭全部外设
temp = S3C_CLOCK -> CLKSLOW;
temp &= (~(3<<4));
temp |= (1<<7);
S3C_CLOCK -> CLKSLOW = temp;
S3C_CLOCK -> CLKDIVN = 0x02;
// S3C_CLOCK -> CAMDIVN = 0x00;
// Delay(10);
// temp = temp;
return ;
#else
unsigned long test = 2;
// test = S3C_CLOCK->LOCKTIME;// test = _LOCKTIME;
// S3C_CLOCK -> LOCKTIME = 0;//_LOCKTIME = 0;
// test = test;
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////s3c2440.c ///////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "s3c2440.h"
extern void Delay(int t)
{
volatile int i,j,k;
for(k = 0; k < t; k ++){
for(i = 0; i < 0x100; i ++){
for(j = 0; j < 0x100; j ++);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////gpio.c ///////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "gpio.h"
// LED0 - GPB5
// LED1 - GPB6
// LED2 - GPB8
// LED3 - GPB10
extern void LedInit(void)
{
unsigned long temp;
S3C_CLOCK -> CLKCON = (1<<13);// 开启gpio时钟
temp = S3C_GPIO -> GPBCON;
temp &= (~( (3<<10) | (3<<12) | (3<<16) | (3<<20) ));
temp |= ( (1<<10) | (1<<12) | (1<<16) | (1<<20) );
S3C_GPIO -> GPBCON = temp;
S3C_GPIO -> GPBDAT &= (~( (1<<5) | (1<<6) | (1<<8) | (1<<10) ));
S3C_GPIO -> GPBDAT |= ( (1<<5) | (1<<6) | (1<<8) | (1<<10) );
// S3C_GPIO -> GPBUP
}
extern void LedOn(void)
{
S3C_GPIO -> GPBDAT &= (~( (1<<5) | (1<<6) | (1<<8) | (1<<10) ));
}
extern void LedOff(void)
{
S3C_GPIO -> GPBDAT |= ( (1<<5) | (1<<6) | (1<<8) | (1<<10) );
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;分散加载脚本;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ROM_LOAD 0x40000000
{
ROM_EXEC 0x40000000
{
startup.o (os, +First)
*(InRoot$$Sections)
* (+RO)
}
IRAM 0x40000800
{
startup.o (MyStacks)
.ANY (+RW,+ZI) ; * (+RO)
}
HEAP +0 UNINIT
{
startup.o (Heap)
}
STACKS 0x40001000 UNINIT
{
startup.o (Stacks)
}
}
初始化脚本:我去掉了时钟和SDRAM的初始化,只是需要系统在调试仿真时能跳转到0x40000000.
FUNC void SetupForStart (void) {
// <o> Program Entry Point
PC = 0x40000000;//0x30000000
}
FUNC void Init (void) {
}
// Reset chip with watchdog, because nRST line is routed on hardware in a way
// that it can not be pulled low with ULINK
_WDWORD(0x40000000, 0xEAFFFFFE); // Load RAM addr 0 with branch to itself
CPSR = 0x000000D3; // Disable interrupts
PC = 0x40000000; //0x30000000 // Position PC to start of RAM
_WDWORD(0x53000000, 0x00000021); // Enable Watchdog
g, 0 // Wait for Watchdog to reset chip
Init(); // Initialize memory
LOAD FL2440.axf INCREMENTAL // Download program
SetupForStart(); // Setup for Running
//g, main
编译通过,没有错误,警告也是写无关紧要。
调试仿真环境我对着看汇编代码。
BL LowLevelInit
BL InitStack
这些都是没问题的,但是在BL SystemInit后,紧接着就 BL ClockInit。
这就有问题了,BL SystemInit,会把这条指令的下一条地址保存到LR中,当然我这里是B .,而且程序在SystemInit中需要死循环,按功能来说,不保存BL SystemInit下一条指令是可以的,
但按照ATPCS的规则,编译器是需要在进到SystemInit函数后需要保存一些必要的寄存器值到栈中。而且接下来我看到程序确实是没有按照应有的顺序来执行,跑飞了。
代码量不多,倒腾了很久,也没发现运行正常,有一次倒是发现编译器编译代码,在 BL SystemInit后有保存LR,但还是会跑飞。另外,多数情况下编译器编译代码没有保存LR的指令,
我也不知道该怎么搞了,只知道编译器编译C代码成汇编的代码有问题,如果是设置的问题,我也都试着调了下,在ADS1.2下也试过,也会跑飞。代码的问题的话,我按ATPCS规则来写
也只是在函数调用的第一层做啊,到SystemInit函数里面,就是编译器的事,出了问题,该怎么解决呢?
|