Add option for ARM interrupt stack
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@981 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
86bf39f652
commit
2d13668fd9
@ -156,7 +156,15 @@ up_vectorirq:
|
||||
|
||||
mov fp, #0 /* Init frame pointer */
|
||||
mov r1, sp /* Get r1=xcp */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
ldr sp, .Lirqstackbase /* SP = interrupt stack base */
|
||||
str r1, [sp] /* Save the user stack pointer */
|
||||
bl up_doirq /* Call the handler */
|
||||
ldr sp, [sp] /* Restore the user stack pointer */
|
||||
#else
|
||||
bl up_doirq /* Call the handler */
|
||||
#endif
|
||||
|
||||
/* Restore the CPSR, SVC modr registers and return */
|
||||
.Lnoirqset:
|
||||
@ -166,7 +174,10 @@ up_vectorirq:
|
||||
|
||||
.Lirqtmp:
|
||||
.word g_irqtmp
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
.Lirqstackbase:
|
||||
.word up_stackbase
|
||||
#endif
|
||||
.align 5
|
||||
|
||||
/************************************************************************************
|
||||
@ -446,4 +457,26 @@ up_vectorfiq:
|
||||
.type up_vectoraddrexcptn, %function
|
||||
up_vectoraddrexcptn:
|
||||
b up_vectoraddrexcptn
|
||||
|
||||
/************************************************************************************
|
||||
* Name: up_interruptstack/g_userstack
|
||||
*
|
||||
* Description:
|
||||
* Shouldn't happen
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
.bss
|
||||
.align 4
|
||||
.globl g_userstack
|
||||
.type g_userstack, object
|
||||
up_interruptstack:
|
||||
.skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4)
|
||||
g_userstack:
|
||||
up_stackbase:
|
||||
.skip 4
|
||||
.size g_userstack, 4
|
||||
.size up_interruptstack, (CONFIG_ARCH_INTERRUPTSTACK & ~3)
|
||||
#endif
|
||||
.end
|
||||
|
@ -94,50 +94,37 @@ static inline uint32 up_getsp(void)
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void up_stackdump(void)
|
||||
static void up_stackdump(uint32 sp, uint32 stack_base)
|
||||
{
|
||||
_TCB *rtcb = (_TCB*)g_readytorun.head;
|
||||
uint32 sp = up_getsp();
|
||||
uint32 stack_base;
|
||||
uint32 stack_size;
|
||||
uint32 stack ;
|
||||
|
||||
if (rtcb->pid == 0)
|
||||
for (stack = sp & ~0x1f; stack < stack_base; stack += 32)
|
||||
{
|
||||
stack_base = g_heapbase - 4;
|
||||
stack_size = CONFIG_PROC_STACK_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack_base = (uint32)rtcb->adj_stack_ptr;
|
||||
stack_size = (uint32)rtcb->adj_stack_size;
|
||||
uint32 *ptr = (uint32*)stack;
|
||||
lldbg("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define up_stackdump()
|
||||
#endif
|
||||
|
||||
lldbg("stack_base: %08x\n", stack_base);
|
||||
lldbg("stack_size: %08x\n", stack_size);
|
||||
lldbg("sp: %08x\n", sp);
|
||||
/****************************************************************************
|
||||
* Name: up_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
if (sp >= stack_base || sp < stack_base - stack_size)
|
||||
{
|
||||
lldbg("ERROR: Stack pointer is not within allocated stack\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 stack = sp & ~0x1f;
|
||||
|
||||
for (stack = sp & ~0x1f; stack < stack_base; stack += 32)
|
||||
{
|
||||
uint32 *ptr = (uint32*)stack;
|
||||
lldbg("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static inline void up_registerdump(void)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (current_regs)
|
||||
{
|
||||
int regs;
|
||||
|
||||
/* Yes.. dump the interrupt registers */
|
||||
|
||||
for (regs = REG_R0; regs <= REG_R15; regs += 8)
|
||||
{
|
||||
uint32 *ptr = (uint32*)¤t_regs[regs];
|
||||
@ -149,7 +136,101 @@ static void up_stackdump(void)
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define up_stackdump()
|
||||
# define up_registerdump()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void up_dumpstate(void)
|
||||
{
|
||||
_TCB *rtcb = (_TCB*)g_readytorun.head;
|
||||
uint32 sp = up_getsp();
|
||||
uint32 ustackbase;
|
||||
uint32 ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint32 istackbase;
|
||||
uint32 istacksize;
|
||||
#endif
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
if (rtcb->pid == 0)
|
||||
{
|
||||
ustackbase = g_heapbase - 4;
|
||||
ustacksize = CONFIG_PROC_STACK_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ustackbase = (uint32)rtcb->adj_stack_ptr;
|
||||
ustacksize = (uint32)rtcb->adj_stack_size;
|
||||
}
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint32)&g_userstack;
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4;
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
lldbg("sp: %08x\n", sp);
|
||||
lldbg("IRQ stack:\n");
|
||||
lldbg(" base: %08x\n", istackbase);
|
||||
lldbg(" size: %08x\n", istacksize);
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp <= istackbase && sp < istackbase - istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
up_stackdump(sp, istackbase);
|
||||
|
||||
/* Extract the user stack pointer which should lie
|
||||
* at the base of the interrupt stack.
|
||||
*/
|
||||
|
||||
sp = g_userstack;
|
||||
lldbg("sp: %08x\n", sp);
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
lldbg("User stack:\n");
|
||||
lldbg(" base: %08x\n", ustackbase);
|
||||
lldbg(" size: %08x\n", ustacksize);
|
||||
#else
|
||||
lldbg("sp: %08x\n", sp);
|
||||
lldbg("stack base: %08x\n", ustackbase);
|
||||
lldbg("stack size: %08x\n", ustacksize);
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase || sp < ustackbase - ustacksize)
|
||||
{
|
||||
#if !defined(CONFIG_ARCH_INTERRUPTSTACK) || CONFIG_ARCH_INTERRUPTSTACK < 4
|
||||
lldbg("ERROR: Stack pointer is not within allocated stack\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
up_stackdump(sp, ustackbase);
|
||||
}
|
||||
|
||||
/* Then dump the registers (if available) */
|
||||
|
||||
up_registerdump();
|
||||
}
|
||||
#else
|
||||
# define up_dumpstate()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@ -201,7 +282,7 @@ void up_assert(const ubyte *filename, int lineno)
|
||||
lldbg("Assertion failed at file:%s line: %d\n",
|
||||
filename, lineno);
|
||||
#endif
|
||||
up_stackdump();
|
||||
up_dumpstate();
|
||||
_up_assert(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -223,6 +304,6 @@ void up_assert_code(const ubyte *filename, int lineno, int errorcode)
|
||||
lldbg("Assertion failed at file:%s line: %d error code: %d\n",
|
||||
filename, lineno, errorcode);
|
||||
#endif
|
||||
up_stackdump();
|
||||
up_dumpstate();
|
||||
_up_assert(errorcode);
|
||||
}
|
||||
|
@ -65,6 +65,12 @@
|
||||
# define CONFIG_USE_EARLYSERIALINIT 1
|
||||
#endif
|
||||
|
||||
/* Check if an interrupt stack size is configured */
|
||||
|
||||
#ifndef CONFIG_ARCH_INTERRUPTSTACK
|
||||
# define CONFIG_ARCH_INTERRUPTSTACK 0
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
@ -92,6 +98,12 @@ extern uint32 *current_regs;
|
||||
*/
|
||||
|
||||
extern uint32 g_heapbase;
|
||||
|
||||
/* Address of the saved user stack pointer */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
extern uint32 g_userstack;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -128,7 +128,15 @@ up_vectorirq:
|
||||
|
||||
mov fp, #0 /* Init frame pointer */
|
||||
mov r0, sp /* Get r0=xcp */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
ldr sp, .Lirqstackbase /* SP = interrupt stack base */
|
||||
str r0, [sp] /* Save the user stack pointer */
|
||||
bl up_decodeirq /* Call the handler */
|
||||
ldr sp, [sp] /* Restore the user stack pointer */
|
||||
#else
|
||||
bl up_decodeirq /* Call the handler */
|
||||
#endif
|
||||
|
||||
/* Restore the CPSR, SVC modr registers and return */
|
||||
.Lnoirqset:
|
||||
@ -138,8 +146,11 @@ up_vectorirq:
|
||||
|
||||
.Lirqtmp:
|
||||
.word g_irqtmp
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
.Lirqstackbase:
|
||||
.word up_stackbase
|
||||
#endif
|
||||
.size up_vectorirq, . - up_vectorirq
|
||||
|
||||
.align 5
|
||||
|
||||
/************************************************************************************
|
||||
@ -404,4 +415,25 @@ up_vectorfiq:
|
||||
subs pc, lr, #4
|
||||
.size up_vectofiq, . - up_vectorfiq
|
||||
|
||||
.align 5
|
||||
/************************************************************************************
|
||||
* Name: up_interruptstack/g_userstack
|
||||
*
|
||||
* Description:
|
||||
* Shouldn't happen
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
.bss
|
||||
.align 4
|
||||
.globl g_userstack
|
||||
.type g_userstack, object
|
||||
up_interruptstack:
|
||||
.skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4)
|
||||
g_userstack:
|
||||
up_stackbase:
|
||||
.skip 4
|
||||
.size g_userstack, 4
|
||||
.size up_interruptstack, (CONFIG_ARCH_INTERRUPTSTACK & ~3)
|
||||
#endif
|
||||
.end
|
||||
|
Loading…
Reference in New Issue
Block a user