这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» MCU» 关于ADS的 RO Base ,RW Base 设置问题和bootloader程

共4条 1/1 1 跳转至

关于ADS的 RO Base ,RW Base 设置问题和bootloader程序链接问题

菜鸟
2006-02-23 05:55:08 打赏

最近,在写一个支持usb通信的bootloader,我的系统是这样的:

CPU ->S3C2410A,(内部集成4KB的SRAM,以支持Nand Flash的启动)

FLASH ==〉64M的Nand Flash

SDRAM ==〉64M

我的程序基于三星的S3C2410X USB downloader的 ,因为三星的程序是 针对NOR FLASH,而我们系统的非易失存储器是NAND FLASH,所以我需要改动它以支持我们的系统。

程序的开发环境是ADS1.2;我的系统的启动代码大概有30KB,从Flash的0x0开始存放。程序的流程是这样的:系统加电后,NAND Flash 的前4KB程序会自动地流入SRAM中,自动执行,在SRAM中的程序在完成CPU模式,中断,时钟频率,电源,存储器和堆栈等的初始化后,把启动代码拷贝一份到SDRAM中,然后程序跳转到SDRAM中接着执行后面的代码。

程序的编译链接我采用U-boot的思路,使起始代码地址无关,然后用一条"ldr pc,main"指令,使程序转移到main函数的编译地址。我的想法是要让程序从地址0x33f00000开始编译,因此我在ADS中设置RO Base=0x33f000000,没有设置RW Base。在用AXD调试程序时,程序从0x33f00000开始运行,很正常,也能够直接跳入到C代码部分的main函数执行。当我把启动代码直接烧入到NAND FLASH 后,问题出现了:当我的代码量小于4KB时,也就是说程序还在SRAM里执行时一切正常,而当代码量大于4KB时,程序立马就死掉(通过点灯发现,第一句代码都没执行),也就是说程序从SRAM跳往SDRAM里执行时没有成功。

起初我认为是SDRAM 初始化的问题,但我往内存里写数据再读出,数据正确。反复调试,觉得会不会是代码的链接问题,在程序中,我把启动代码拷贝到了内存的0x33f00000处,因为程序的编译地址是从0x33f00000处开始执行的;用存储器地址加载指令ldr将main函数的入口地址赋给pc,我想程序应该可以执行的啊,可程序总是死掉。=========望各位指点指点。

程序初始化代码如下:

GET option.s
GET memcfg.s
GET 2410addr.s

IMPORT nand_read_ll
IMPORT Port_Init
DELAY EQU 0x200
R1_iA EQU (1<<31)
R1_nF EQU (1<<30)

BIT_SELFREFRESH EQU (1<<22)

;Pre-defined constants
USERMODE EQU 0x10
FIQMODE EQU 0x11
IRQMODE EQU 0x12
SVCMODE EQU 0x13
ABORTMODE EQU 0x17
UNDEFMODE EQU 0x1b
MODEMASK EQU 0x1f
NOINT EQU 0xc0

;The location of stacks
UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~
SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~
UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~
AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~
IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~
FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~

;Check if tasm.exe(armasm -16...@ADS1.0) is used.
GBLL THUMBCODE
[ {CONFIG} = 16
THUMBCODE SETL {TRUE}
CODE32
|
THUMBCODE SETL {FALSE}
]

MACRO
MOV_PC_LR
[ THUMBCODE
bx lr
|
mov pc,lr
]
MEND

MACRO
MOVEQ_PC_LR
[ THUMBCODE
bxeq lr
|
moveq pc,lr
]
MEND

;---------------------------------------------------------------------------
; 4 LED light function
; The LEDs are located below AMD Flash ROM

MACRO
LED_ON $data
LDR r10, =0x56000054
LDR r11, =$data
MOV r11, r11, lsl #4
STR r11, [r10]
MEND
;---------------------------------------------------------------------------

MACRO
$HandlerLabel HANDLER $HandleLabel

$HandlerLabel
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does't push because it return to original address)
ldr r0,=$HandleLabel;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND

IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)
IMPORT |Image$$RW$$Base| ; Base of RAM to initialise
IMPORT |Image$$ZI$$Base| ; Base and limit of area
IMPORT |Image$$ZI$$Limit| ; to zero initialise

IMPORT Main ; The main entry of mon program

AREA Init,CODE,READONLY

ENTRY

;1)The code, which converts to Big-endian, should be in little endian code.
;2)The following little endian code will be compiled in Big-Endian mode.
; The code byte order should be changed as the memory bus width.
;3)The pseudo instruction,DCD can't be used here because the linker generates error.
ASSERT :DEF:ENDIAN_CHANGE
b ResetHandler
[ ENDIAN_CHANGE
ASSERT :DEF:ENTRY_BUS_WIDTH
[ ENTRY_BUS_WIDTH=32
b ChangeBigEndian ;DCD 0xea000007
]

[ ENTRY_BUS_WIDTH=16
andeq r14,r7,r0,lsl #20 ;DCD 0x0007ea00
]

[ ENTRY_BUS_WIDTH=8
streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea
]
|
b ResetHandler
]
b HandlerUndef ;handler for Undefined mode
b HandlerSWI ;handler for SWI interrupt
b HandlerPabort ;handler for PAbort
b HandlerDabort ;handler for DAbort
b . ;reserved
b HandlerIRQ ;handler for IRQ interrupt
b HandlerFIQ ;handler for FIQ interrupt

;@0x20
b EnterPWDN
ChangeBigEndian
;@0x24
[ ENTRY_BUS_WIDTH=32
DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0
DCD 0xe3800080 ;0xe3800080 => orr r0,r0,#0x80; //Big-endian
DCD 0xee010f10 ;0xee010f10 => mcr p15,0,r0,c1,c0,0
]
[ ENTRY_BUS_WIDTH=16
DCD 0x0f10ee11
DCD 0x0080e380
DCD 0x0f10ee01
]
[ ENTRY_BUS_WIDTH=8
DCD 0x100f11ee
DCD 0x800080e3
DCD 0x100f01ee
]
DCD 0xffffffff ;swinv 0xffffff is similar with NOP and run well in both endian mode.
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
b ResetHandler

;Function for entering power down mode
; 1. SDRAM should be in self-refresh mode.
; 2. All interrupt should be maksked for SDRAM/DRAM self-refresh.
; 3. LCD controller should be disabled for SDRAM/DRAM self-refresh.
; 4. The I-cache may have to be turned on.
; 5. The location of the following code may have not to be changed.

;void EnterPWDN(int CLKCON);
EnterPWDN
mov r2,r0 ;r2=rCLKCON
tst r0,#0x8 ;POWER_OFF mode?
bne ENTER_POWER_OFF

ENTER_STOP
ldr r0,=REFRESH
ldr r3,[r0] ;r3=rREFRESH
mov r1, r3
orr r1, r1, #BIT_SELFREFRESH
str r1, [r0] ;Enable SDRAM self-refresh

mov r1,#16 ;wait until self-refresh is issued. may not be needed.
0 subs r1,r1,#1
bne %B0

ldr r0,=CLKCON ;enter STOP mode.
str r2,[r0]

mov r1,#32
0 subs r1,r1,#1 ;1) wait until the STOP mode is in effect.
bne %B0 ;2) Or wait here until the CPU&Peripherals will be turned-off
; Entering POWER_OFF mode, only the reset by wake-up is available.

ldr r0,=REFRESH ;exit from SDRAM self refresh mode.
str r3,[r0]

MOV_PC_LR

ENTER_POWER_OFF
;NOTE.
;1) rGSTATUS3 should have the return address after wake-up from POWER_OFF mode.

ldr r0,=REFRESH
ldr r1,[r0] ;r1=rREFRESH
orr r1, r1, #BIT_SELFREFRESH
str r1, [r0] ;Enable SDRAM self-refresh

mov r1,#16 ;Wait until self-refresh is issued,which may not be needed.
0 subs r1,r1,#1
bne %B0

ldr r1,=MISCCR
ldr r0,[r1]
orr r0,r0,#(7<<17) ;Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up
str r0,[r1]

ldr r0,=CLKCON
str r2,[r0]

b . ;CPU will die here.

WAKEUP_POWER_OFF
;Release SCLKn after wake-up from the POWER_OFF mode.

ldr r1,=MISCCR
ldr r0,[r1]
bic r0,r0,#(7<<17) ;SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:L->H
str r0,[r1]

;Set memory control registers
ldr r0,=SMRDATA
ldr r1,=BWSCON ;BWSCON Address
add r2, r0, #52 ;End address of SMRDATA
0
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne %B0

mov r1,#256
0 subs r1,r1,#1 ;1) wait until the SelfRefresh is released.
bne %B0

ldr r1,=GSTATUS3 ;GSTATUS3 has the start address just after POWER_OFF wake-up
ldr r0,[r1]
mov pc,r0

LTORG
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort

IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}

ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}

;=======
; ENTRY
;=======
ResetHandler

LED_ON 0x8

ldr r0,=WTCON ;watch dog disable
ldr r1,=0x0
str r1,[r0]

ldr r0,=INTMSK
ldr r1,=0xffffffff ;all interrupt disable
str r1,[r0]

ldr r0,=INTSUBMSK
ldr r1,=0x3ff ;all sub interrupt disable
str r1,[r0]

;feng add

ldr r0, = INTMOD
mov r1, #0x0 ; set all interrupt as IRQ (not FIQ)
str r1, [r0]

; configure GPIO pins
bl Port_Init


; CLKDIVN
ldr r0,=CLKDIVN
ldr r1,=0x3 ; 1:2:4
str r1,[r0]
; delay
mov r0, #DELAY
5 subs r0, r0, #1
bne %B5


; MMU_SetAsyncBusMode FCLK:HCLK= 1:2
ands r1, r1, #0x2
beq %F1
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0

1
;To reduce PLL lock time, adjust the LOCKTIME register.
ldr r0,=LOCKTIME
ldr r1,=0xffffff
str r1,[r0]

; delay
mov r0, #DELAY
5 subs r0, r0, #1
bne %B5


;Configure MPLL
ldr r0,=MPLLCON
ldr r1,=((0x5c<<12)+(0x4<<4)+0x0) ;Fin=12MHz,Fout=200MHz
str r1,[r0]
; delay
mov r0, #DELAY
5 subs r0, r0, #1
bne %B5

;Configure UPLL
ldr r0, =UPLLCON
ldr r1, =((0x48<<12)+(0x3<<4)+0x2) ;Fin=12MHz, Fout=48MHz
str r1, [r0]
; delay
mov r0, #0x200
5 subs r0, r0, #1
bne %B5

;Set memory control registers
ldr r0,=SMRDATA
ldr r1,=BWSCON ;BWSCON Address
add r2, r0, #52 ;End address of SMRDATA
0
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne %B0


;Initialize stacks
bl InitStacks

; Setup IRQ handler
ldr r0,=HandleIRQ ;This routine is needed
ldr r1,=IsrIRQ ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c
str r1,[r0]

;Copy and paste RW data/zero initialized data
ldr r0, =|Image$$RO$$Limit| ; Get pointer to ROM data
ldr r1, =|Image$$RW$$Base| ; and RAM copy
ldr r3, =|Image$$ZI$$Base|

mov r10,pc
ldr r4,=0x30000000
cmp r4,r10
bcc %F2

bl nand_read_ll


2
ldr r1, =|Image$$ZI$$Limit| ; Top of zero init segment
mov r2, #0
3
cmp r3, r1 ; Zero init
strcc r2, [r3], #4
bcc %B3

LED_ON 0x3

[ :LNOT:THUMBCODE
bl Main ;Don't use main() because ......
b .
]

[ THUMBCODE ;for start-up code for Thumb mode
orr lr,pc,#1
bx lr
CODE16
bl Main ;Don't use main() because ......
b .
CODE32
]


;function initializing stacks
InitStacks
;Don't use DRAM,such as stmfd,ldmfd......
;SVCstack is initialized before
;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack

orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack

orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack

orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack

bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack

;USER mode has not be initialized.

mov pc,lr
;The LR register won't be valid if the current mode is not SVC mode.

LTORG

SMRDATA DATA
; Memory configuration should be optimized for best performance
; The following parameter is not optimized.
; Memory access cycle parameter strategy
; 1) The memory settings is safe parameters even at HCLK=75Mhz.
; 2) SDRAM refresh period is for HCLK=75Mhz.

DCD (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) ;GCS0
DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) ;GCS1
DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) ;GCS2
DCD ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) ;GCS3
DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) ;GCS4
DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) ;GCS5
DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) ;GCS6
DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) ;GCS7
DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)

DCD 0x32 ;SCLK power saving mode, BANKSIZE 128M/128M

DCD 0x30 ;MRSR6 CL=3clk
DCD 0x30 ;MRSR7
; DCD 0x20 ;MRSR6 CL=2clk
; DCD 0x20 ;MRSR7

ALIGN


AREA RamData, DATA, READWRITE

^ _ISR_STARTADDRESS
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4

;Don't use the label 'IntVectorTable',
;The value of IntVectorTable is different with the address you think it may be.
;IntVectorTable
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleRSV6 # 4
HandleBATFLT # 4
HandleTICK # 4
HandleWDT # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
HandleLCD # 4
HandleDMA0 # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleRSV24 # 4
HandleUSBD # 4
HandleUSBH # 4
HandleIIC # 4
HandleUART0 # 4
HandleSPI1 # 4
HandleRTC # 4
HandleADC # 4

END




关键词: 关于 设置 问题 bootloader 程序 链接

菜鸟
2006-02-23 21:00:00 打赏
2楼

你选择从NAN FLASH启动的话,2410只把NAND FLASH的前4K拷贝到SRAM里面去,然后执行这个4K大小的程序。不知道是不是和这个有关系。


菜鸟
2006-02-24 04:55:00 打赏
3楼

谢谢twentyone 的回答。

问题终于发现了,是__inline惹得祸,不过不知道为什么:在程序中我有一个等待FLASH状态的函数

__inline void nand_wait(void) {
int i;

while(!(NF_STAT & BUSY))
for(i=0; i<10; i++);
}

据我所知,ads是支持__inline使用的,但程序中我加入__inline,就会出现上面的问题。

===========================================================

另外我想问twentyone一个问题:“RO段一般包括代码段和一些常量,在运行的时候是只读的”,那么ads链接选项里的”RO Base"又是指什么呢,程序链接出来的RO 段是不是也是只读的。如果我用ads在内存里调试程序的话,我得把ro base 设置为内存相应地址,这里程序却是可读写,那么ads的ro base 选项在程序链接时除了给程序传递ro base 这个值外,又会对程序的编译和运行产生什么影响呢。


菜鸟
2006-02-24 05:36:00 打赏
4楼

RO段是只读的。RO_BASE指定了你的RO段存放的位置,链接器根据你设定的RO_BASE来链接。如果的程序在RAM里运行的时候,你一般看不出什么影响。你考虑下面这种情况:板子上的RAM很小,程序希望在FLASH里面运行,那RO段可以放在FLASH里面,而只要把RW段拷贝到RAM里面就可以了。


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]