[U-Boot-Users] Uboot-V2: ARM: towards a common start-arm.S

Hi Sascha,
I think we dont have a seperate list for uboot-v2, so, just wanted to know the opinion of having a single arch/arm/cpu/start-arm.S instead of multiple start-arm files. essentially providing hooks to arch,soc,board specific preinits can allow us to reuse major chunk of code.. I have attached a sample start-arm.S (modified from start-arm920t.S) as reference.
Do let me know your comments and view as to how the initial handling can be made abstract enough to plug into requirements of future SOCs, boards etc. I am looking not to mash in #ifdef ARCH_XYZ for each of the SOC implementation I plan on doing.
Regards, Nishanth Menon
/* * armboot - Startup Code for ARM920 CPU-core * * Copyright (c) 2001 Marius Gr�ger mag@sysgo.de * Copyright (c) 2002 Alex Z�pke azu@sysgo.de * Copyright (c) 2002 Gary Jennejohn gj@denx.de * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */
/** * @file * @brief The very basic beginning of each CPU after reset * * @note * This reset code can be used at least for All ARM platforms * * FIXME: Stop doxygen from parsing the text below */ .section ".text_entry","ax"
#include <config.h>
/************************************************************************* * Jump vector table as in table 3.1 in [1] *************************************************************************/
.globl _start _start: b reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq
_undefined_instruction: .word undefined_instruction _software_interrupt: .word software_interrupt _prefetch_abort: .word prefetch_abort _data_abort: .word data_abort _not_used: .word not_used _irq: .word irq _fiq: .word fiq
.balignl 16,0xdeadbeef
/* ************************************************************************* * * Startup Code (reset vector) * * do important init only if we don't start from memory! * setup Memory and board specific bits prior to relocation. * relocate armboot to ram * setup stack * ************************************************************************* */
_TEXT_BASE: .word TEXT_BASE
.globl _u_boot_start _u_boot_start: .word _start
/************************************************************************* * FIXME *************************************************************************/
_MALLOC_START: .word _start - CFG_MALLOC_LEN
_STACK_START: .word _start - CFG_MALLOC_LEN - CONFIG_STACKSIZE
/* * These are defined in the board-specific linker script. */ .globl _bss_start _bss_start: .word __bss_start
.globl _bss_end _bss_end: .word _end
#ifdef CONFIG_USE_IRQ /* IRQ stack memory (calculated at run-time) */ .globl IRQ_STACK_START IRQ_STACK_START: .word 0x0badc0de
/* IRQ stack memory (calculated at run-time) */ .globl FIQ_STACK_START FIQ_STACK_START: .word 0x0badc0de #endif
/************************************************************************* * the actual reset code *************************************************************************/ reset: /* * set the cpu to SVC32 mode */ mrs r0,cpsr bic r0,r0,#0x1f orr r0,r0,#0xd3 msr cpsr,r0
#ifdef ARCH_HAS_INIT_LOWLEVEL bl arch_init_lowlevel #endif #ifdef CONFIG_SOC_PRE_INIT /* Do SOC specific initalization here * r0 contains the start address * This allows for SOC code to configure * based on current program execution context * E.g.: NOR boot Vs SDRAM boot. */ mov r0,pc bl soc_init_crit #endif /* CONFIG_SOC_PRE_INIT */
/* * we do sys-critical inits only at reboot, * not when booting from ram! */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit #endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup
ldr r2, _u_boot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ add r2, r0, r2 /* r2 <- source end address */
copy_loop: ldmia r0!, {r3-r10} /* copy from source address [r0] */ stmia r1!, {r3-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
/* Set up the stack */ stack_setup: ldr r0, _MALLOC_START /* upper 128 KiB: relocated uboot */ #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif sub sp, r0, #12 /* leave 3 words for abort-stack */
clear_bss: ldr r0, _bss_start /* find start of bss segment */ ldr r1, _bss_end /* stop here */ mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 ble clbss_l
ldr pc, _start_armboot
_start_armboot: .word start_uboot
/************************************************************************* * * CPU_init_critical registers * * setup important registers * setup memory timing * ************************************************************************/ #ifndef CONFIG_SKIP_LOWLEVEL_INIT cpu_init_crit: /* * flush v4 I/D caches */ mov r0, #0 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
/* * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ #ifdef CONFIG_ARM_ALIGN_ABRT orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ #endif #ifdef CONFIG_ARM_I_CACHE orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ #endif mcr p15, 0, r0, c1, c0, 0
/* * before relocating, we have to setup RAM timing * because memory timing is board-dependent, you will * find a lowlevel_init.S in your board directory. */ mov ip, lr bl board_init_lowlevel mov lr, ip mov pc, lr #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
/* ************************************************************************* * * Interrupt handling * ************************************************************************* */
@ @ IRQ stack frame. @ #define S_FRAME_SIZE 72
#define S_OLD_R0 68 #define S_PSR 64 #define S_PC 60 #define S_LR 56 #define S_SP 52
#define S_IP 48 #define S_FP 44 #define S_R10 40 #define S_R9 36 #define S_R8 32 #define S_R7 28 #define S_R6 24 #define S_R5 20 #define S_R4 16 #define S_R3 12 #define S_R2 8 #define S_R1 4 #define S_R0 0
#define MODE_SVC 0x13 #define I_BIT 0x80
/* * use bad_save_user_regs for abort/prefetch/undef/swi ... * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling */
.macro bad_save_user_regs sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0-r12 ldr r2, _STACK_START sub r2, r2, #(8) @ set base 2 words into abort stack ldmia r2, {r2 - r3} @ get pc, cpsr add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
add r5, sp, #S_SP mov r1, lr stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr mov r0, sp .endm
.macro irq_save_user_regs sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0-r12 add r8, sp, #S_PC stmdb r8, {sp, lr}^ @ Calling SP, LR str lr, [r8, #0] @ Save calling PC mrs r6, spsr str r6, [r8, #4] @ Save CPSR str r0, [r8, #8] @ Save OLD_R0 mov r0, sp .endm
.macro irq_restore_user_regs ldmia sp, {r0 - lr}^ @ Calling r0 - lr mov r0, r0 ldr lr, [sp, #S_PC] @ Get PC add sp, sp, #S_FRAME_SIZE subs pc, lr, #4 @ return & move spsr_svc into cpsr .endm
.macro get_bad_stack ldr r2, _STACK_START sub r13, r13, #(8) @ reserved a couple spots in abort stack
str lr, [r13] @ save caller lr / spsr mrs lr, spsr str lr, [r13, #4]
mov r13, #MODE_SVC @ prepare SVC-Mode @ msr spsr_c, r13 msr spsr, r13 mov lr, pc movs pc, lr .endm
.macro get_irq_stack @ setup IRQ stack ldr sp, IRQ_STACK_START .endm
.macro get_fiq_stack @ setup FIQ stack ldr sp, FIQ_STACK_START .endm
/* * exception handlers */ .align 5 undefined_instruction: get_bad_stack bad_save_user_regs bl do_undefined_instruction
.align 5 software_interrupt: get_bad_stack bad_save_user_regs bl do_software_interrupt
.align 5 prefetch_abort: get_bad_stack bad_save_user_regs bl do_prefetch_abort
.align 5 data_abort: get_bad_stack bad_save_user_regs bl do_data_abort
.align 5 not_used: get_bad_stack bad_save_user_regs bl do_not_used
#ifdef CONFIG_USE_IRQ
.align 5 irq: get_irq_stack irq_save_user_regs bl do_irq irq_restore_user_regs
.align 5 fiq: get_fiq_stack /* someone ought to write a more effiction fiq_save_user_regs */ irq_save_user_regs bl do_fiq irq_restore_user_regs
#else
.align 5 irq: get_bad_stack bad_save_user_regs bl do_irq
.align 5 fiq: get_bad_stack bad_save_user_regs bl do_fiq
#endif

Hi,
On Mon, Mar 17, 2008 at 05:32:10PM -0500, Nishanth Menon wrote:
Hi Sascha,
I think we dont have a seperate list for uboot-v2,
No we have not. This is the right place ;)
so, just wanted to know the opinion of having a single arch/arm/cpu/start-arm.S instead of multiple start-arm files. essentially providing hooks to arch,soc,board specific preinits can allow us to reuse major chunk of code.. I have attached a sample start-arm.S (modified from start-arm920t.S) as reference.
Do let me know your comments and view as to how the initial handling can be made abstract enough to plug into requirements of future SOCs, boards etc. I am looking not to mash in #ifdef ARCH_XYZ for each of the SOC implementation I plan on doing.
Regards, Nishanth Menon
It is my plan to unify the different start.S files anyway, so good idea ;)
I'll comment on a diff to current start-arm920t.S as it's easier to see what you actually changed.
diff --git a/arch/arm/cpu/start-arm920t.S b/arch/arm/cpu/start-arm920t.S index db52ad9..a2c9ecb 100644 --- a/arch/arm/cpu/start-arm920t.S +++ b/arch/arm/cpu/start-arm920t.S @@ -29,11 +29,7 @@
- @brief The very basic beginning of each CPU after reset
- @note
- This reset code can be used at least for:
- ARM920T
- i.MX1
- i.MX27
- i.MX31
- This reset code can be used at least for All ARM platforms
I wouldn't say it works at least on all arm platforms, maybe for xscale it's easier to have a start-xscale.S, but I haven't looked into this very deeply. But for sure this code won't work on any non-arm platform.
- FIXME: Stop doxygen from parsing the text below
*/ @@ -134,32 +130,26 @@ reset: #ifdef ARCH_HAS_INIT_LOWLEVEL bl arch_init_lowlevel #endif
- /*
* flush v4 I/D caches
*/
- mov r0, #0
- mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
- mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
- /*
* disable MMU stuff and caches
+#ifdef CONFIG_SOC_PRE_INIT
- /* Do SOC specific initalization here
* r0 contains the start address
* This allows for SOC code to configure
* based on current program execution context
*/* E.g.: NOR boot Vs SDRAM boot.
- mrc p15, 0, r0, c1, c0, 0
- bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
- bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
- orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
- orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
- mcr p15, 0, r0, c1, c0, 0
- mov r0,pc
- bl soc_init_crit
+#endif /* CONFIG_SOC_PRE_INIT */
We do not have any SoC specific init at the moment, but when you need it lets introduce it here.
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a lowlevel_init.S in your board directory.
* we do sys-critical inits only at reboot,
*/* not when booting from ram!
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
- bl board_init_lowlevel
- bl cpu_init_crit
#endif
+#ifndef CONFIG_SKIP_RELOCATE_UBOOT relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ @@ -176,6 +166,7 @@ copy_loop: stmia r1!, {r3-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop +#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
No need to introduce this option. Look into the various board specific lowlevel-init.S. They all check whether we run from RAM or not, so all binaries can run from RAM or ROM without changes. In case we run with start address == link address the relocation is skipped anyway.
/* Set up the stack */ stack_setup: @@ -199,6 +190,48 @@ clbss_l:str r2, [r0] /* clear loop... */
_start_armboot: .word start_uboot
+/*************************************************************************
- CPU_init_critical registers
- setup important registers
- setup memory timing
- ************************************************************************/
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit:
- /*
* flush v4 I/D caches
*/
- mov r0, #0
- mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
- mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
- /*
* disable MMU stuff and caches
*/
- mrc p15, 0, r0, c1, c0, 0
- bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
- bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
+#ifdef CONFIG_ARM_ALIGN_ABRT
- orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
+#endif +#ifdef CONFIG_ARM_I_CACHE
- orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
+#endif
- mcr p15, 0, r0, c1, c0, 0
- /*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependent, you will
* find a lowlevel_init.S in your board directory.
*/
- mov ip, lr
- bl board_init_lowlevel
- mov lr, ip
- mov pc, lr
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
Do we really need the SKIP_LOWLEVEL_INIT option? It should be safe to run all times.
Sascha
participants (2)
-
Nishanth Menon
-
Sascha Hauer