Hi all,
I recently had questions here about SDRAM initialization and startup consideratins.
I figured it out so I would like to ensure at least taht nobody blocks stupidly as I did. Here is the CStartup.s79 file I ended with.
Please note tnhat the stacks are not initialized, the interrupt vectors are neither. All this must be done, I elected to do it in C in the low_level_init() function called by IAR system after (very) low level init.
Of course to init the vectors, we need to have them in RAM.
The #ifdef around the SDRAm initialization is there to allow compiling versions to download into SDRAM for bench tests so that it does not saw the branch on which it sits.
Also the funny C-style comments are for doxygen. Dont worry about them.
If anybody has improvement suggestions, you are very welcome.
(Apparently all the tabs have been removed. Good luck)
Best regards to all of you out there working on that board.
Patrick
; /**
; \file cstartup.s79
; \brief This is the bootstrap code: It initializes the CPU clocks and busses, sets the pins functions and initializes the SDRAM.
; */
;-----------------------------------------------------------------------------
; This file contains the startup code used by the ICCARM C compiler.
;
; All code in the modules (except ?RESET) will be placed in the ICODE segment.
;
;-----------------------------------------------------------------------------
;---------------------------------------------------------------
; Macros and definitions for the whole file
;---------------------------------------------------------------
; Mode, correspords to bits 0-5 in CPSR
MODE_BITS DEFINE 0x1F ; Bit mask for mode bits in CPSR
USR_MODE DEFINE 0x10 ; User mode
FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12 ; Interrupt Request mode
SVC_MODE DEFINE 0x13 ; Supervisor mode
ABT_MODE DEFINE 0x17 ; Abort mode
UND_MODE DEFINE 0x1B ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F ; System mode
;---------------------------------------------------------------
; ?RESET
; Reset Vector.
;---------------------------------------------------------------
MODULE ?RESET
COMMON INTVEC:CODE:NOROOT(2)
PUBLIC __program_start
EXTERN ?cstartup
EXTERN undef_handler, swi_handler, prefetch_handler
EXTERN data_handler, irq_handler, fiq_handler
CODE32 ; Always ARM mode after reset
ORG 0x00
__program_start
; Here are the main ARM interrupt vectors.
ldr pc,=?cstartup ; Absolute jump can reach 4 GByte
; b ?cstartup ; Relative branch allows remap, limited to 32 MByte
org 0x04
; ldr pc,=undef_handler
org 0x08
; ldr pc,=swi_handler
org 0x0c
; ldr pc,=prefetch_handler
org 0x10
; ldr pc,=data_handler
org 0x18
; ldr pc,=irq_handler
org 0x1c
; ldr pc,=fiq_handler
; Constant table entries (for ldr pc) will be placed at 0x20
org 0x20
LTORG
; ENDMOD __program_start
ENDMOD
;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
MODULE ?CSTARTUP
RSEG IRQ_STACK:DATA(2)
RSEG SVC_STACK:DATA:NOROOT(2)
RSEG CSTACK:DATA(2)
RSEG ICODE:CODE:NOROOT(2)
PUBLIC ?cstartup
EXTERN ?main
; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.
CODE32
?cstartup
; Add initialization nedded before setup of stackpointers here
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; Disable the MMU
mov r1,#0x70
mcr p15, 0, r1, c1, c0, 0
; set SVC mode
mov r0,#0xd3
msr cpsr_cxsf,r0
nop
; Disable the interruption
ldr r1,=0xfffff000 ; =VIC_BASE #
mov r0,#0
str r0,[r1,#0x10] ; VICIntEnable
; unlock the RCPC
ldr r1,=0xfffe2000 ; =RCPC_BASE #
ldr r0,[r1,#0]
orr r0,r0,#0x200
str r0,[r1,#0] ; RCPC Control
; // Enable crystal osc; enable the PLL, select the PLL
; RCPC_Ctrl = 0x23;
; set the CPU running as FAST mode
ldr r1,=0xfffe2000 ; =RCPC_BASE #
ldr r0,[r1,#0x88]
bic r0,r0,#3
str r0,[r1,#0x88] ; CoreClkConfig
; set the CPU running at 50 Mhz
ldr r1,=0xfffe2000 ; =RCPC_BASE #
mov r0,#3
str r0,[r1,#0x1c] ; CpuClkPrescale
; set the HCLK running at 50 Mhz
ldr r1,=0xfffe2000 ; =RCPC_BASE #
mov r0,#3
str r0,[r1,#0x18] ; HclkPrescale
; set the Mux pin register
ldr r1,=0xfffe5000 ; =MUX_BASE #
ldr r0,[r1,#0]
and r0,r0,#0
orr r0,r0,#0x1700
orr r0,r0,#0xef
; set the MemMux register
str r0,[r1,#0] ; MemMux
ldr r0,[r1,#8]
and r0,r0,#0
orr r0,r0,#0x100
orr r0,r0,#0xfe
; set the MiscMux register
str r0,[r1,#8] ; MiscMux
ldr r0,[r1,#0x10]
and r0,r0,#0
orr r0,r0,#0xf
; set the UARTMux register
str r0,[r1,#0x10] ; UARTMux
; enable the clock to AHB bus
ldr r1,=0xfffe2000 ; =RCPC_BASE #
ldr r0,[r1,#0x2c]
and r0,r0,#0
orr r0,r0,#5
str r0,[r1,#0x2c] ; AHBClkCtrl
; start to config the SDRAM
#ifdef INIT_SDRAM
; set SDRCRefTimer = 10
ldr r1,=0xffff2000 ; SDRC_BASE
ldr r0,[r1,#8]
and r0,r0,#0
orr r0,r0,#0xa ; is 0xa
str r0,[r1,#8] ; SDRCRefTimer
; issue NOP command for 0x10000 times
ldr r1,=0xffff2000 ; SDRC_BASE
ldr r0,[r1,#4] ; SDRCConfig1
bic r0,r0,#3
orr r0,r0,#3
mov r2,#0x10000
wait_10000
str r0,[r1,#4] ; SDRCConfig1
sub r2,r2,#1
cmp r2,#0
beq wait_10000_done
nop
b wait_10000
wait_10000_done
; issue Precharge All command
ldr r1,=0xffff2000 ; SDRC_BASE
ldr r0,[r1,#4]
bic r0,r0,#3
orr r0,r0,#1
str r0,[r1,#4] ; SDRCConfig1
; wait for a while = 20 cycles
mov r2,#0x20
wait_20
sub r2,r2,#1
cmp r2,#0
beq wait_20_done
nop
b wait_20
wait_20_done
; set SDRCRefTimer = 0x2ee = 750
ldr r1,=0xffff2000 ; SDRC_BASE
ldr r0,[r1,#8]
and r0,r0,#0
orr r0,r0,#0xee
orr r0,r0,#0x200
str r0,[r1,#8] ; SDRCRefTimer
; SDRAM_BASE_ADDR | (0x22 << 12)
mov r1,#0x20000000 ; SDRAM_BASE_ADDRESS
mov r3,#0x22
mov r3,r3,lsl #12
orr r3,r3,r1
; issue Enable SDRAM MODE command
ldr r1,=0xffff2000 ; SDRC_BASE
ldr r0,[r1,#4] ; SDRCConfig1
bic r0,r0,#3
orr r0,r0,#2
str r0,[r1,#4] ; SDRCConfig1
; tmp = *((int *)(SDRAM_BASE_ADDR | (0x22 << 12))
ldr r1,[r3,#0]
; Wait until idle
ldr r1,=0xffff2000 ; SDRC_BASE
wait_idle_1
ldr r0,[r1,#4] ; SDRCConfig1
tst r0,#0x20
beq wait_idle_1
nop
; Set SDRCCongig0 register
ldr r1,=0xffff2000 ; SDRC_BASE
ldr r0,[r1,#0] ; SDRCConfig0
and r0,r0,#0
orr r0,r0,#0x1000000
orr r0,r0,#0xa00000
orr r0,r0,#0x40000
orr r0,r0,#0x88
str r0,[r1,#0] ; SDRCConfig0
; Wait until idle
ldr r1,=0xffff2000 ; SDRC_BASE
wait_idle_2
ldr r0,[r1,#4] ; SDRCConfig1
tst r0,#0x20
beq wait_idle_2
nop
; issue NORMAL command
ldr r1,=0xffff2000 ; SDRC_BASE
ldr r0,[r1,#4]
bic r0,r0,#3
str r0,[r1,#4] ; SDRCConfig1
; wait until idle
ldr r1,=0xffff2000 ; SDRC_BASE
wait_idle_3
ldr r0,[r1,#4] ; SDRCConfig1
tst r0,#0x20
beq wait_idle_3
nop
#endif ; INIT_SDRAM
; SDRAM is ready to use now
; Stop the Watchdog Timer
eor r0,r0,r0
ldr r1,=0xFFFE3000 ; =WDT_BASE
str r0,[r1,#0]
; Clear Peripheral Clock Control bits so Timers,
; RTC, PWM's, UART's
; will work
ldr r1,=0xfffe2000 ; =RCPC_BASE
mvn r0,#0
ldr r2,=0x3B7
bic r0,r0,r2
str r0,[r1,#0x24] ; address for PeriphClkCtrl
; Enable the LCD clock to enable the LCD
ldr r1,=0xfffe2000 ; =RCPC_BASE
mov r0,#0x0
str r0,[r1,#0x28] ; address for PeriphClkCtrl2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Flash memory is slow upon reset, maker it faster here
; configure the SMC for accessing the flash from bank 0 (nCS0).
; the LH28F320BJE is a 90 ns device with about 15 extra ns
; of gate delays. 5 wait states makes 96.88 ns, not enough.
; 6 wait states makes 116.26 ns, which is OK. Program as follows:
; No Retry, Width 16 bits, non-burst, write-enabled, clear errors,
; 6 write wait states, all byte lane controls are high during
; reads, 6 read wait states, 1 HCLK bus turnaround time
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ldr r1,=0xFFFF1000 ; =SMC_BASE
ldr r0,=0x13002CA0
str r0,[r1,#0]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Chip select SMCBCRx register set
; All set as 16 bit bus width
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ldr r1,=0xFFFF1000 ; =SMC_BASE
ldr r0,=0x13002CA0 ; 6 wait status
str r0,[r1,#0x4] ; nCS1
str r0,[r1,#0x8] ; nCS2
str r0,[r1,#0xC] ; nCS3
ldr r0,=0x13008CE0
str r0,[r1,#0x10] ; nCS4 slow for Compact Flash
ldr r0,=0x1300FD03
str r0,[r1,#0x14] ; nCS5
str r0,[r1,#0x18] ; nCS6
; ; --- Initialize stack pointer registers
; ; Enter IRQ mode and set up the IRQ stack pointer
; mov r0, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; No interrupts
; msr cpsr_c, r0
; ldr sp, =IRQ_Stack
;
; ; Enter FIQ mode and set up the FIQ stack pointer
; mov r0, #Mode_FIQ:OR:I_Bit:OR:F_Bit ; No interrupts
; msr cpsr_c, r0
; ldr sp, =FIQ_Stack
;
; ; Enter ABT mode and set up the ABT stack pointer
; mov r0, #Mode_ABT:OR:I_Bit:OR:F_Bit ; No interrupts
; msr cpsr_c, r0
; ldr sp, =ABT_Stack
;
; ; Enter IRQ mode and set up the IRQ stack pointer
; mov r0, #Mode_UNDEF:OR:I_Bit:OR:F_Bit ; No interrupts
; msr cpsr_c, r0
; ldr sp, =UNDEF_Stack
;
; ; Set up the SVC stack pointer last and return to SVC mode
; mov r0, #Mode_SVC:OR:I_Bit:OR:F_Bit ; No interrupts
; msr cpsr_c, r0
; ldr sp, =SVC_Stack
; ; clear all the existing interrupts
ldr r1,=0xfffff000 ;VIC controller base
ldr r0,=0xFFFFFFFF
str r0,[r1,#0x14] ;VICIntEnableClear
str r0,[r1,#0x1C] ;VICSoftIntClear
mov r0,#0
str r0,[r1,#0x30] ;Interrupt Vector Address
str r0,[r1,#0x200] ;Interrupt Vector Control[0]
str r0,[r1,#0x204] ;Interrupt Vector Control[1]
str r0,[r1,#0x208] ;Interrupt Vector Control[2]
str r0,[r1,#0x20c] ;Interrupt Vector Control[3]
str r0,[r1,#0x210] ;Interrupt Vector Control[4]
str r0,[r1,#0x214] ;Interrupt Vector Control[5]
str r0,[r1,#0x218] ;Interrupt Vector Control[6]
str r0,[r1,#0x21c] ;Interrupt Vector Control[7]
str r0,[r1,#0x220] ;Interrupt Vector Control[8]
str r0,[r1,#0x224] ;Interrupt Vector Control[9]
str r0,[r1,#0x228] ;Interrupt Vector Control[10]
str r0,[r1,#0x22c] ;Interrupt Vector Control[11]
str r0,[r1,#0x230] ;Interrupt Vector Control[12]
str r0,[r1,#0x234] ;Interrupt Vector Control[13]
str r0,[r1,#0x238] ;Interrupt Vector Control[14]
str r0,[r1,#0x23c] ;Interrupt Vector Control[15]
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
mrs r0,cpsr ; Original PSR value
; Interrupt
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#IRQ_MODE ; Set IRQ mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(IRQ_STACK) & 0xFFFFFFF8 ; End of IRQ_STACK
; User and system
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#SYS_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(CSTACK) & 0xFFFFFFF8 ; End of CSTACK
; ; Fast interrupt
; bic r0,r0,#MODE_BITS ; Clear the mode bits
; orr r0,r0,#FIQ_MODE ; Set System mode bits
; msr cpsr_c,r0 ; Change the mode
; ldr sp,=SFE(FIQSTACK) & 0xFFFFFFF8 ; End of FIQSTACK
;
; ; Supervisor
; bic r0,r0,#MODE_BITS ; Clear the mode bits
; orr r0,r0,#SYS_MODE ; Set System mode bits
; msr cpsr_c,r0 ; Change the mode
; ldr sp,=SFE(SRVTACK) & 0xFFFFFFF8 ; End of CSTACK
;
; ; Undefined instruction
; bic r0,r0,#MODE_BITS ; Clear the mode bits
; orr r0,r0,#SYS_MODE ; Set System mode bits
; msr cpsr_c,r0 ; Change the mode
; ldr sp,=SFE(UNDTACK) & 0xFFFFFFF8 ; End of CSTACK
;
; ; Abort
; bic r0,r0,#MODE_BITS ; Clear the mode bits
; orr r0,r0,#SYS_MODE ; Set System mode bits
; msr cpsr_c,r0 ; Change the mode
; ldr sp,=SFE(ABTSTACK) & 0xFFFFFFF8 ; End of CSTACK
#ifdef __ARMVFP__
; Enable the VFP coprocessor.
mov r0, #0x40000000 ; Set EN bit in VFP
fmxr fpexc, r0 ; FPEXC, clear others.
; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
mov r0, #0x01000000 ; Set FZ bit in VFP
fmxr fpscr, r0 ; FPSCR, clear others.
#endif
; Add more initialization here
; Continue to ?main for more IAR specific system startup
ldr r0,=?main
bx r0
LTORG
ENDMOD
END
|