From 16f6bb5dc52978b1ef4f6a65ebf0ff2a4a7ed676 Mon Sep 17 00:00:00 2001 From: patacongo Date: Mon, 19 Feb 2007 22:51:18 +0000 Subject: [PATCH] Fix ARM IRQ handling problem + ARM context restore problem git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@9 42af7a65-404d-4744-a932-0658087f49c3 --- arch/c5471/src/Makefile | 2 +- arch/c5471/src/up_createstack.c | 2 +- arch/c5471/src/up_doirq.c | 83 ++++++++++++++++++++++++++ arch/c5471/src/up_fullcontextrestore.S | 8 +-- arch/c5471/src/up_internal.h | 1 + arch/c5471/src/up_irq.c | 44 +++++++------- arch/c5471/src/up_vectors.S | 2 +- 7 files changed, 111 insertions(+), 31 deletions(-) create mode 100644 arch/c5471/src/up_doirq.c diff --git a/arch/c5471/src/Makefile b/arch/c5471/src/Makefile index b75b1daf62..a4f953c6f9 100644 --- a/arch/c5471/src/Makefile +++ b/arch/c5471/src/Makefile @@ -44,7 +44,7 @@ ASRCS += up_lowputc.S endif AOBJS = $(ASRCS:.S=.o) -CSRCS = up_initialize.c up_initialstate.c up_idle.c \ +CSRCS = up_initialize.c up_initialstate.c up_idle.c up_doirq.c \ up_irq.c up_syscall.c up_dataabort.c up_prefetchabort.c \ up_undefinedinsn.c up_interruptcontext.c up_timerisr.c \ up_createstack.c up_usestack.c up_releasestack.c \ diff --git a/arch/c5471/src/up_createstack.c b/arch/c5471/src/up_createstack.c index 20276bff09..90919e265f 100644 --- a/arch/c5471/src/up_createstack.c +++ b/arch/c5471/src/up_createstack.c @@ -116,7 +116,7 @@ STATUS up_create_stack(_TCB *tcb, uint32 stack_size) /* Save the adjusted stack values in the _TCB */ - tcb->adj_stack_size = top_of_stack; + tcb->adj_stack_ptr = (uint32*)top_of_stack; tcb->adj_stack_size = size_of_stack; return OK; diff --git a/arch/c5471/src/up_doirq.c b/arch/c5471/src/up_doirq.c new file mode 100644 index 0000000000..339b285966 --- /dev/null +++ b/arch/c5471/src/up_doirq.c @@ -0,0 +1,83 @@ +/************************************************************ + * up_doirq.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include +#include +#include +#include +#include "c5471.h" +#include "up_internal.h" + +/************************************************************ + * Definitions + ************************************************************/ + +/************************************************************ + * Public Data + ************************************************************/ + +/************************************************************ + * Private Data + ************************************************************/ + +/************************************************************ + * Private Functions + ************************************************************/ + +/************************************************************ + * Public Funtions + ************************************************************/ + +void up_doirq(int irq, uint32* regs) +{ + if ((unsigned)irq < NR_IRQS) + { + /* Mask and acknowledge the interrupt */ + + up_maskack_irq(irq); + + /* Deliver the IRQ */ + + irq_dispatch(irq, regs); + + /* Then unmask it */ + + up_enable_irq(irq); + } +} diff --git a/arch/c5471/src/up_fullcontextrestore.S b/arch/c5471/src/up_fullcontextrestore.S index 572d3c20ca..4d0303ba25 100644 --- a/arch/c5471/src/up_fullcontextrestore.S +++ b/arch/c5471/src/up_fullcontextrestore.S @@ -87,11 +87,11 @@ up_fullcontextrestore: sub sp, sp, #(3*4) /* Frame for three registers */ ldr r1, [r0, #(4*REG_R0)] /* Fetch the stored r0 value */ - str r2, [sp, #8] /* Save it at the top of the stack */ + str r1, [sp] /* Save it at the top of the stack */ ldr r1, [r0, #(4*REG_R1)] /* Fetch the stored r1 value */ - str r2, [sp, #4] /* Save it in the stack */ + str r1, [sp, #4] /* Save it in the stack */ ldr r1, [r0, #(4*REG_PC)] /* Fetch the stored pc value */ - str r2, [sp] /* Save it at the bottom of the stack */ + str r1, [sp, #8] /* Save it at the bottom of the frame */ /* Now we can restore the CPSR. We wait until we are completely * finished with the context save data to do this. Restore the CPSR @@ -104,7 +104,7 @@ up_fullcontextrestore: /* Now recover r0 and r1 */ - ldr r0, [sp, #8] + ldr r0, [sp] ldr r1, [sp, #4] add sp, sp, #(2*4) diff --git a/arch/c5471/src/up_internal.h b/arch/c5471/src/up_internal.h index e11783e023..88ed459f3c 100644 --- a/arch/c5471/src/up_internal.h +++ b/arch/c5471/src/up_internal.h @@ -75,6 +75,7 @@ extern uint32 *current_regs; extern void up_copystate(uint32 *dest, uint32 *src); extern void up_dataabort(uint32 *regs); +extern void up_doirq(int irq, uint32* regs); extern void up_fullcontextrestore(uint32 *regs) __attribute__ ((noreturn)); extern void up_irqinitialize(void); extern void up_prefetchabort(uint32 *regs); diff --git a/arch/c5471/src/up_irq.c b/arch/c5471/src/up_irq.c index d388f6446a..3c8a173712 100644 --- a/arch/c5471/src/up_irq.c +++ b/arch/c5471/src/up_irq.c @@ -48,8 +48,8 @@ * Definitions ************************************************************/ -#define EdgeSensitive 0x00000020 -#define Priority 0x0000001E +#define ILR_EDGESENSITIVE 0x00000020 +#define ILR_PRIORITY 0x0000001E /************************************************************ * Public Data @@ -164,10 +164,10 @@ void up_irqinitialize(void) /* Override hardware defaults */ - putreg32(EdgeSensitive | Priority, ILR_IRQ2_REG); - putreg32(EdgeSensitive | Priority, ILR_IRQ4_REG); - putreg32(Priority, ILR_IRQ6_REG); - putreg32(EdgeSensitive | Priority, ILR_IRQ15_REG); + putreg32(ILR_EDGESENSITIVE | ILR_PRIORITY, ILR_IRQ2_REG); + putreg32(ILR_EDGESENSITIVE | ILR_PRIORITY, ILR_IRQ4_REG); + putreg32(ILR_PRIORITY, ILR_IRQ6_REG); + putreg32(ILR_EDGESENSITIVE | ILR_PRIORITY, ILR_IRQ15_REG); /* Initialize hardware interrupt vectors */ @@ -214,30 +214,26 @@ void up_enable_irq(int irq) } /************************************************************ - * Name: up_acknowledge_irq + * Name: up_maskack_irq * * Description: - * Disable the IRQ specified by 'irq' + * Mask the IRQ and acknowledge it * ************************************************************/ -/* Bit 0 of the Interrupt Control Rigster == New IRQ - * agreement (NEW_IRQ_AGR). Reset IRQ output. Clear source - * IRQ register. Enables a new IRQ generation. Reset by - * internal logic. - * - * IRQ (FIQ) output and SRC_IRQ_REG and SRC_IRQ_BIN_REG - * (SRC_FIQ_REG) registers are reset only if the bit in the - * Interrupt register (IT_REG) corresponding to the interrupt - * having requested MCU action is already cleared or masked. - * - * For an edge-sensitive interrupt, the Interrupt register bit is - * deactivated when reading the SRC_IRQ_REG or SRC_IRQ_BIN_REG - * (SRC_FIQ_REG) registers. - */ - -void up_acknowledge_irq(int irq) +void up_maskack_irq(int irq) { uint32 reg = getreg32(INT_CTRL_REG); + + /* Mask the interrupt */ + + reg = getreg32(MASK_IT_REG); + putreg32(reg | (1 << irq), MASK_IT_REG); + + /* Set the NEW_IRQ_AGR bit. This clears the IRQ src register + * enables generation of a new IRQ. + */ + + reg = getreg32(INT_CTRL_REG); putreg32(reg | 0x00000001, INT_CTRL_REG); /* write the NEW_IRQ_AGR bit. */ } diff --git a/arch/c5471/src/up_vectors.S b/arch/c5471/src/up_vectors.S index b9a4e6d6c4..110fcce693 100644 --- a/arch/c5471/src/up_vectors.S +++ b/arch/c5471/src/up_vectors.S @@ -147,7 +147,7 @@ up_vectorirq: mov fp, #0 /* Init frame pointer */ mov r1, sp /* Get r1=xcp */ - bl up_prefetchabort /* Call the handler */ + bl up_doirq /* Call the handler */ /* Restore the CPSR, SVC modr registers and return */ .Lnoirqset: