7c02432f0e
In SVC mode, the banked register will be inconsistent with the user mode register: arch/arm/src/armv7-a/arm_vectors.S 276 .globl arm_syscall 277 .globl arm_vectorsvc 278 .type arm_vectorsvc, %function 279 280 arm_vectorsvc: ... 286 sub sp, sp, #XCPTCONTEXT_SIZE // < SVC mode SP ... 308 stmia r0, {r13, r14}^ // < USR mode SP/LR ... [ 2.200000] [ 4] [ ALERT] SYSCALL Entry: regs: 0x80202708 cmd: 4 [ 2.200000] [ 4] [ ALERT] R0: 00000004 80001229 00000001 80202018 00000000 00000000 00000000 802027d0 [ 2.200000] [ 4] [ ALERT] R8: 00000000 00000000 00000000 00000000 00000000 802027d0 1080f710 1080f710 [ 2.200000] [ 4] [ ALERT] CPSR: 00000073 [ 2.200000] [ 4] [ ALERT] SYSCALL Exit: regs: 0x80202708 [ 2.200000] [ 4] [ ALERT] R0: 1 80202018 1 80202018 0 0 0 802027d0 [ 2.200000] [ 4] [ ALERT] R8: 0 0 0 0 0 802027d0 1080f710 80001229 [ 2.200000] [ 4] [ ALERT] CPSR: 00000070 SVC SP is 0x80202708 USR SP is 0x802027d0 0x802027d0 - 0x80202708 should be XCPTCONTEXT_SIZE [ 2.200000] [ 4] [ ALERT] SYSCALL Entry: regs: 0x80202708 cmd: 51 [ 2.200000] [ 4] [ ALERT] R0: 00000033 00000000 80202780 00000000 00000000 00000000 00000000 80202710 [ 2.200000] [ 4] [ ALERT] R8: 00000000 00000000 00000000 00000000 00000000 80202710 800039d5 800039b2 [ 2.200000] [ 4] [ ALERT] CPSR: 00000070 [ 2.200000] [ 4] [ ALERT] SYSCALL Exit: regs: 0x80202708 [ 2.200000] [ 4] [ ALERT] R0: 2b 0 80202780 0 0 0 0 80202710 [ 2.200000] [ 4] [ ALERT] R8: 0 0 0 0 0 10843d80 800039d5 10801425 [ 2.200000] [ 4] [ ALERT] CPSR: 00000073 SVC SP is 0x80202708 USR SP is 0x80202710 SP overlap in SVC and USR mode This commit change the default CPU mode to System and ensure the consistency of SP/LR in USR/SYS mode during syscall. Signed-off-by: chao.an <anchao@xiaomi.com>
214 lines
6.2 KiB
C
214 lines
6.2 KiB
C
/****************************************************************************
|
|
* arch/arm/src/lpc214x/lpc214x_irq.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <stdint.h>
|
|
#include <debug.h>
|
|
#include <nuttx/arch.h>
|
|
|
|
#include "arm.h"
|
|
#include "chip.h"
|
|
#include "arm_internal.h"
|
|
#include "lpc214x_vic.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Public Data
|
|
****************************************************************************/
|
|
|
|
/* g_current_regs[] holds a references to the current interrupt level
|
|
* register storage structure. If is non-NULL only during interrupt
|
|
* processing. Access to g_current_regs[] must be through the macro
|
|
* CURRENT_REGS for portability.
|
|
*/
|
|
|
|
volatile uint32_t *g_current_regs[1];
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: up_irqinitialize
|
|
****************************************************************************/
|
|
|
|
void up_irqinitialize(void)
|
|
{
|
|
int reg;
|
|
|
|
/* Disable all interrupts. We do this by writing zero to the IntEnable
|
|
* register. This is equivalent to writing all ones to the IntClearEnable
|
|
* register.
|
|
*/
|
|
|
|
vic_putreg(0, LPC214X_VIC_INTENABLE_OFFSET);
|
|
|
|
/* Select all IRQs, no FIQs */
|
|
|
|
vic_putreg(0, LPC214X_VIC_INTSELECT_OFFSET);
|
|
|
|
/* Set the default vector */
|
|
|
|
vic_putreg((uint32_t)arm_decodeirq, LPC214X_VIC_DEFVECTADDR_OFFSET);
|
|
|
|
/* Disable all vectored interrupts */
|
|
|
|
for (reg = LPC214X_VIC_VECTCNTL0_OFFSET;
|
|
reg <= LPC214X_VIC_VECTCNTL15_OFFSET;
|
|
reg += 4)
|
|
{
|
|
vic_putreg(0, reg);
|
|
}
|
|
|
|
/* currents_regs is non-NULL only while processing an interrupt */
|
|
|
|
CURRENT_REGS = NULL;
|
|
|
|
/* And finally, enable interrupts */
|
|
|
|
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
|
up_irq_restore(PSR_MODE_SYS | PSR_F_BIT);
|
|
#endif
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: up_disable_irq
|
|
*
|
|
* Description:
|
|
* Disable the IRQ specified by 'irq'
|
|
*
|
|
****************************************************************************/
|
|
|
|
void up_disable_irq(int irq)
|
|
{
|
|
/* Verify that the IRQ number is within range */
|
|
|
|
if (irq < NR_IRQS)
|
|
{
|
|
/* Disable the irq by setting the corresponding bit in the VIC
|
|
* Interrupt Enable Clear register.
|
|
*/
|
|
|
|
vic_putreg((1 << irq), LPC214X_VIC_INTENCLEAR_OFFSET);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: up_enable_irq
|
|
*
|
|
* Description:
|
|
* Enable the IRQ specified by 'irq'
|
|
*
|
|
****************************************************************************/
|
|
|
|
void up_enable_irq(int irq)
|
|
{
|
|
/* Verify that the IRQ number is within range */
|
|
|
|
if (irq < NR_IRQS)
|
|
{
|
|
/* Disable all interrupts */
|
|
|
|
irqstate_t flags = enter_critical_section();
|
|
|
|
/* Enable the irq by setting the corresponding bit in the VIC
|
|
* Interrupt Enable register.
|
|
*/
|
|
|
|
uint32_t val = vic_getreg(LPC214X_VIC_INTENABLE_OFFSET);
|
|
vic_putreg(val | (1 << irq), LPC214X_VIC_INTENABLE_OFFSET);
|
|
leave_critical_section(flags);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: up_attach_vector
|
|
*
|
|
* Description:
|
|
* Attach a user-supplied handler to a vectored interrupt
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifndef CONFIG_VECTORED_INTERRUPTS
|
|
void up_attach_vector(int irq, int vector, vic_vector_t handler)
|
|
{
|
|
/* Verify that the IRQ number and vector number are within range */
|
|
|
|
if (irq < NR_IRQS && vector < 16 && handler)
|
|
{
|
|
int offset = vector << 2;
|
|
|
|
/* Disable all interrupts */
|
|
|
|
irqstate_t flags = enter_critical_section();
|
|
|
|
/* Save the vector address */
|
|
|
|
vic_putreg((uint32_t)handler, LPC214X_VIC_VECTADDR0_OFFSET + offset);
|
|
|
|
/* Enable the vectored interrupt */
|
|
|
|
vic_putreg(((irq << LPC214X_VECTCNTL_IRQSHIFT) |
|
|
LPC214X_VECTCNTL_ENABLE),
|
|
LPC214X_VIC_VECTCNTL0_OFFSET + offset);
|
|
leave_critical_section(flags);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Name: up_detach_vector
|
|
*
|
|
* Description:
|
|
* Detach a user-supplied handler from a vectored interrupt
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifndef CONFIG_VECTORED_INTERRUPTS
|
|
void up_detach_vector(int vector)
|
|
{
|
|
/* Verify that the vector number is within range */
|
|
|
|
if (vector < 16)
|
|
{
|
|
/* Disable the vectored interrupt */
|
|
|
|
int offset = vector << 2;
|
|
vic_putreg(0, LPC214X_VIC_VECTCNTL0_OFFSET + offset);
|
|
}
|
|
}
|
|
#endif
|