mirror of
https://github.com/apache/nuttx.git
synced 2026-05-19 20:06:24 +08:00
arch/arm/armv7-a: Support thumb mode and fix interworking issue.
This commit is contained in:
+42
-6
@@ -498,9 +498,14 @@ config ARCH_CORTEXM23
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARCH_ARMV7M
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARCH_CORTEXM3
|
||||
bool
|
||||
default n
|
||||
select ARCH_ARMV7M
|
||||
select ARCH_HAVE_IRQPRIO
|
||||
select ARCH_HAVE_IRQTRIGGER
|
||||
select ARCH_HAVE_RAMVECTORS
|
||||
@@ -518,6 +523,7 @@ config ARCH_CORTEXM33
|
||||
config ARCH_CORTEXM4
|
||||
bool
|
||||
default n
|
||||
select ARCH_ARMV7M
|
||||
select ARCH_HAVE_IRQPRIO
|
||||
select ARCH_HAVE_IRQTRIGGER
|
||||
select ARCH_HAVE_RAMVECTORS
|
||||
@@ -531,6 +537,7 @@ config ARCH_CORTEXM4
|
||||
config ARCH_CORTEXM7
|
||||
bool
|
||||
default n
|
||||
select ARCH_ARMV7M
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_IRQPRIO
|
||||
select ARCH_HAVE_IRQTRIGGER
|
||||
@@ -542,9 +549,24 @@ config ARCH_CORTEXM7
|
||||
select ARCH_HAVE_HARDFAULT_DEBUG
|
||||
select ARCH_HAVE_MEMFAULT_DEBUG
|
||||
|
||||
config ARCH_ARMV7A
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARCH_CORTEXA5
|
||||
bool
|
||||
default n
|
||||
select ARCH_ARMV7A
|
||||
select ARCH_DCACHE
|
||||
select ARCH_ICACHE
|
||||
select ARCH_HAVE_MMU
|
||||
select ARCH_USE_MMU
|
||||
select ARCH_HAVE_TESTSET
|
||||
|
||||
config ARCH_CORTEXA7
|
||||
bool
|
||||
default n
|
||||
select ARCH_ARMV7A
|
||||
select ARCH_DCACHE
|
||||
select ARCH_ICACHE
|
||||
select ARCH_HAVE_MMU
|
||||
@@ -554,6 +576,7 @@ config ARCH_CORTEXA5
|
||||
config ARCH_CORTEXA8
|
||||
bool
|
||||
default n
|
||||
select ARCH_ARMV7A
|
||||
select ARCH_DCACHE
|
||||
select ARCH_ICACHE
|
||||
select ARCH_HAVE_MMU
|
||||
@@ -563,15 +586,21 @@ config ARCH_CORTEXA8
|
||||
config ARCH_CORTEXA9
|
||||
bool
|
||||
default n
|
||||
select ARCH_ARMV7A
|
||||
select ARCH_DCACHE
|
||||
select ARCH_ICACHE
|
||||
select ARCH_HAVE_MMU
|
||||
select ARCH_USE_MMU
|
||||
select ARCH_HAVE_TESTSET
|
||||
|
||||
config ARCH_ARMV7R
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARCH_CORTEXR4
|
||||
bool
|
||||
default n
|
||||
select ARCH_ARMV7R
|
||||
select ARCH_DCACHE
|
||||
select ARCH_ICACHE
|
||||
select ARCH_HAVE_MPU
|
||||
@@ -580,6 +609,7 @@ config ARCH_CORTEXR4
|
||||
config ARCH_CORTEXR5
|
||||
bool
|
||||
default n
|
||||
select ARCH_ARMV7R
|
||||
select ARCH_DCACHE
|
||||
select ARCH_ICACHE
|
||||
select ARCH_HAVE_MPU
|
||||
@@ -588,6 +618,7 @@ config ARCH_CORTEXR5
|
||||
config ARCH_CORTEXR7
|
||||
bool
|
||||
default n
|
||||
select ARCH_ARMV7R
|
||||
select ARCH_DCACHE
|
||||
select ARCH_ICACHE
|
||||
select ARCH_HAVE_MPU
|
||||
@@ -597,9 +628,9 @@ config ARCH_FAMILY
|
||||
string
|
||||
default "arm" if ARCH_ARM7TDMI || ARCH_ARM926EJS || ARCH_ARM920T
|
||||
default "armv6-m" if ARCH_CORTEXM0
|
||||
default "armv7-a" if ARCH_CORTEXA5 || ARCH_CORTEXA8 || ARCH_CORTEXA9
|
||||
default "armv7-m" if ARCH_CORTEXM3 || ARCH_CORTEXM4 || ARCH_CORTEXM7
|
||||
default "armv7-r" if ARCH_CORTEXR4 || ARCH_CORTEXR5 || ARCH_CORTEXR7
|
||||
default "armv7-a" if ARCH_ARMV7A
|
||||
default "armv7-m" if ARCH_ARMV7M
|
||||
default "armv7-r" if ARCH_ARMV7R
|
||||
|
||||
config ARCH_CHIP
|
||||
string
|
||||
@@ -665,6 +696,11 @@ config ARCH_TRUSTZONE_BOTH
|
||||
|
||||
endchoice # TrustZone Configuration
|
||||
|
||||
config ARM_THUMB
|
||||
bool
|
||||
default n
|
||||
depends on ARCH_ARMV7A
|
||||
|
||||
config ARM_HAVE_MPU_UNIFIED
|
||||
bool
|
||||
default n
|
||||
@@ -759,13 +795,13 @@ config ARM_SEMIHOSTING_HOSTFS
|
||||
if ARCH_CORTEXM0
|
||||
source arch/arm/src/armv6-m/Kconfig
|
||||
endif
|
||||
if ARCH_CORTEXA5 || ARCH_CORTEXA8 || ARCH_CORTEXA9
|
||||
if ARCH_ARMV7A
|
||||
source arch/arm/src/armv7-a/Kconfig
|
||||
endif
|
||||
if ARCH_CORTEXM3 || ARCH_CORTEXM4 || ARCH_CORTEXM7
|
||||
if ARCH_ARMV7M
|
||||
source arch/arm/src/armv7-m/Kconfig
|
||||
endif
|
||||
if ARCH_CORTEXR4 || ARCH_CORTEXR5 || ARCH_CORTEXR7
|
||||
if ARCH_ARMV7R
|
||||
source arch/arm/src/armv7-r/Kconfig
|
||||
endif
|
||||
if ARCH_ARM7TDMI || ARCH_ARM920T || ARCH_ARM926EJS || ARCH_ARM1136J || ARCH_ARM1156T2 || ARCH_ARM1176JZ
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv7-a/arm_fullcontextrestore.S
|
||||
*
|
||||
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2013, 2019 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include "up_internal.h"
|
||||
#include "svcall.h"
|
||||
#include "arm.h"
|
||||
|
||||
.file "arm_fullcontextrestore.S"
|
||||
|
||||
@@ -120,20 +121,26 @@ up_fullcontextrestore:
|
||||
* a longjmp() all on steriods.
|
||||
*/
|
||||
|
||||
/* Recover all registers except for r0, r1, R15, and CPSR */
|
||||
/* Recover all registers except for r0, r1, r2, R15, and CPSR */
|
||||
|
||||
add r1, r0, #(4*REG_R2) /* Offset to REG_R2 storage */
|
||||
ldmia r1, {r2-r14} /* Recover registers */
|
||||
add r1, r0, #(4*REG_R3) /* Offset to REG_R3 storage */
|
||||
ldmia r1, {r3-r14} /* Recover registers */
|
||||
|
||||
ldr r2, [r0, #(4*REG_CPSR)] /* Fetch the stored CPSR value */
|
||||
|
||||
/* Create a stack frame to hold the some registers */
|
||||
|
||||
sub sp, sp, #(3*4) /* Frame for three registers */
|
||||
sub sp, sp, #(4*4) /* Frame for four registers */
|
||||
ldr r1, [r0, #(4*REG_R0)] /* Fetch the stored r0 value */
|
||||
str r1, [sp] /* Save it at the top of the stack */
|
||||
ldr r1, [r0, #(4*REG_R1)] /* Fetch the stored r1 value */
|
||||
str r1, [sp, #4] /* Save it in the stack */
|
||||
ldr r1, [r0, #(4*REG_R2)] /* Fetch the stored r2 value */
|
||||
str r1, [sp, #8] /* Save it in the stack */
|
||||
ldr r1, [r0, #(4*REG_PC)] /* Fetch the stored pc value */
|
||||
str r1, [sp, #8] /* Save it at the bottom of the frame */
|
||||
tst r2, #PSR_T_BIT
|
||||
orrne r1, r1, #1
|
||||
str r1, [sp, #12] /* 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
|
||||
@@ -142,20 +149,11 @@ up_fullcontextrestore:
|
||||
* disabled.
|
||||
*/
|
||||
|
||||
ldr r1, [r0, #(4*REG_CPSR)] /* Fetch the stored CPSR value */
|
||||
msr cpsr, r1 /* Set the CPSR */
|
||||
msr cpsr, r2 /* Set the CPSR */
|
||||
|
||||
/* Now recover r0 and r1 */
|
||||
/* Now recover r0 r1 r2 and R15 */
|
||||
|
||||
ldr r0, [sp]
|
||||
ldr r1, [sp, #4]
|
||||
add sp, sp, #(2*4)
|
||||
|
||||
/* Then return to the address at the stop of the stack,
|
||||
* destroying the stack frame
|
||||
*/
|
||||
|
||||
ldr pc, [sp], #4
|
||||
pop {r0-r2, pc}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -124,5 +124,9 @@ void up_initial_state(struct tcb_s *tcb)
|
||||
#endif /* !CONFIG_ARMV7A_DECODEFIQ */
|
||||
#endif /* CONFIG_SUPPRESS_INTERRUPTS */
|
||||
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
cpsr |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
xcp->regs[REG_CPSR] = cpsr;
|
||||
}
|
||||
|
||||
@@ -87,12 +87,11 @@ up_saveusercontext:
|
||||
add r1, r0, #(4*REG_CPSR)
|
||||
str r2, [r1]
|
||||
|
||||
/* Save the return address as the PC so that we return to the exit from
|
||||
* this function.
|
||||
*/
|
||||
/* Save the return address */
|
||||
|
||||
ldr r2, =1f
|
||||
add r1, r0, #(4*REG_PC)
|
||||
str lr, [r1]
|
||||
str r2, [r1]
|
||||
|
||||
/* Save the floating point registers.
|
||||
* REVISIT: Not all of the floating point registers need to be saved.
|
||||
@@ -122,5 +121,13 @@ up_saveusercontext:
|
||||
|
||||
mov r0, #0 /* Return value == 0 */
|
||||
mov pc, lr /* Return */
|
||||
|
||||
1:
|
||||
|
||||
/* Return 1 now indicating that this return is a context switch */
|
||||
|
||||
mov r0, #1 /* Return value == 1 */
|
||||
mov pc, lr /* Return */
|
||||
|
||||
.size up_saveusercontext, . - up_saveusercontext
|
||||
.end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv7-a/arm_schedulesigaction.c
|
||||
*
|
||||
* Copyright (C) 2013, 2015-2018 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2013, 2015-2019 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -147,16 +147,19 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* the signals have been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
tcb->xcp.saved_pc = CURRENT_REGS[REG_PC];
|
||||
tcb->xcp.saved_cpsr = CURRENT_REGS[REG_CPSR];
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
tcb->xcp.saved_pc = CURRENT_REGS[REG_PC];
|
||||
tcb->xcp.saved_cpsr = CURRENT_REGS[REG_CPSR];
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)up_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)up_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
/* And make sure that the saved context in the TCB is the same
|
||||
* as the interrupt return context.
|
||||
@@ -178,16 +181,19 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
|
||||
tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR];
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
|
||||
tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR];
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,16 +274,19 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* by the signal trampoline after the signal has been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
|
||||
tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR];
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
|
||||
tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR];
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -289,17 +298,20 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.sigdeliver = (FAR void *)sigdeliver;
|
||||
tcb->xcp.saved_pc = CURRENT_REGS[REG_PC];
|
||||
tcb->xcp.saved_cpsr = CURRENT_REGS[REG_CPSR];
|
||||
tcb->xcp.sigdeliver = (FAR void *)sigdeliver;
|
||||
tcb->xcp.saved_pc = CURRENT_REGS[REG_PC];
|
||||
tcb->xcp.saved_cpsr = CURRENT_REGS[REG_CPSR];
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)up_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)up_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
/* And make sure that the saved context in the TCB is the same
|
||||
* as the interrupt return context.
|
||||
@@ -346,9 +358,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
|
||||
tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR];
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC];
|
||||
tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR];
|
||||
|
||||
/* Increment the IRQ lock count so that when the task is restarted,
|
||||
* it will hold the IRQ spinlock.
|
||||
@@ -361,8 +373,11 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user