diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fedb3a3afcb..4342c2946c3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -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 diff --git a/arch/arm/src/armv7-a/arm_fullcontextrestore.S b/arch/arm/src/armv7-a/arm_fullcontextrestore.S index f65adbfadb3..af3372b386c 100644 --- a/arch/arm/src/armv7-a/arm_fullcontextrestore.S +++ b/arch/arm/src/armv7-a/arm_fullcontextrestore.S @@ -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 * * Redistribution and use in source and binary forms, with or without @@ -41,6 +41,7 @@ #include #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 diff --git a/arch/arm/src/armv7-a/arm_initialstate.c b/arch/arm/src/armv7-a/arm_initialstate.c index d5888fbcc9b..dedd64ab79a 100644 --- a/arch/arm/src/armv7-a/arm_initialstate.c +++ b/arch/arm/src/armv7-a/arm_initialstate.c @@ -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; } diff --git a/arch/arm/src/armv7-a/arm_saveusercontext.S b/arch/arm/src/armv7-a/arm_saveusercontext.S index 0f75bc8432b..763070a39da 100644 --- a/arch/arm/src/armv7-a/arm_saveusercontext.S +++ b/arch/arm/src/armv7-a/arm_saveusercontext.S @@ -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 diff --git a/arch/arm/src/armv7-a/arm_schedulesigaction.c b/arch/arm/src/armv7-a/arm_schedulesigaction.c index 752ae63667a..1fc7f48c237 100644 --- a/arch/arm/src/armv7-a/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-a/arm_schedulesigaction.c @@ -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 * * 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 } }