Improve Cortex-A5 context switching so that a little less copying is done
This commit is contained in:
parent
d6ae8db987
commit
3860fc17f0
9
TODO
9
TODO
@ -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
|
||||
@ -1390,8 +1390,11 @@ o ARM (arch/arm/)
|
||||
Description: ARM interrupt handling performance could be improved in some
|
||||
ways. One easy way is to use a pointer to the context save
|
||||
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
|
||||
Priority: Low
|
||||
|
||||
|
@ -113,6 +113,7 @@ config ARCH_CHIP_SAMA5
|
||||
bool "Atmel AT91SAMA5"
|
||||
select ARCH_CORTEXA5
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_LOWVECTORS
|
||||
---help---
|
||||
Atmel AT91SAMA5 (ARM Cortex-A5)
|
||||
|
||||
|
@ -117,7 +117,7 @@ static bool g_pgwrap;
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_allocpage()
|
||||
* Name: arm_allocpage()
|
||||
*
|
||||
* Description:
|
||||
* 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
|
||||
* 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-
|
||||
* 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()
|
||||
* 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 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]);
|
||||
pte = up_va2pte(oldvaddr);
|
||||
pte = arm_va2pte(oldvaddr);
|
||||
*pte = 0;
|
||||
|
||||
/* 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)
|
||||
*/
|
||||
|
||||
pte = up_va2pte(vaddr);
|
||||
pte = arm_va2pte(vaddr);
|
||||
*pte = (paddr | MMU_L2_ALLOCFLAGS);
|
||||
|
||||
/* And save the new L1 index */
|
||||
|
@ -68,10 +68,10 @@
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_checkmapping()
|
||||
* Name: arm_checkmapping()
|
||||
*
|
||||
* 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
|
||||
* may occur on several threads and be queued multiple times. This function
|
||||
* 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;
|
||||
uint32_t *pte;
|
||||
@ -113,7 +113,7 @@ bool up_checkmapping(FAR struct tcb_s *tcb)
|
||||
|
||||
/* Get the PTE associated with this virtual address */
|
||||
|
||||
pte = up_va2pte(vaddr);
|
||||
pte = arm_va2pte(vaddr);
|
||||
|
||||
/* Return true if this virtual address is mapped. */
|
||||
|
||||
|
@ -71,8 +71,6 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* A little faster than most memcpy's */
|
||||
|
||||
void up_copyarmstate(uint32_t *dest, uint32_t *src)
|
||||
{
|
||||
int i;
|
||||
|
@ -101,7 +101,7 @@
|
||||
|
||||
#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;
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
savestate = (uint32_t*)current_regs;
|
||||
current_regs = regs;
|
||||
|
||||
@ -172,17 +171,18 @@ void arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
|
||||
*/
|
||||
|
||||
current_regs = savestate;
|
||||
return;
|
||||
return regs;
|
||||
|
||||
segfault:
|
||||
lldbg("Data abort. PC: %08x DFAR: %08x DFSR: %08x\n",
|
||||
regs[REG_PC], dfar, dfsr);
|
||||
PANIC();
|
||||
return regs; /* To keep the compiler happy */
|
||||
}
|
||||
|
||||
#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
|
||||
* 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",
|
||||
regs[REG_PC], dfar, dfsr);
|
||||
PANIC();
|
||||
return regs; /* To keep the compiler happy */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PAGING */
|
||||
|
@ -70,7 +70,7 @@
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void up_doirq(int irq, uint32_t *regs)
|
||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
up_ledon(LED_INIRQ);
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
@ -100,22 +100,27 @@ void up_doirq(int irq, uint32_t *regs)
|
||||
* point state before returning from the interrupt.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
if (regs != current_regs)
|
||||
{
|
||||
/* Restore floating point registers */
|
||||
|
||||
up_restorefpu((uint32_t*)current_regs);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
regs = current_regs;
|
||||
current_regs = NULL;
|
||||
|
||||
/* Unmask the last interrupt (global interrupts are still disabled) */
|
||||
|
||||
up_enable_irq(irq);
|
||||
#endif
|
||||
|
||||
up_ledoff(LED_INIRQ);
|
||||
return regs;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@
|
||||
|
||||
#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;
|
||||
|
||||
@ -150,11 +150,13 @@ void arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
|
||||
regs[REG_PC], ifar, ifsr);
|
||||
PANIC();
|
||||
}
|
||||
|
||||
return regs;
|
||||
}
|
||||
|
||||
#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
|
||||
* 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",
|
||||
regs[REG_PC], ifar, ifsr);
|
||||
PANIC();
|
||||
return regs; /* To keep the compiler happy */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PAGING */
|
||||
|
@ -76,19 +76,18 @@
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_syscall
|
||||
* Name: arm_syscall
|
||||
*
|
||||
* Description:
|
||||
* SWI interrupts will vection here with insn=the SWI
|
||||
* instruction and xcp=the interrupt context
|
||||
* SWI interrupts will vection here with insn=the SWI instruction and
|
||||
* xcp=the interrupt context
|
||||
*
|
||||
* The handler may get the SWI number be de-referencing
|
||||
* the return address saved in the xcp and decoding
|
||||
* the SWI instruction
|
||||
* The handler may get the SWI number be de-referencing the return
|
||||
* address saved in the xcp and decoding 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]);
|
||||
current_regs = regs;
|
||||
|
@ -73,9 +73,10 @@
|
||||
* 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]);
|
||||
current_regs = regs;
|
||||
PANIC();
|
||||
return regs; /* To keep the compiler happy */
|
||||
}
|
||||
|
@ -69,7 +69,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_va2pte
|
||||
* Name: arm_va2pte
|
||||
*
|
||||
* Description:
|
||||
* 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 *L2;
|
||||
|
@ -136,20 +136,27 @@ arm_vectorirq:
|
||||
str r0, [sp] /* Save the user stack pointer */
|
||||
mov r4, sp /* Save the SP in a preserved register */
|
||||
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 */
|
||||
#else
|
||||
mov r4, sp /* Save the SP in a preserved register */
|
||||
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 */
|
||||
#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:
|
||||
ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr, r0
|
||||
ldmia sp, {r0-r15}^ /* Return */
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr, r1
|
||||
ldmia r0, {r0-r15}^ /* Return */
|
||||
|
||||
.Lirqtmp:
|
||||
.word g_irqtmp
|
||||
@ -162,7 +169,7 @@ arm_vectorirq:
|
||||
|
||||
/************************************************************************************
|
||||
* Function: arm_vectorswi
|
||||
*
|
||||
*
|
||||
* Description:
|
||||
* SWI interrupt. We enter the SWI in SVC mode.
|
||||
*
|
||||
@ -192,21 +199,27 @@ arm_vectorswi:
|
||||
stmia r0, {r1-r4}
|
||||
|
||||
/* 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 r0, sp /* Get r0=xcp */
|
||||
mov r4, sp /* Save the SP in a preserved register */
|
||||
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 */
|
||||
|
||||
/* 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 */
|
||||
|
||||
ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr, r0
|
||||
ldmia sp, {r0-r15}^ /* Return */
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr, r1
|
||||
ldmia r0, {r0-r15}^ /* Return */
|
||||
.size arm_vectorswi, . - arm_vectorswi
|
||||
|
||||
.align 5
|
||||
@ -275,11 +288,17 @@ arm_vectordata:
|
||||
bl arm_dataabort /* Call the handler */
|
||||
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 */
|
||||
|
||||
ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr_cxsf, r0
|
||||
ldmia sp, {r0-r15}^ /* Return */
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr_cxsf, r1
|
||||
ldmia r0, {r1-r15}^ /* Return */
|
||||
|
||||
.Ldaborttmp:
|
||||
.word g_aborttmp
|
||||
@ -351,11 +370,17 @@ arm_vectorprefetch:
|
||||
bl arm_prefetchabort /* Call the handler */
|
||||
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 */
|
||||
|
||||
ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr_cxsf, r0
|
||||
ldmia sp, {r0-r15}^ /* Return */
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr_cxsf, r1
|
||||
ldmia r0, {r0-r15}^ /* Return */
|
||||
|
||||
.Lpaborttmp:
|
||||
.word g_aborttmp
|
||||
@ -422,11 +447,17 @@ arm_vectorundefinsn:
|
||||
bl arm_undefinedinsn /* Call the handler */
|
||||
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 */
|
||||
|
||||
ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr_cxsf, r0
|
||||
ldmia sp, {r0-r15}^ /* Return */
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
|
||||
msr spsr_cxsf, r1
|
||||
ldmia r0, {r0-r15}^ /* Return */
|
||||
|
||||
.Lundeftmp:
|
||||
.word g_undeftmp
|
||||
|
@ -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
|
||||
* 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;
|
||||
|
@ -134,8 +134,25 @@
|
||||
# endif
|
||||
# define up_restorestate(regs) (current_regs = regs)
|
||||
|
||||
/* Otherwise, for the ARM7, ARM9, and Cortex-A5. The state is copied in full
|
||||
* from stack to stack. This is not very efficient.
|
||||
/* The Cortex-A5 supports the same mechanism, but only lazy floating point
|
||||
* 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
|
||||
@ -289,10 +306,17 @@ void up_systemreset(void) noreturn_function;
|
||||
void up_irqinitialize(void);
|
||||
void up_maskack_irq(int irq);
|
||||
|
||||
/* Exception handling logic unique to the Cortex-M family */
|
||||
|
||||
#if defined(CONFIG_ARCH_CORTEXM0) || defined(CONFIG_ARCH_CORTEXM3) || \
|
||||
defined(CONFIG_ARCH_CORTEXM4)
|
||||
|
||||
/* Interrupt dispatch */
|
||||
|
||||
uint32_t *up_doirq(int irq, uint32_t *regs);
|
||||
|
||||
/* Exception Handlers */
|
||||
|
||||
int up_svcall(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);
|
||||
|
||||
# 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);
|
||||
|
||||
/* Paging support (and exception handlers) */
|
||||
|
||||
#ifdef CONFIG_PAGING
|
||||
void up_pginitialize(void);
|
||||
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()
|
||||
void up_dataabort(uint32_t *regs);
|
||||
#endif /* CONFIG_PAGING */
|
||||
|
||||
/* Exception handlers */
|
||||
|
||||
void up_prefetchabort(uint32_t *regs);
|
||||
void up_syscall(uint32_t *regs);
|
||||
void up_undefinedinsn(uint32_t *regs);
|
||||
|
@ -283,6 +283,7 @@ void up_irqinitialize(void)
|
||||
|
||||
putreg32(AIC_WPMR_WPKEY | AIC_WPMR_WPEN, SAM_AIC_WPMR);
|
||||
|
||||
#ifndef CONFIG_ARCH_LOWVECTORS
|
||||
/* Set remap state 0:
|
||||
*
|
||||
* Boot state: ROM is seen at address 0x00000000
|
||||
@ -290,10 +291,15 @@ void up_irqinitialize(void)
|
||||
* interface) instead of ROM.
|
||||
* Remap State 1: HEBI is seen at address 0x00000000 (through AHB slave
|
||||
* 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(AXIMX_REMAP_REMAP0, SAM_AXIMX_REMAP); /* Remap SRAM */
|
||||
#endif
|
||||
|
||||
/* 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:
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* 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;
|
||||
|
||||
@ -376,11 +382,12 @@ void up_decodeirq(uint32_t *regs)
|
||||
|
||||
/* Dispatch the interrupt */
|
||||
|
||||
up_doirq((int)regval, regs);
|
||||
regs = arm_doirq((int)regval, regs);
|
||||
|
||||
/* Acknowledge interrupt */
|
||||
|
||||
putreg32(AIC_EOICR_ENDIT, SAM_AIC_EOICR);
|
||||
return regs;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -93,6 +93,8 @@ CONFIG_ARCH_CHIP="sama5"
|
||||
CONFIG_ARCH_HAVE_FPU=y
|
||||
CONFIG_ARCH_FPU=y
|
||||
# CONFIG_ARCH_HAVE_MPU is not set
|
||||
CONFIG_ARCH_HAVE_LOWVECTORS=y
|
||||
CONFIG_ARCH_LOWVECTORS=y
|
||||
CONFIG_PGTABLE_VADDR=0x20000000
|
||||
# CONFIG_ARCH_ROMPGTABLE is not set
|
||||
# CONFIG_PAGING is not set
|
||||
|
@ -36,11 +36,14 @@
|
||||
/* 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
|
||||
* 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
|
||||
{
|
||||
isram (W!RX) : ORIGIN = 0x300000, LENGTH = 128K
|
||||
isram (W!RX) : ORIGIN = 0x300000, LENGTH = 128K - 16K
|
||||
sdram (W!RX) : ORIGIN = 0x20000000, LENGTH = 64M
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
isram (W!RX) : ORIGIN = 0x300000, LENGTH = 128K
|
||||
isram (W!RX) : ORIGIN = 0x300000, LENGTH = 128K - 16K
|
||||
}
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
|
@ -60,6 +60,9 @@
|
||||
* 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
|
||||
* 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
|
||||
|
Loading…
Reference in New Issue
Block a user