Improve Cortex-A5 context switching so that a little less copying is done

This commit is contained in:
Gregory Nutt 2013-07-24 07:47:51 -06:00
parent d6ae8db987
commit 3860fc17f0
19 changed files with 187 additions and 64 deletions

9
TODO
View File

@ -1,4 +1,4 @@
NuttX TODO List (Last updated July 23, 2013) NuttX TODO List (Last updated July 24, 2013)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with This file summarizes known NuttX bugs, limitations, inconsistencies with
@ -1390,8 +1390,11 @@ o ARM (arch/arm/)
Description: ARM interrupt handling performance could be improved in some Description: ARM interrupt handling performance could be improved in some
ways. One easy way is to use a pointer to the context save ways. One easy way is to use a pointer to the context save
area in current_regs instead of using up_copystate so much. area in current_regs instead of using up_copystate so much.
see handling of 'current_regs" in arch/arm/src/armv7-m/* for
examples of how this might be done. This approach is already implemented for the ARM Cortex-M0,
Cortex-M3, Cortex-M4, and Cortex-A5 families. But still needs
to be back-ported to the ARM7 and ARM9 (which are nearly
identical to the Cortex-A5 in this regard).
Status: Open Status: Open
Priority: Low Priority: Low

View File

@ -113,6 +113,7 @@ config ARCH_CHIP_SAMA5
bool "Atmel AT91SAMA5" bool "Atmel AT91SAMA5"
select ARCH_CORTEXA5 select ARCH_CORTEXA5
select ARCH_HAVE_FPU select ARCH_HAVE_FPU
select ARCH_HAVE_LOWVECTORS
---help--- ---help---
Atmel AT91SAMA5 (ARM Cortex-A5) Atmel AT91SAMA5 (ARM Cortex-A5)

View File

@ -117,7 +117,7 @@ static bool g_pgwrap;
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: up_allocpage() * Name: arm_allocpage()
* *
* Description: * Description:
* This architecture-specific function will set aside page in memory and map * This architecture-specific function will set aside page in memory and map
@ -136,9 +136,9 @@ static bool g_pgwrap;
* NOTE 2: If an in-use page is un-mapped, it may be necessary to flush the * NOTE 2: If an in-use page is un-mapped, it may be necessary to flush the
* instruction cache in some architectures. * instruction cache in some architectures.
* *
* NOTE 3: Allocating and filling a page is a two step process. up_allocpage() * NOTE 3: Allocating and filling a page is a two step process. arm_allocpage()
* allocates the page, and up_fillpage() fills it with data from some non- * allocates the page, and up_fillpage() fills it with data from some non-
* volatile storage device. This distinction is made because up_allocpage() * volatile storage device. This distinction is made because arm_allocpage()
* can probably be implemented in board-independent logic whereas up_fillpage() * can probably be implemented in board-independent logic whereas up_fillpage()
* probably must be implemented as board-specific logic. * probably must be implemented as board-specific logic.
* *
@ -165,7 +165,7 @@ static bool g_pgwrap;
* *
****************************************************************************/ ****************************************************************************/
int up_allocpage(FAR struct tcb_s *tcb, FAR void **vpage) int arm_allocpage(FAR struct tcb_s *tcb, FAR void **vpage)
{ {
uintptr_t vaddr; uintptr_t vaddr;
uintptr_t paddr; uintptr_t paddr;
@ -203,7 +203,7 @@ int up_allocpage(FAR struct tcb_s *tcb, FAR void **vpage)
*/ */
uintptr_t oldvaddr = PG_POOL_NDX2VA(g_ptemap[pgndx]); uintptr_t oldvaddr = PG_POOL_NDX2VA(g_ptemap[pgndx]);
pte = up_va2pte(oldvaddr); pte = arm_va2pte(oldvaddr);
*pte = 0; *pte = 0;
/* Invalidate the instruction TLB corresponding to the virtual address */ /* Invalidate the instruction TLB corresponding to the virtual address */
@ -227,7 +227,7 @@ int up_allocpage(FAR struct tcb_s *tcb, FAR void **vpage)
* non-cached (MMU_L2_ALLOCFLAGS) * non-cached (MMU_L2_ALLOCFLAGS)
*/ */
pte = up_va2pte(vaddr); pte = arm_va2pte(vaddr);
*pte = (paddr | MMU_L2_ALLOCFLAGS); *pte = (paddr | MMU_L2_ALLOCFLAGS);
/* And save the new L1 index */ /* And save the new L1 index */

View File

@ -68,10 +68,10 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: up_checkmapping() * Name: arm_checkmapping()
* *
* Description: * Description:
* The function up_checkmapping() returns an indication if the page fill * The function arm_checkmapping() returns an indication if the page fill
* still needs to performed or not. In certain conditions, the page fault * still needs to performed or not. In certain conditions, the page fault
* may occur on several threads and be queued multiple times. This function * may occur on several threads and be queued multiple times. This function
* will prevent the same page from be filled multiple times. * will prevent the same page from be filled multiple times.
@ -97,7 +97,7 @@
* *
****************************************************************************/ ****************************************************************************/
bool up_checkmapping(FAR struct tcb_s *tcb) bool arm_checkmapping(FAR struct tcb_s *tcb)
{ {
uintptr_t vaddr; uintptr_t vaddr;
uint32_t *pte; uint32_t *pte;
@ -113,7 +113,7 @@ bool up_checkmapping(FAR struct tcb_s *tcb)
/* Get the PTE associated with this virtual address */ /* Get the PTE associated with this virtual address */
pte = up_va2pte(vaddr); pte = arm_va2pte(vaddr);
/* Return true if this virtual address is mapped. */ /* Return true if this virtual address is mapped. */

View File

@ -71,8 +71,6 @@
* *
****************************************************************************/ ****************************************************************************/
/* A little faster than most memcpy's */
void up_copyarmstate(uint32_t *dest, uint32_t *src) void up_copyarmstate(uint32_t *dest, uint32_t *src)
{ {
int i; int i;

View File

@ -101,7 +101,7 @@
#ifdef CONFIG_PAGING #ifdef CONFIG_PAGING
void arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr) uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
{ {
DFAR struct tcb_s *tcb = (DFAR struct tcb_s *)g_readytorun.head; DFAR struct tcb_s *tcb = (DFAR struct tcb_s *)g_readytorun.head;
uint32_t *savestate; uint32_t *savestate;
@ -110,7 +110,6 @@ void arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
* for register dumps and possibly context switching. * for register dumps and possibly context switching.
*/ */
savestate = (uint32_t*)current_regs; savestate = (uint32_t*)current_regs;
current_regs = regs; current_regs = regs;
@ -172,17 +171,18 @@ void arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
*/ */
current_regs = savestate; current_regs = savestate;
return; return regs;
segfault: segfault:
lldbg("Data abort. PC: %08x DFAR: %08x DFSR: %08x\n", lldbg("Data abort. PC: %08x DFAR: %08x DFSR: %08x\n",
regs[REG_PC], dfar, dfsr); regs[REG_PC], dfar, dfsr);
PANIC(); PANIC();
return regs; /* To keep the compiler happy */
} }
#else /* CONFIG_PAGING */ #else /* CONFIG_PAGING */
void arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr) uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
{ {
/* Save the saved processor context in current_regs where it can be accessed /* Save the saved processor context in current_regs where it can be accessed
* for register dumps and possibly context switching. * for register dumps and possibly context switching.
@ -195,6 +195,7 @@ void arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
lldbg("Data abort. PC: %08x DFAR: %08x DFSR: %08x\n", lldbg("Data abort. PC: %08x DFAR: %08x DFSR: %08x\n",
regs[REG_PC], dfar, dfsr); regs[REG_PC], dfar, dfsr);
PANIC(); PANIC();
return regs; /* To keep the compiler happy */
} }
#endif /* CONFIG_PAGING */ #endif /* CONFIG_PAGING */

View File

@ -70,7 +70,7 @@
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
void up_doirq(int irq, uint32_t *regs) uint32_t *arm_doirq(int irq, uint32_t *regs)
{ {
up_ledon(LED_INIRQ); up_ledon(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS #ifdef CONFIG_SUPPRESS_INTERRUPTS
@ -100,22 +100,27 @@ void up_doirq(int irq, uint32_t *regs)
* point state before returning from the interrupt. * point state before returning from the interrupt.
*/ */
#ifdef CONFIG_ARCH_FPU
if (regs != current_regs) if (regs != current_regs)
{ {
/* Restore floating point registers */ /* Restore floating point registers */
up_restorefpu((uint32_t*)current_regs); up_restorefpu((uint32_t*)current_regs);
} }
#endif
/* Set current_regs to NULL to indicate that we are no longer in an /* Set current_regs to NULL to indicate that we are no longer in an
* interrupt handler. * interrupt handler.
*/ */
regs = current_regs;
current_regs = NULL; current_regs = NULL;
/* Unmask the last interrupt (global interrupts are still disabled) */ /* Unmask the last interrupt (global interrupts are still disabled) */
up_enable_irq(irq); up_enable_irq(irq);
#endif #endif
up_ledoff(LED_INIRQ); up_ledoff(LED_INIRQ);
return regs;
} }

View File

@ -89,7 +89,7 @@
#ifdef CONFIG_PAGING #ifdef CONFIG_PAGING
void arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr) uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
{ {
uint32_t *savestate; uint32_t *savestate;
@ -150,11 +150,13 @@ void arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
regs[REG_PC], ifar, ifsr); regs[REG_PC], ifar, ifsr);
PANIC(); PANIC();
} }
return regs;
} }
#else /* CONFIG_PAGING */ #else /* CONFIG_PAGING */
void arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr) uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
{ {
/* Save the saved processor context in current_regs where it can be accessed /* Save the saved processor context in current_regs where it can be accessed
* for register dumps and possibly context switching. * for register dumps and possibly context switching.
@ -167,6 +169,7 @@ void arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
lldbg("Prefetch abort. PC: %08x IFAR: %08x IFSR: %08x\n", lldbg("Prefetch abort. PC: %08x IFAR: %08x IFSR: %08x\n",
regs[REG_PC], ifar, ifsr); regs[REG_PC], ifar, ifsr);
PANIC(); PANIC();
return regs; /* To keep the compiler happy */
} }
#endif /* CONFIG_PAGING */ #endif /* CONFIG_PAGING */

View File

@ -76,19 +76,18 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: up_syscall * Name: arm_syscall
* *
* Description: * Description:
* SWI interrupts will vection here with insn=the SWI * SWI interrupts will vection here with insn=the SWI instruction and
* instruction and xcp=the interrupt context * xcp=the interrupt context
* *
* The handler may get the SWI number be de-referencing * The handler may get the SWI number be de-referencing the return
* the return address saved in the xcp and decoding * address saved in the xcp and decoding the SWI instruction
* the SWI instruction
* *
****************************************************************************/ ****************************************************************************/
void up_syscall(uint32_t *regs) uint32_t *arm_syscall(uint32_t *regs)
{ {
lldbg("Syscall from 0x%x\n", regs[REG_PC]); lldbg("Syscall from 0x%x\n", regs[REG_PC]);
current_regs = regs; current_regs = regs;

View File

@ -73,9 +73,10 @@
* Name: arm_undefinedinsn * Name: arm_undefinedinsn
****************************************************************************/ ****************************************************************************/
void arm_undefinedinsn(uint32_t *regs) uint32_t *arm_undefinedinsn(uint32_t *regs)
{ {
lldbg("Undefined instruction at 0x%x\n", regs[REG_PC]); lldbg("Undefined instruction at 0x%x\n", regs[REG_PC]);
current_regs = regs; current_regs = regs;
PANIC(); PANIC();
return regs; /* To keep the compiler happy */
} }

View File

@ -69,7 +69,7 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: up_va2pte * Name: arm_va2pte
* *
* Description: * Description:
* Convert a virtual address within the paged text region into a pointer to * Convert a virtual address within the paged text region into a pointer to
@ -89,7 +89,7 @@
* *
****************************************************************************/ ****************************************************************************/
uint32_t *up_va2pte(uintptr_t vaddr) uint32_t *arm_va2pte(uintptr_t vaddr)
{ {
uint32_t L1; uint32_t L1;
uint32_t *L2; uint32_t *L2;

View File

@ -136,20 +136,27 @@ arm_vectorirq:
str r0, [sp] /* Save the user stack pointer */ str r0, [sp] /* Save the user stack pointer */
mov r4, sp /* Save the SP in a preserved register */ mov r4, sp /* Save the SP in a preserved register */
bic sp, sp, #7 /* Force 8-byte alignement */ bic sp, sp, #7 /* Force 8-byte alignement */
bl up_decodeirq /* Call the handler */ bl arm_decodeirq /* Call the handler */
ldr sp, [r4] /* Restore the user stack pointer */ ldr sp, [r4] /* Restore the user stack pointer */
#else #else
mov r4, sp /* Save the SP in a preserved register */ mov r4, sp /* Save the SP in a preserved register */
bic sp, sp, #7 /* Force 8-byte alignement */ bic sp, sp, #7 /* Force 8-byte alignement */
bl up_decodeirq /* Call the handler */ bl arm_decodeirq /* Call the handler */
mov sp, r4 /* Restore the possibly unaligned stack pointer */ mov sp, r4 /* Restore the possibly unaligned stack pointer */
#endif #endif
/* Restore the CPSR, SVC modr registers and return */ /* Upon return from arm_decodeirq, r0 holds the pointer to the register
* state save area to use to restore the registers. This may or may not
* be the same value that was passed to arm_decodeirq: It will differ if a
* context switch is required.
*/
/* Restore the CPSR, SVC mode registers and return */
.Lnoirqset: .Lnoirqset:
ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
msr spsr, r0 msr spsr, r1
ldmia sp, {r0-r15}^ /* Return */ ldmia r0, {r0-r15}^ /* Return */
.Lirqtmp: .Lirqtmp:
.word g_irqtmp .word g_irqtmp
@ -162,7 +169,7 @@ arm_vectorirq:
/************************************************************************************ /************************************************************************************
* Function: arm_vectorswi * Function: arm_vectorswi
* *
* Description: * Description:
* SWI interrupt. We enter the SWI in SVC mode. * SWI interrupt. We enter the SWI in SVC mode.
* *
@ -192,21 +199,27 @@ arm_vectorswi:
stmia r0, {r1-r4} stmia r0, {r1-r4}
/* Then call the SWI handler with interrupts disabled. /* Then call the SWI handler with interrupts disabled.
* void up_syscall(struct xcptcontext *xcp) * void arm_syscall(struct xcptcontext *xcp)
*/ */
mov fp, #0 /* Init frame pointer */ mov fp, #0 /* Init frame pointer */
mov r0, sp /* Get r0=xcp */ mov r0, sp /* Get r0=xcp */
mov r4, sp /* Save the SP in a preserved register */ mov r4, sp /* Save the SP in a preserved register */
bic sp, sp, #7 /* Force 8-byte alignement */ bic sp, sp, #7 /* Force 8-byte alignement */
bl up_syscall /* Call the handler */ bl arm_syscall /* Call the handler */
mov sp, r4 /* Restore the possibly unaligned stack pointer */ mov sp, r4 /* Restore the possibly unaligned stack pointer */
/* Upon return from arm_syscall, r0 holds the pointer to the register
* state save area to use to restore the registers. This may or may not
* be the same value that was passed to arm_syscall: It will differ if a
* context switch is required.
*/
/* Restore the CPSR, SVC modr registers and return */ /* Restore the CPSR, SVC modr registers and return */
ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
msr spsr, r0 msr spsr, r1
ldmia sp, {r0-r15}^ /* Return */ ldmia r0, {r0-r15}^ /* Return */
.size arm_vectorswi, . - arm_vectorswi .size arm_vectorswi, . - arm_vectorswi
.align 5 .align 5
@ -275,11 +288,17 @@ arm_vectordata:
bl arm_dataabort /* Call the handler */ bl arm_dataabort /* Call the handler */
mov sp, r4 /* Restore the possibly unaligned stack pointer */ mov sp, r4 /* Restore the possibly unaligned stack pointer */
/* Upon return from arm_dataabort, r0 holds the pointer to the register
* state save area to use to restore the registers. This may or may not
* be the same value that was passed to arm_dataabort: It will differ if a
* context switch is required.
*/
/* Restore the CPSR, SVC modr registers and return */ /* Restore the CPSR, SVC modr registers and return */
ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
msr spsr_cxsf, r0 msr spsr_cxsf, r1
ldmia sp, {r0-r15}^ /* Return */ ldmia r0, {r1-r15}^ /* Return */
.Ldaborttmp: .Ldaborttmp:
.word g_aborttmp .word g_aborttmp
@ -351,11 +370,17 @@ arm_vectorprefetch:
bl arm_prefetchabort /* Call the handler */ bl arm_prefetchabort /* Call the handler */
mov sp, r4 /* Restore the possibly unaligned stack pointer */ mov sp, r4 /* Restore the possibly unaligned stack pointer */
/* Upon return from arm_prefetchabort, r0 holds the pointer to the register
* state save area to use to restore the registers. This may or may not
* be the same value that was passed to arm_prefetchabort: It will differ if a
* context switch is required.
*/
/* Restore the CPSR, SVC modr registers and return */ /* Restore the CPSR, SVC modr registers and return */
ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
msr spsr_cxsf, r0 msr spsr_cxsf, r1
ldmia sp, {r0-r15}^ /* Return */ ldmia r0, {r0-r15}^ /* Return */
.Lpaborttmp: .Lpaborttmp:
.word g_aborttmp .word g_aborttmp
@ -422,11 +447,17 @@ arm_vectorundefinsn:
bl arm_undefinedinsn /* Call the handler */ bl arm_undefinedinsn /* Call the handler */
mov sp, r4 /* Restore the possibly unaligned stack pointer */ mov sp, r4 /* Restore the possibly unaligned stack pointer */
/* Upon return from arm_undefinedinsn, r0 holds the pointer to the register
* state save area to use to restore the registers. This may or may not
* be the same value that was passed to arm_undefinedinsn: It will differ if a
* context switch is required.
*/
/* Restore the CPSR, SVC modr registers and return */ /* Restore the CPSR, SVC modr registers and return */
ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
msr spsr_cxsf, r0 msr spsr_cxsf, r1
ldmia sp, {r0-r15}^ /* Return */ ldmia r0, {r0-r15}^ /* Return */
.Lundeftmp: .Lundeftmp:
.word g_undeftmp .word g_undeftmp

View File

@ -99,7 +99,8 @@ void up_copyarmstate(uint32_t *dest, uint32_t *src)
/* Skip over the floating point registers and save the block of ARM /* Skip over the floating point registers and save the block of ARM
* registers that were saved by the hardware when the interrupt was * registers that were saved by the hardware when the interrupt was
* taken. Indices: (SW_INT_REGS+SW_FPU_REGS) through (HW_XCPT_REGS-1) * taken. Indices: (SW_INT_REGS+SW_FPU_REGS) through
* (XCPTCONTEXT_REGS-1)
*/ */
src += SW_FPU_REGS; src += SW_FPU_REGS;

View File

@ -134,8 +134,25 @@
# endif # endif
# define up_restorestate(regs) (current_regs = regs) # define up_restorestate(regs) (current_regs = regs)
/* Otherwise, for the ARM7, ARM9, and Cortex-A5. The state is copied in full /* The Cortex-A5 supports the same mechanism, but only lazy floating point
* from stack to stack. This is not very efficient. * register save/restore.
*/
#elif defined(CONFIG_ARCH_CORTEXA5)
/* If the floating point unit is present and enabled, then save the
* floating point registers as well as normal ARM registers.
*/
# if defined(CONFIG_ARCH_FPU)
# define up_savestate(regs) up_copyarmstate(regs, (uint32_t*)current_regs)
# else
# define up_savestate(regs) up_copyfullstate(regs, (uint32_t*)current_regs)
# endif
# define up_restorestate(regs) (current_regs = regs)
/* Otherwise, for the ARM7 and ARM9. The state is copied in full from stack
* to stack. This is not very efficient and should be fixed to match Cortex-A5.
*/ */
#else #else
@ -289,10 +306,17 @@ void up_systemreset(void) noreturn_function;
void up_irqinitialize(void); void up_irqinitialize(void);
void up_maskack_irq(int irq); void up_maskack_irq(int irq);
/* Exception handling logic unique to the Cortex-M family */
#if defined(CONFIG_ARCH_CORTEXM0) || defined(CONFIG_ARCH_CORTEXM3) || \ #if defined(CONFIG_ARCH_CORTEXM0) || defined(CONFIG_ARCH_CORTEXM3) || \
defined(CONFIG_ARCH_CORTEXM4) defined(CONFIG_ARCH_CORTEXM4)
/* Interrupt dispatch */
uint32_t *up_doirq(int irq, uint32_t *regs); uint32_t *up_doirq(int irq, uint32_t *regs);
/* Exception Handlers */
int up_svcall(int irq, FAR void *context); int up_svcall(int irq, FAR void *context);
int up_hardfault(int irq, FAR void *context); int up_hardfault(int irq, FAR void *context);
@ -301,9 +325,43 @@ int up_hardfault(int irq, FAR void *context);
int up_memfault(int irq, FAR void *context); int up_memfault(int irq, FAR void *context);
# endif /* CONFIG_ARCH_CORTEXM3 || CONFIG_ARCH_CORTEXM4 */ # endif /* CONFIG_ARCH_CORTEXM3 || CONFIG_ARCH_CORTEXM4 */
#else /* CONFIG_ARCH_CORTEXM0 || CONFIG_ARCH_CORTEXM3 || CONFIG_ARCH_CORTEXM4 */
/* Exception handling logic unique to the Cortex-A family (but should be
* back-ported to the ARM7 and ARM9 families).
*/
#elif defined(CONFIG_ARCH_CORTEXA5)
/* Interrupt dispatch */
uint32_t *arm_doirq(int irq, uint32_t *regs);
/* Paging support */
#ifdef CONFIG_PAGING
void arm_pginitialize(void);
uint32_t *arm_va2pte(uintptr_t vaddr);
#else /* CONFIG_PAGING */
# define up_pginitialize()
#endif /* CONFIG_PAGING */
/* Exception Handlers */
uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr);
uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr);
uint32_t *arm_syscall(uint32_t *regs);
uint32_t *arm_undefinedinsn(uint32_t *regs);
/* Exception handling logic common to other ARM7 and ARM9 family. */
#else /* ARM7 | ARM9 */
/* Interrupt dispatch */
void up_doirq(int irq, uint32_t *regs); void up_doirq(int irq, uint32_t *regs);
/* Paging support (and exception handlers) */
#ifdef CONFIG_PAGING #ifdef CONFIG_PAGING
void up_pginitialize(void); void up_pginitialize(void);
uint32_t *up_va2pte(uintptr_t vaddr); uint32_t *up_va2pte(uintptr_t vaddr);
@ -312,6 +370,9 @@ void up_dataabort(uint32_t *regs, uint32_t far, uint32_t fsr);
# define up_pginitialize() # define up_pginitialize()
void up_dataabort(uint32_t *regs); void up_dataabort(uint32_t *regs);
#endif /* CONFIG_PAGING */ #endif /* CONFIG_PAGING */
/* Exception handlers */
void up_prefetchabort(uint32_t *regs); void up_prefetchabort(uint32_t *regs);
void up_syscall(uint32_t *regs); void up_syscall(uint32_t *regs);
void up_undefinedinsn(uint32_t *regs); void up_undefinedinsn(uint32_t *regs);

View File

@ -283,6 +283,7 @@ void up_irqinitialize(void)
putreg32(AIC_WPMR_WPKEY | AIC_WPMR_WPEN, SAM_AIC_WPMR); putreg32(AIC_WPMR_WPKEY | AIC_WPMR_WPEN, SAM_AIC_WPMR);
#ifndef CONFIG_ARCH_LOWVECTORS
/* Set remap state 0: /* Set remap state 0:
* *
* Boot state: ROM is seen at address 0x00000000 * Boot state: ROM is seen at address 0x00000000
@ -290,10 +291,15 @@ void up_irqinitialize(void)
* interface) instead of ROM. * interface) instead of ROM.
* Remap State 1: HEBI is seen at address 0x00000000 (through AHB slave * Remap State 1: HEBI is seen at address 0x00000000 (through AHB slave
* interface) instead of ROM for external boot. * interface) instead of ROM for external boot.
*
* Here we are assuming that vectors reside in the lower end of ISRAM.
* Hmmm... this probably does not matter since we will map a page to
* address 0x0000:0000 in that case anyway.
*/ */
putreg32(MATRIX_MRCR_RCB0, SAM_MATRIX_MRCR); /* Enable remap */ putreg32(MATRIX_MRCR_RCB0, SAM_MATRIX_MRCR); /* Enable remap */
putreg32(AXIMX_REMAP_REMAP0, SAM_AXIMX_REMAP); /* Remap SRAM */ putreg32(AXIMX_REMAP_REMAP0, SAM_AXIMX_REMAP); /* Remap SRAM */
#endif
/* currents_regs is non-NULL only while processing an interrupt */ /* currents_regs is non-NULL only while processing an interrupt */
@ -315,13 +321,13 @@ void up_irqinitialize(void)
} }
/**************************************************************************** /****************************************************************************
* Name: up_decodeirq * Name: arm_decodeirq
* *
* Description: * Description:
* This function is called from the IRQ vector handler in arm_vectors.S. * This function is called from the IRQ vector handler in arm_vectors.S.
* At this point, the interrupt has been taken and the registers have * At this point, the interrupt has been taken and the registers have
* been saved on the stack. This function simply needs to determine the * been saved on the stack. This function simply needs to determine the
* the irq number of the interrupt and then to call up_doirq to dispatch * the irq number of the interrupt and then to call arm_doirq to dispatch
* the interrupt. * the interrupt.
* *
* Input paramters: * Input paramters:
@ -329,7 +335,7 @@ void up_irqinitialize(void)
* *
****************************************************************************/ ****************************************************************************/
void up_decodeirq(uint32_t *regs) uint32_t *arm_decodeirq(uint32_t *regs)
{ {
uint32_t regval; uint32_t regval;
@ -376,11 +382,12 @@ void up_decodeirq(uint32_t *regs)
/* Dispatch the interrupt */ /* Dispatch the interrupt */
up_doirq((int)regval, regs); regs = arm_doirq((int)regval, regs);
/* Acknowledge interrupt */ /* Acknowledge interrupt */
putreg32(AIC_EOICR_ENDIT, SAM_AIC_EOICR); putreg32(AIC_EOICR_ENDIT, SAM_AIC_EOICR);
return regs;
} }
/**************************************************************************** /****************************************************************************

View File

@ -93,6 +93,8 @@ CONFIG_ARCH_CHIP="sama5"
CONFIG_ARCH_HAVE_FPU=y CONFIG_ARCH_HAVE_FPU=y
CONFIG_ARCH_FPU=y CONFIG_ARCH_FPU=y
# CONFIG_ARCH_HAVE_MPU is not set # CONFIG_ARCH_HAVE_MPU is not set
CONFIG_ARCH_HAVE_LOWVECTORS=y
CONFIG_ARCH_LOWVECTORS=y
CONFIG_PGTABLE_VADDR=0x20000000 CONFIG_PGTABLE_VADDR=0x20000000
# CONFIG_ARCH_ROMPGTABLE is not set # CONFIG_ARCH_ROMPGTABLE is not set
# CONFIG_PAGING is not set # CONFIG_PAGING is not set

View File

@ -36,11 +36,14 @@
/* The SAMA5D3 has 128 KB of ISRAM beginning at virtual address 0x0030:0000. /* The SAMA5D3 has 128 KB of ISRAM beginning at virtual address 0x0030:0000.
* This memory configuration, however, loads into the 64 MB SDRAM on board * This memory configuration, however, loads into the 64 MB SDRAM on board
* the SAMA5D3x-EK which lies at 0x2000:0000 * the SAMA5D3x-EK which lies at 0x2000:0000
*
* Vectors in low memory are assumed and 16KB of ISRAM is reserved at the
* high end of ISRAM for the page table.
*/ */
MEMORY MEMORY
{ {
isram (W!RX) : ORIGIN = 0x300000, LENGTH = 128K isram (W!RX) : ORIGIN = 0x300000, LENGTH = 128K - 16K
sdram (W!RX) : ORIGIN = 0x20000000, LENGTH = 64M sdram (W!RX) : ORIGIN = 0x20000000, LENGTH = 64M
} }

View File

@ -33,11 +33,15 @@
* *
****************************************************************************/ ****************************************************************************/
/* The SAMA5D3 has 128 KB of ISRAM beginning at virtual address 0x0030:0000. */ /* The SAMA5D3 has 128 KB of ISRAM beginning at virtual address 0x0030:0000.
*
* Vectors in low memory are assumed and 16KB of ISRAM is reserved at the
* high end of ISRAM for the page table.
*/
MEMORY MEMORY
{ {
isram (W!RX) : ORIGIN = 0x300000, LENGTH = 128K isram (W!RX) : ORIGIN = 0x300000, LENGTH = 128K - 16K
} }
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

View File

@ -60,6 +60,9 @@
* get a link time error saying that the locked region is full, you may have to * get a link time error saying that the locked region is full, you may have to
* re-organize this memory layout (here and in defconfig) to make the locked * re-organize this memory layout (here and in defconfig) to make the locked
* region even bigger. * region even bigger.
*
* NOTE 3: Vectors in low memory are assumed and 16KB of ISRAM is reserved at
* the high end of ISRAM for the page table (?).
*/ */
MEMORY MEMORY