diff options
Diffstat (limited to 'arch/arm/lib')
-rw-r--r-- | arch/arm/lib/Makefile | 8 | ||||
-rw-r--r-- | arch/arm/lib/crt0.S | 30 | ||||
-rw-r--r-- | arch/arm/lib/interrupts_m.c | 95 | ||||
-rw-r--r-- | arch/arm/lib/relocate.S | 13 | ||||
-rw-r--r-- | arch/arm/lib/vectors_m.S | 57 |
5 files changed, 201 insertions, 2 deletions
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index da8ed72..0e1ad0e 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -8,7 +8,9 @@ lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _ashldi3.o _ashrdi3.o _divsi3.o \ _lshrdi3.o _modsi3.o _udivsi3.o _umodsi3.o div0.o -ifdef CONFIG_ARM64 +ifdef CONFIG_CPU_V7M +obj-y += vectors_m.o crt0.o +else ifdef CONFIG_ARM64 obj-y += crt0_64.o else obj-y += vectors.o crt0.o @@ -36,7 +38,9 @@ obj-$(CONFIG_SEMIHOSTING) += semihosting.o obj-y += sections.o obj-y += stack.o -ifdef CONFIG_ARM64 +ifdef CONFIG_CPU_V7M +obj-y += interrupts_m.o +else ifdef CONFIG_ARM64 obj-y += gic_64.o obj-y += interrupts_64.o else diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S index 92d3732..afd4f10 100644 --- a/arch/arm/lib/crt0.S +++ b/arch/arm/lib/crt0.S @@ -9,6 +9,9 @@ #include <config.h> #include <asm-offsets.h> #include <linux/linkage.h> +#ifdef CONFIG_CPU_V7M +#include <asm/armv7m.h> +#endif /* * This file handles the target-independent stages of the U-Boot @@ -66,15 +69,30 @@ ENTRY(_main) #else ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) #endif +#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */ + mov r3, sp + bic r3, r3, #7 + mov sp, r3 +#else bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ +#endif mov r2, sp sub sp, sp, #GD_SIZE /* allocate one GD above SP */ +#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */ + mov r3, sp + bic r3, r3, #7 + mov sp, r3 +#else bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ +#endif mov r9, sp /* GD is above SP */ mov r1, sp mov r0, #0 clr_gd: cmp r1, r2 /* while not at end of GD */ +#if defined(CONFIG_CPU_V7M) + itt lo +#endif strlo r0, [r1] /* clear 32-bit GD word */ addlo r1, r1, #4 /* move to next */ blo clr_gd @@ -94,13 +112,22 @@ clr_gd: */ ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ +#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */ + mov r3, sp + bic r3, r3, #7 + mov sp, r3 +#else bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ +#endif ldr r9, [r9, #GD_BD] /* r9 = gd->bd */ sub r9, r9, #GD_SIZE /* new GD is below bd */ adr lr, here ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */ add lr, lr, r0 +#if defined(CONFIG_CPU_V7M) + orr lr, #1 /* As required by Thumb-only */ +#endif ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ b relocate_code here: @@ -134,6 +161,9 @@ here: mov r2, #0x00000000 /* prepare zero to clear BSS */ clbss_l:cmp r0, r1 /* while not at end of BSS */ +#if defined(CONFIG_CPU_V7M) + itt lo +#endif strlo r2, [r0] /* clear 32-bit BSS word */ addlo r0, r0, #4 /* move to next */ blo clbss_l diff --git a/arch/arm/lib/interrupts_m.c b/arch/arm/lib/interrupts_m.c new file mode 100644 index 0000000..89ce493 --- /dev/null +++ b/arch/arm/lib/interrupts_m.c @@ -0,0 +1,95 @@ +/* + * (C) Copyright 2015 + * Kamil Lulko, <rev13@wp.pl> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +/* + * Upon exception entry ARMv7-M processors automatically save stack + * frames containing some registers. For simplicity initial + * implementation uses only this auto-saved stack frame. + * This does not contain complete register set dump, + * only R0-R3, R12, LR, PC and xPSR are saved. + */ + +struct autosave_regs { + long uregs[8]; +}; + +#define ARM_XPSR uregs[7] +#define ARM_PC uregs[6] +#define ARM_LR uregs[5] +#define ARM_R12 uregs[4] +#define ARM_R3 uregs[3] +#define ARM_R2 uregs[2] +#define ARM_R1 uregs[1] +#define ARM_R0 uregs[0] + +int interrupt_init(void) +{ + return 0; +} + +void enable_interrupts(void) +{ + return; +} + +int disable_interrupts(void) +{ + return 0; +} + +void dump_regs(struct autosave_regs *regs) +{ + printf("pc : %08lx lr : %08lx xPSR : %08lx\n", + regs->ARM_PC, regs->ARM_LR, regs->ARM_XPSR); + printf("r12 : %08lx r3 : %08lx r2 : %08lx\n" + "r1 : %08lx r0 : %08lx\n", + regs->ARM_R12, regs->ARM_R3, regs->ARM_R2, + regs->ARM_R1, regs->ARM_R0); +} + +void bad_mode(void) +{ + panic("Resetting CPU ...\n"); + reset_cpu(0); +} + +void do_hard_fault(struct autosave_regs *autosave_regs) +{ + printf("Hard fault\n"); + dump_regs(autosave_regs); + bad_mode(); +} + +void do_mm_fault(struct autosave_regs *autosave_regs) +{ + printf("Memory management fault\n"); + dump_regs(autosave_regs); + bad_mode(); +} + +void do_bus_fault(struct autosave_regs *autosave_regs) +{ + printf("Bus fault\n"); + dump_regs(autosave_regs); + bad_mode(); +} + +void do_usage_fault(struct autosave_regs *autosave_regs) +{ + printf("Usage fault\n"); + dump_regs(autosave_regs); + bad_mode(); +} + +void do_invalid_entry(struct autosave_regs *autosave_regs) +{ + printf("Exception\n"); + dump_regs(autosave_regs); + bad_mode(); +} diff --git a/arch/arm/lib/relocate.S b/arch/arm/lib/relocate.S index 92f5314..475d503 100644 --- a/arch/arm/lib/relocate.S +++ b/arch/arm/lib/relocate.S @@ -9,6 +9,9 @@ #include <asm-offsets.h> #include <config.h> #include <linux/linkage.h> +#ifdef CONFIG_CPU_V7M +#include <asm/armv7m.h> +#endif /* * Default/weak exception vectors relocation routine @@ -23,6 +26,15 @@ ENTRY(relocate_vectors) +#ifdef CONFIG_CPU_V7M + /* + * On ARMv7-M we only have to write the new vector address + * to VTOR register. + */ + ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ + ldr r1, =V7M_SCB_BASE + str r0, [r1, V7M_SCB_VTOR] +#else #ifdef CONFIG_HAS_VBAR /* * If the ARM processor has the security extensions, @@ -47,6 +59,7 @@ ENTRY(relocate_vectors) ldmia r0!, {r2-r8,r10} stmia r1!, {r2-r8,r10} #endif +#endif bx lr ENDPROC(relocate_vectors) diff --git a/arch/arm/lib/vectors_m.S b/arch/arm/lib/vectors_m.S new file mode 100644 index 0000000..abc7f88 --- /dev/null +++ b/arch/arm/lib/vectors_m.S @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2015 + * Kamil Lulko, <rev13@wp.pl> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <asm/armv7m.h> +#include <linux/linkage.h> + +.type __hard_fault_entry, %function +__hard_fault_entry: + mov r0, sp @ pass auto-saved registers as argument + b do_hard_fault + +.type __mm_fault_entry, %function +__mm_fault_entry: + mov r0, sp @ pass auto-saved registers as argument + b do_mm_fault + +.type __bus_fault_entry, %function +__bus_fault_entry: + mov r0, sp @ pass auto-saved registers as argument + b do_bus_fault + +.type __usage_fault_entry, %function +__usage_fault_entry: + mov r0, sp @ pass auto-saved registers as argument + b do_usage_fault + +.type __invalid_entry, %function +__invalid_entry: + mov r0, sp @ pass auto-saved registers as argument + b do_invalid_entry + + .section .vectors +ENTRY(_start) + .long CONFIG_SYS_INIT_SP_ADDR @ 0 - Reset stack pointer + .long reset @ 1 - Reset + .long __invalid_entry @ 2 - NMI + .long __hard_fault_entry @ 3 - HardFault + .long __mm_fault_entry @ 4 - MemManage + .long __bus_fault_entry @ 5 - BusFault + .long __usage_fault_entry @ 6 - UsageFault + .long __invalid_entry @ 7 - Reserved + .long __invalid_entry @ 8 - Reserved + .long __invalid_entry @ 9 - Reserved + .long __invalid_entry @ 10 - Reserved + .long __invalid_entry @ 11 - SVCall + .long __invalid_entry @ 12 - Debug Monitor + .long __invalid_entry @ 13 - Reserved + .long __invalid_entry @ 14 - PendSV + .long __invalid_entry @ 15 - SysTick + .rept 255 - 16 + .long __invalid_entry @ 16..255 - External Interrupts + .endr |