ARM: Add ARMv7-M support

Signed-off-by: Kamil Lulko <rev13@wp.pl>
master
rev13@wp.pl 9 years ago committed by Tom Rini
parent 5d27223ea5
commit 12d8a72913
  1. 4
      arch/arm/Kconfig
  2. 9
      arch/arm/cpu/armv7m/Makefile
  3. 8
      arch/arm/cpu/armv7m/config.mk
  4. 35
      arch/arm/cpu/armv7m/cpu.c
  5. 15
      arch/arm/cpu/armv7m/start.S
  6. 60
      arch/arm/include/asm/armv7m.h
  7. 8
      arch/arm/lib/Makefile
  8. 30
      arch/arm/lib/crt0.S
  9. 95
      arch/arm/lib/interrupts_m.c
  10. 13
      arch/arm/lib/relocate.S
  11. 57
      arch/arm/lib/vectors_m.S

@ -33,6 +33,9 @@ config CPU_V7
bool
select HAS_VBAR
config CPU_V7M
bool
config CPU_PXA
bool
@ -47,6 +50,7 @@ config SYS_CPU
default "arm1136" if CPU_ARM1136
default "arm1176" if CPU_ARM1176
default "armv7" if CPU_V7
default "armv7m" if CPU_V7M
default "pxa" if CPU_PXA
default "sa1100" if CPU_SA1100
default "armv8" if ARM64

@ -0,0 +1,9 @@
#
# (C) Copyright 2000-2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# SPDX-License-Identifier: GPL-2.0+
#
extra-y := start.o
obj-y += cpu.o

@ -0,0 +1,8 @@
#
# (C) Copyright 2015
# Kamil Lulko, <rev13@wp.pl>
#
# SPDX-License-Identifier: GPL-2.0+
#
PLATFORM_CPPFLAGS += -march=armv7-m -mthumb

@ -0,0 +1,35 @@
/*
* (C) Copyright 2010,2011
* Vladimir Khusainov, Emcraft Systems, vlad@emcraft.com
*
* (C) Copyright 2015
* Kamil Lulko, <rev13@wp.pl>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/armv7m.h>
/*
* This is called right before passing control to
* the Linux kernel point.
*/
int cleanup_before_linux(void)
{
return 0;
}
/*
* Perform the low-level reset.
*/
void reset_cpu(ulong addr)
{
/*
* Perform reset but keep priority group unchanged.
*/
writel((V7M_AIRCR_VECTKEY << V7M_AIRCR_VECTKEY_SHIFT)
| (V7M_SCB->aircr & V7M_AIRCR_PRIGROUP_MSK)
| V7M_AIRCR_SYSRESET, &V7M_SCB->aircr);
}

@ -0,0 +1,15 @@
/*
* (C) Copyright 2015
* Kamil Lulko, <rev13@wp.pl>
*
* SPDX-License-Identifier: GPL-2.0+
*/
.globl reset
.type reset, %function
reset:
b _main
.globl c_runtime_cpu_setup
c_runtime_cpu_setup:
mov pc, lr

@ -0,0 +1,60 @@
/*
* (C) Copyright 2010,2011
* Vladimir Khusainov, Emcraft Systems, vlad@emcraft.com
*
* (C) Copyright 2015
* Kamil Lulko, <rev13@wp.pl>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef ARMV7M_H
#define ARMV7M_H
#if defined(__ASSEMBLY__)
.syntax unified
.thumb
#endif
#define V7M_SCB_BASE 0xE000ED00
#define V7M_MPU_BASE 0xE000ED90
#define V7M_SCB_VTOR 0x08
#if !defined(__ASSEMBLY__)
struct v7m_scb {
uint32_t cpuid; /* CPUID Base Register */
uint32_t icsr; /* Interrupt Control and State Register */
uint32_t vtor; /* Vector Table Offset Register */
uint32_t aircr; /* App Interrupt and Reset Control Register */
};
#define V7M_SCB ((struct v7m_scb *)V7M_SCB_BASE)
#define V7M_AIRCR_VECTKEY 0x5fa
#define V7M_AIRCR_VECTKEY_SHIFT 16
#define V7M_AIRCR_ENDIAN (1 << 15)
#define V7M_AIRCR_PRIGROUP_SHIFT 8
#define V7M_AIRCR_PRIGROUP_MSK (0x7 << V7M_AIRCR_PRIGROUP_SHIFT)
#define V7M_AIRCR_SYSRESET (1 << 2)
#define V7M_ICSR_VECTACT_MSK 0xFF
struct v7m_mpu {
uint32_t type; /* Type Register */
uint32_t ctrl; /* Control Register */
uint32_t rnr; /* Region Number Register */
uint32_t rbar; /* Region Base Address Register */
uint32_t rasr; /* Region Attribute and Size Register */
};
#define V7M_MPU ((struct v7m_mpu *)V7M_MPU_BASE)
#define V7M_MPU_CTRL_ENABLE (1 << 0)
#define V7M_MPU_CTRL_HFNMIENA (1 << 1)
#define V7M_MPU_RASR_EN (1 << 0)
#define V7M_MPU_RASR_SIZE_BITS 1
#define V7M_MPU_RASR_SIZE_4GB (31 << V7M_MPU_RASR_SIZE_BITS)
#define V7M_MPU_RASR_AP_RW_RW (3 << 24)
#endif /* !defined(__ASSEMBLY__) */
#endif /* ARMV7M_H */

@ -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

@ -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

@ -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();
}

@ -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)

@ -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
Loading…
Cancel
Save