arch/arm/armv7-a: Support thumb mode and fix interworking issue.

This commit is contained in:
zhangyuan7
2019-03-19 11:10:41 -06:00
committed by Gregory Nutt
parent 032c7f1ec9
commit 3d171340db
5 changed files with 114 additions and 54 deletions
+42 -6
View File
@@ -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
+16 -18
View File
@@ -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
+4
View File
@@ -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;
}
+11 -4
View File
@@ -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
+41 -26
View File
@@ -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
}
}