Finishes coding of ARMv7-M high priority nested interrupt logic. Still undocumented; still not fully tested
This commit is contained in:
parent
7bcfcb2544
commit
5f89b91ad1
@ -6250,7 +6250,11 @@
|
|||||||
autogenerated Documentation/NuttXConfigVariables.html file.
|
autogenerated Documentation/NuttXConfigVariables.html file.
|
||||||
This old configuration variable documentation is now a liability
|
This old configuration variable documentation is now a liability
|
||||||
and, hence, was removed (2013-12-20).
|
and, hence, was removed (2013-12-20).
|
||||||
* nuttx/arch/Kconfig, nuttx/arch/arm/Kconfig, nuttx/arch/arm/include/x/chip.h,
|
* arch/Kconfig, arch/arm/Kconfig, arch/arm/include/x/chip.h, and
|
||||||
and nuttx/arch/arm/src/x/x_irq.c where x={kinetis, lm, lpc17xx, lpc43xx,
|
and arch/arm/src/x/x_irq.c where x={kinetis, lm, lpc17xx, lpc43xx,
|
||||||
sam34, or stm32}: Beginning of support for nested, high priority
|
sam34, or stm32}: Beginning of support for nested, high priority
|
||||||
interrupts. Lots more still needs to be done (2013-12-21).
|
interrupts. Lots more still needs to be done (2013-12-21).
|
||||||
|
* arch/arm/src/armv7-m/up_exception.S and arch/arm/src/x/x_vectors.S:
|
||||||
|
where x={kinetis, lm, lpc17xx, lpc43xx, sam34, or stm32}: completes
|
||||||
|
the basic implementation of nested, high priority interreupts.
|
||||||
|
Still untested and need documentation (2013-12-21).
|
||||||
|
17
arch/Kconfig
17
arch/Kconfig
@ -281,6 +281,23 @@ config ARCH_HIPRI_INTERRUPT
|
|||||||
|
|
||||||
int up_prioritize_irq(int irq, int priority)
|
int up_prioritize_irq(int irq, int priority)
|
||||||
|
|
||||||
|
NOTE: ARCH_INTERRUPTSTACK must be set in kernel mode (NUTTX_KERNEL).
|
||||||
|
In kernel mode without an interrupt stack, the interrupt handler
|
||||||
|
will set the MSP to the stack pointer of the interrupted thread. If
|
||||||
|
the interrupted thread was a privileged thread, that will be the MSP
|
||||||
|
otherwise it will be the PSP. If the PSP is used, then the value of
|
||||||
|
the MSP will be invalid when the interrupt handler returns because
|
||||||
|
it will be a pointer to an old position in the unprivileged stack.
|
||||||
|
Then when the high priority interrupt occurs and uses this stale MSP,
|
||||||
|
there will most likely be a system failure.
|
||||||
|
|
||||||
|
If the interrupt stack is selected, on the other hand, then the
|
||||||
|
interrupt handler will always set the the MSP to the interrupt
|
||||||
|
stack. So when the high priority interrupt occurs, it will either
|
||||||
|
use the MSP of the last privileged thread to run or, in the case of
|
||||||
|
the nested interrupt, the interrupt stack if no privileged task has
|
||||||
|
run
|
||||||
|
|
||||||
config ARCH_INT_DISABLEALL
|
config ARCH_INT_DISABLEALL
|
||||||
bool "Disable high priority interrupts"
|
bool "Disable high priority interrupts"
|
||||||
default y
|
default y
|
||||||
|
@ -45,6 +45,40 @@
|
|||||||
|
|
||||||
#include "chip.h"
|
#include "chip.h"
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
************************************************************************************/
|
||||||
|
/* Configuration ********************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
/* In kernel mode without an interrupt stack, this interrupt handler will set the
|
||||||
|
* MSP to the stack pointer of the interrupted thread. If the interrupted thread
|
||||||
|
* was a privileged thread, that will be the MSP otherwise it will be the PSP. If
|
||||||
|
* the PSP is used, then the value of the MSP will be invalid when the interrupt
|
||||||
|
* handler returns because it will be a pointer to an old position in the
|
||||||
|
* unprivileged stack. Then when the high priority interrupt occurs and uses this
|
||||||
|
* stale MSP, there will most likely be a system failure.
|
||||||
|
*
|
||||||
|
* If the interrupt stack is selected, on the other hand, then the interrupt
|
||||||
|
* handler will always set the the MSP to the interrupt stack. So when the high
|
||||||
|
* priority interrupt occurs, it will either use the MSP of the last privileged
|
||||||
|
* thread to run or, in the case of the nested interrupt, the interrupt stack if
|
||||||
|
* no privileged task has run.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# if defined(CONFIG_NUTTX_KERNEL) && CONFIG_ARCH_INTERRUPTSTACK < 4
|
||||||
|
# error Interrupt stack must be used with high priority interrupts in kernel mode
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Use the the BASEPRI to control interrupts is required if nested, high
|
||||||
|
* priority interrupts are supported.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# ifndef CONFIG_ARMV7M_USEBASEPRI
|
||||||
|
# error CONFIG_ARMV7M_USEBASEPRI must be used with CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Global Symbols
|
* Global Symbols
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
@ -114,8 +148,8 @@ exception_common:
|
|||||||
* as they are restored before returning, so we can't assume that we can get at the
|
* as they are restored before returning, so we can't assume that we can get at the
|
||||||
* true values of these registers in any routine called from here.
|
* true values of these registers in any routine called from here.
|
||||||
*
|
*
|
||||||
* XXX we could do all this saving lazily on the context switch side if we knew where to put
|
* REVISIT: we could do all this saving lazily on the context switch side if we knew
|
||||||
* the registers.
|
* where to put the registers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
vstmdb r1!, {s16-s31} /* Save the non-volatile FP context */
|
vstmdb r1!, {s16-s31} /* Save the non-volatile FP context */
|
||||||
@ -124,23 +158,39 @@ exception_common:
|
|||||||
|
|
||||||
stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP/PRIMASK values */
|
stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP/PRIMASK values */
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
/* Disable interrupts, select the stack to use for interrupt handling
|
/* Disable interrupts, select the stack to use for interrupt handling
|
||||||
* and call up_doirq to handle the interrupt
|
* and call up_doirq to handle the interrupt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cpsid i /* Disable further interrupts */
|
cpsid i /* Disable further interrupts */
|
||||||
|
|
||||||
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt
|
#else
|
||||||
* stack pointer. The way that this is done here prohibits nested interrupts!
|
/* Set the BASEPRI register so that further normal interrupts will be
|
||||||
* Otherwise, we will use the stack that was current when the interrupt was taken.
|
* masked. Nested, high priority may still occur, however.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mov r2, #NVIC_SYSH_DISABLE_PRIORITY
|
||||||
|
msr basepri, r2 /* Set the BASEPRI */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||||
|
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will set the MSP to use
|
||||||
|
* a special special interrupt stack pointer. The way that this is done
|
||||||
|
* here prohibits nested interrupts without some additional logic!
|
||||||
|
*/
|
||||||
|
|
||||||
ldr sp, =g_intstackbase
|
ldr sp, =g_intstackbase
|
||||||
push {r1} /* Save the MSP on the interrupt stack */
|
push {r1} /* Save the MSP on the interrupt stack */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save area on stack */
|
bl up_doirq /* R0=IRQ, R1=register save area on stack */
|
||||||
pop {r1} /* Recover R1=main stack pointer */
|
pop {r1} /* Recover R1=main stack pointer */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
/* Otherwise, we will re-use the interrupted thread's stack. That may
|
||||||
|
* mean using either MSP or PSP stack for interrupt level processing (in
|
||||||
|
* kernel mode).
|
||||||
|
*/
|
||||||
|
|
||||||
msr msp, r1 /* We are using the main stack pointer */
|
msr msp, r1 /* We are using the main stack pointer */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save area on stack */
|
bl up_doirq /* R0=IRQ, R1=register save area on stack */
|
||||||
mrs r1, msp /* Recover R1=main stack pointer */
|
mrs r1, msp /* Recover R1=main stack pointer */
|
||||||
@ -230,7 +280,10 @@ exception_common:
|
|||||||
|
|
||||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||||
msr basepri, r3 /* Restore interrupts priority masking */
|
msr basepri, r3 /* Restore interrupts priority masking */
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
cpsie i /* Re-enable interrupts */
|
cpsie i /* Re-enable interrupts */
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
msr primask, r3 /* Restore interrupts */
|
msr primask, r3 /* Restore interrupts */
|
||||||
#endif
|
#endif
|
||||||
|
@ -47,8 +47,37 @@
|
|||||||
/************************************************************************************************
|
/************************************************************************************************
|
||||||
* Preprocessor Definitions
|
* Preprocessor Definitions
|
||||||
************************************************************************************************/
|
************************************************************************************************/
|
||||||
/* Memory Map:
|
/* Configuration ********************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
/* In kernel mode without an interrupt stack, this interrupt handler will set the MSP to the
|
||||||
|
* stack pointer of the interrupted thread. If the interrupted thread was a privileged
|
||||||
|
* thread, that will be the MSP otherwise it will be the PSP. If the PSP is used, then the
|
||||||
|
* value of the MSP will be invalid when the interrupt handler returns because it will be a
|
||||||
|
* pointer to an old position in the unprivileged stack. Then when the high priority
|
||||||
|
* interrupt occurs and uses this stale MSP, there will most likely be a system failure.
|
||||||
*
|
*
|
||||||
|
* If the interrupt stack is selected, on the other hand, then the interrupt handler will
|
||||||
|
* always set the the MSP to the interrupt stack. So when the high priority interrupt occurs,
|
||||||
|
* it will either use the MSP of the last privileged thread to run or, in the case of the
|
||||||
|
* nested interrupt, the interrupt stack if no privileged task has run.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# if defined(CONFIG_NUTTX_KERNEL) && CONFIG_ARCH_INTERRUPTSTACK < 4
|
||||||
|
# error Interrupt stack must be used with high priority interrupts in kernel mode
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Use the the BASEPRI to control interrupts is required if nested, high
|
||||||
|
* priority interrupts are supported.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# ifndef CONFIG_ARMV7M_USEBASEPRI
|
||||||
|
# error CONFIG_ARMV7M_USEBASEPRI must be used with CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Memory Map ***********************************************************************************/
|
||||||
|
/*
|
||||||
* 0x0000:0000 - Beginning of FLASH. Address of vectors
|
* 0x0000:0000 - Beginning of FLASH. Address of vectors
|
||||||
* 0x1800:0000 - Start of CPU SRAM and start of .data (_sdata)
|
* 0x1800:0000 - Start of CPU SRAM and start of .data (_sdata)
|
||||||
* - End of .data (_edata) and start of .bss (_sbss)
|
* - End of .data (_edata) and start of .bss (_sbss)
|
||||||
@ -637,23 +666,39 @@ kinetis_common:
|
|||||||
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
/* Disable interrupts, select the stack to use for interrupt handling
|
/* Disable interrupts, select the stack to use for interrupt handling
|
||||||
* and call up_doirq to handle the interrupt
|
* and call up_doirq to handle the interrupt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cpsid i /* Disable further interrupts */
|
cpsid i /* Disable further interrupts */
|
||||||
|
|
||||||
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt
|
#else
|
||||||
* stack pointer. The way that this is done here prohibits nested interrupts!
|
/* Set the BASEPRI register so that further normal interrupts will be
|
||||||
* Otherwise, we will re-use the main stack for interrupt level processing.
|
* masked. Nested, high priority may still occur, however.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mov r2, #NVIC_SYSH_DISABLE_PRIORITY
|
||||||
|
msr basepri, r2 /* Set the BASEPRI */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||||
|
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will set the MSP to use
|
||||||
|
* a special special interrupt stack pointer. The way that this is done
|
||||||
|
* here prohibits nested interrupts without some additional logic!
|
||||||
|
*/
|
||||||
|
|
||||||
ldr sp, =g_intstackbase
|
ldr sp, =g_intstackbase
|
||||||
str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
|
str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
||||||
ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
|
ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
/* Otherwise, we will re-use the interrupted thread's stack. That may
|
||||||
|
* mean using either MSP or PSP stack for interrupt level processing (in
|
||||||
|
* kernel mode).
|
||||||
|
*/
|
||||||
|
|
||||||
mov sp, r1 /* We are using the main stack pointer */
|
mov sp, r1 /* We are using the main stack pointer */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
||||||
mov r1, sp /* Recover R1=main stack pointer */
|
mov r1, sp /* Recover R1=main stack pointer */
|
||||||
@ -766,7 +811,10 @@ kinetis_common:
|
|||||||
|
|
||||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||||
msr basepri, r3 /* Restore interrupts priority masking */
|
msr basepri, r3 /* Restore interrupts priority masking */
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
cpsie i /* Re-enable interrupts */
|
cpsie i /* Re-enable interrupts */
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
msr primask, r3 /* Restore interrupts */
|
msr primask, r3 /* Restore interrupts */
|
||||||
#endif
|
#endif
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* arch/arm/src/lm/lm_vectors.S
|
* arch/arm/src/lm/lm_vectors.S
|
||||||
* arch/arm/src/chip/lm_vectors.S
|
* arch/arm/src/chip/lm_vectors.S
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009-2010 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2009-2010, 2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -52,9 +52,39 @@
|
|||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Preprocessor Definitions
|
* Preprocessor Definitions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
/* Configuration ********************************************************************/
|
||||||
|
|
||||||
/* Memory Map:
|
#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
/* In kernel mode without an interrupt stack, this interrupt handler will set the
|
||||||
|
* MSP to the stack pointer of the interrupted thread. If the interrupted thread
|
||||||
|
* was a privileged thread, that will be the MSP otherwise it will be the PSP. If
|
||||||
|
* the PSP is used, then the value of the MSP will be invalid when the interrupt
|
||||||
|
* handler returns because it will be a pointer to an old position in the
|
||||||
|
* unprivileged stack. Then when the high priority interrupt occurs and uses this
|
||||||
|
* stale MSP, there will most likely be a system failure.
|
||||||
*
|
*
|
||||||
|
* If the interrupt stack is selected, on the other hand, then the interrupt
|
||||||
|
* handler will always set the the MSP to the interrupt stack. So when the high
|
||||||
|
* priority interrupt occurs, it will either use the MSP of the last privileged
|
||||||
|
* thread to run or, in the case of the nested interrupt, the interrupt stack if
|
||||||
|
* no privileged task has run.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# if defined(CONFIG_NUTTX_KERNEL) && CONFIG_ARCH_INTERRUPTSTACK < 4
|
||||||
|
# error Interrupt stack must be used with high priority interrupts in kernel mode
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Use the the BASEPRI to control interrupts is required if nested, high
|
||||||
|
* priority interrupts are supported.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# ifndef CONFIG_ARMV7M_USEBASEPRI
|
||||||
|
# error CONFIG_ARMV7M_USEBASEPRI must be used with CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Memory Map ***********************************************************************/
|
||||||
|
/*
|
||||||
* 0x0000:0000 - Beginning of FLASH. Address of vectors (if not using bootloader)
|
* 0x0000:0000 - Beginning of FLASH. Address of vectors (if not using bootloader)
|
||||||
* 0x0002:0000 - Address of vectors if using bootloader
|
* 0x0002:0000 - Address of vectors if using bootloader
|
||||||
* 0x0003:ffff - End of flash
|
* 0x0003:ffff - End of flash
|
||||||
@ -240,23 +270,39 @@ lm_irqcommon:
|
|||||||
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
/* Disable interrupts, select the stack to use for interrupt handling
|
/* Disable interrupts, select the stack to use for interrupt handling
|
||||||
* and call up_doirq to handle the interrupt
|
* and call up_doirq to handle the interrupt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cpsid i /* Disable further interrupts */
|
cpsid i /* Disable further interrupts */
|
||||||
|
|
||||||
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt
|
#else
|
||||||
* stack pointer. The way that this is done here prohibits nested interrupts!
|
/* Set the BASEPRI register so that further normal interrupts will be
|
||||||
* Otherwise, we will re-use the main stack for interrupt level processing.
|
* masked. Nested, high priority may still occur, however.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mov r2, #NVIC_SYSH_DISABLE_PRIORITY
|
||||||
|
msr basepri, r2 /* Set the BASEPRI */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||||
|
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will set the MSP to use
|
||||||
|
* a special special interrupt stack pointer. The way that this is done
|
||||||
|
* here prohibits nested interrupts without some additional logic!
|
||||||
|
*/
|
||||||
|
|
||||||
ldr sp, =g_intstackbase
|
ldr sp, =g_intstackbase
|
||||||
str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
|
str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
||||||
ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
|
ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
/* Otherwise, we will re-use the interrupted thread's stack. That may
|
||||||
|
* mean using either MSP or PSP stack for interrupt level processing (in
|
||||||
|
* kernel mode).
|
||||||
|
*/
|
||||||
|
|
||||||
mov sp, r1 /* We are using the main stack pointer */
|
mov sp, r1 /* We are using the main stack pointer */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
||||||
mov r1, sp /* Recover R1=main stack pointer */
|
mov r1, sp /* Recover R1=main stack pointer */
|
||||||
@ -369,7 +415,10 @@ lm_irqcommon:
|
|||||||
|
|
||||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||||
msr basepri, r3 /* Restore interrupts priority masking */
|
msr basepri, r3 /* Restore interrupts priority masking */
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
cpsie i /* Re-enable interrupts */
|
cpsie i /* Re-enable interrupts */
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
msr primask, r3 /* Restore interrupts */
|
msr primask, r3 /* Restore interrupts */
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,8 +48,37 @@
|
|||||||
/************************************************************************************************
|
/************************************************************************************************
|
||||||
* Preprocessor Definitions
|
* Preprocessor Definitions
|
||||||
************************************************************************************************/
|
************************************************************************************************/
|
||||||
/* Memory Map:
|
/* Configuration ********************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
/* In kernel mode without an interrupt stack, this interrupt handler will set the MSP to the
|
||||||
|
* stack pointer of the interrupted thread. If the interrupted thread was a privileged
|
||||||
|
* thread, that will be the MSP otherwise it will be the PSP. If the PSP is used, then the
|
||||||
|
* value of the MSP will be invalid when the interrupt handler returns because it will be a
|
||||||
|
* pointer to an old position in the unprivileged stack. Then when the high priority
|
||||||
|
* interrupt occurs and uses this stale MSP, there will most likely be a system failure.
|
||||||
*
|
*
|
||||||
|
* If the interrupt stack is selected, on the other hand, then the interrupt handler will
|
||||||
|
* always set the the MSP to the interrupt stack. So when the high priority interrupt occurs,
|
||||||
|
* it will either use the MSP of the last privileged thread to run or, in the case of the
|
||||||
|
* nested interrupt, the interrupt stack if no privileged task has run.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# if defined(CONFIG_NUTTX_KERNEL) && CONFIG_ARCH_INTERRUPTSTACK < 4
|
||||||
|
# error Interrupt stack must be used with high priority interrupts in kernel mode
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Use the the BASEPRI to control interrupts is required if nested, high
|
||||||
|
* priority interrupts are supported.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# ifndef CONFIG_ARMV7M_USEBASEPRI
|
||||||
|
# error CONFIG_ARMV7M_USEBASEPRI must be used with CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Memory Map ***********************************************************************************/
|
||||||
|
/*
|
||||||
* 0x0000:0000 - Beginning of FLASH. Address of vectors
|
* 0x0000:0000 - Beginning of FLASH. Address of vectors
|
||||||
* 0x0003:ffff - End of flash
|
* 0x0003:ffff - End of flash
|
||||||
* 0x1000:0000 - Start of CPU SRAM and start of .data (_sdata)
|
* 0x1000:0000 - Start of CPU SRAM and start of .data (_sdata)
|
||||||
@ -249,23 +278,39 @@ lpc17_common:
|
|||||||
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
/* Disable interrupts, select the stack to use for interrupt handling
|
/* Disable interrupts, select the stack to use for interrupt handling
|
||||||
* and call up_doirq to handle the interrupt
|
* and call up_doirq to handle the interrupt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cpsid i /* Disable further interrupts */
|
cpsid i /* Disable further interrupts */
|
||||||
|
|
||||||
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt
|
#else
|
||||||
* stack pointer. The way that this is done here prohibits nested interrupts!
|
/* Set the BASEPRI register so that further normal interrupts will be
|
||||||
* Otherwise, we will re-use the main stack for interrupt level processing.
|
* masked. Nested, high priority may still occur, however.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mov r2, #NVIC_SYSH_DISABLE_PRIORITY
|
||||||
|
msr basepri, r2 /* Set the BASEPRI */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||||
|
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will set the MSP to use
|
||||||
|
* a special special interrupt stack pointer. The way that this is done
|
||||||
|
* here prohibits nested interrupts without some additional logic!
|
||||||
|
*/
|
||||||
|
|
||||||
ldr sp, =g_intstackbase
|
ldr sp, =g_intstackbase
|
||||||
str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
|
str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
||||||
ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
|
ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
/* Otherwise, we will re-use the interrupted thread's stack. That may
|
||||||
|
* mean using either MSP or PSP stack for interrupt level processing (in
|
||||||
|
* kernel mode).
|
||||||
|
*/
|
||||||
|
|
||||||
mov sp, r1 /* We are using the main stack pointer */
|
mov sp, r1 /* We are using the main stack pointer */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
||||||
mov r1, sp /* Recover R1=main stack pointer */
|
mov r1, sp /* Recover R1=main stack pointer */
|
||||||
@ -378,7 +423,10 @@ lpc17_common:
|
|||||||
|
|
||||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||||
msr basepri, r3 /* Restore interrupts priority masking */
|
msr basepri, r3 /* Restore interrupts priority masking */
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
cpsie i /* Re-enable interrupts */
|
cpsie i /* Re-enable interrupts */
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
msr primask, r3 /* Restore interrupts */
|
msr primask, r3 /* Restore interrupts */
|
||||||
#endif
|
#endif
|
||||||
|
@ -46,9 +46,37 @@
|
|||||||
/************************************************************************************************
|
/************************************************************************************************
|
||||||
* Preprocessor Definitions
|
* Preprocessor Definitions
|
||||||
************************************************************************************************/
|
************************************************************************************************/
|
||||||
|
/* Configuration ********************************************************************************/
|
||||||
|
|
||||||
/* Memory Map:
|
#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
/* In kernel mode without an interrupt stack, this interrupt handler will set the MSP to the
|
||||||
|
* stack pointer of the interrupted thread. If the interrupted thread was a privileged
|
||||||
|
* thread, that will be the MSP otherwise it will be the PSP. If the PSP is used, then the
|
||||||
|
* value of the MSP will be invalid when the interrupt handler returns because it will be a
|
||||||
|
* pointer to an old position in the unprivileged stack. Then when the high priority
|
||||||
|
* interrupt occurs and uses this stale MSP, there will most likely be a system failure.
|
||||||
*
|
*
|
||||||
|
* If the interrupt stack is selected, on the other hand, then the interrupt handler will
|
||||||
|
* always set the the MSP to the interrupt stack. So when the high priority interrupt occurs,
|
||||||
|
* it will either use the MSP of the last privileged thread to run or, in the case of the
|
||||||
|
* nested interrupt, the interrupt stack if no privileged task has run.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# if defined(CONFIG_NUTTX_KERNEL) && CONFIG_ARCH_INTERRUPTSTACK < 4
|
||||||
|
# error Interrupt stack must be used with high priority interrupts in kernel mode
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Use the the BASEPRI to control interrupts is required if nested, high
|
||||||
|
* priority interrupts are supported.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# ifndef CONFIG_ARMV7M_USEBASEPRI
|
||||||
|
# error CONFIG_ARMV7M_USEBASEPRI must be used with CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Memory Map ***********************************************************************************/
|
||||||
|
/*
|
||||||
* 0x0800:0000 - Beginning of FLASH. Address of vectors. Mapped to address 0x0000:0000 at boot
|
* 0x0800:0000 - Beginning of FLASH. Address of vectors. Mapped to address 0x0000:0000 at boot
|
||||||
* time.
|
* time.
|
||||||
* 0x0803:ffff - End of flash
|
* 0x0803:ffff - End of flash
|
||||||
@ -255,23 +283,39 @@ sam_common:
|
|||||||
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
/* Disable interrupts, select the stack to use for interrupt handling
|
/* Disable interrupts, select the stack to use for interrupt handling
|
||||||
* and call up_doirq to handle the interrupt
|
* and call up_doirq to handle the interrupt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cpsid i /* Disable further interrupts */
|
cpsid i /* Disable further interrupts */
|
||||||
|
|
||||||
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt
|
#else
|
||||||
* stack pointer. The way that this is done here prohibits nested interrupts!
|
/* Set the BASEPRI register so that further normal interrupts will be
|
||||||
* Otherwise, we will re-use the main stack for interrupt level processing.
|
* masked. Nested, high priority may still occur, however.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mov r2, #NVIC_SYSH_DISABLE_PRIORITY
|
||||||
|
msr basepri, r2 /* Set the BASEPRI */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||||
|
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will set the MSP to use
|
||||||
|
* a special special interrupt stack pointer. The way that this is done
|
||||||
|
* here prohibits nested interrupts without some additional logic!
|
||||||
|
*/
|
||||||
|
|
||||||
ldr sp, =g_intstackbase
|
ldr sp, =g_intstackbase
|
||||||
str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
|
str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
||||||
ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
|
ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
/* Otherwise, we will re-use the interrupted thread's stack. That may
|
||||||
|
* mean using either MSP or PSP stack for interrupt level processing (in
|
||||||
|
* kernel mode).
|
||||||
|
*/
|
||||||
|
|
||||||
mov sp, r1 /* We are using the main stack pointer */
|
mov sp, r1 /* We are using the main stack pointer */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
||||||
mov r1, sp /* Recover R1=main stack pointer */
|
mov r1, sp /* Recover R1=main stack pointer */
|
||||||
@ -384,7 +428,10 @@ sam_common:
|
|||||||
|
|
||||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||||
msr basepri, r3 /* Restore interrupts priority masking */
|
msr basepri, r3 /* Restore interrupts priority masking */
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
cpsie i /* Re-enable interrupts */
|
cpsie i /* Re-enable interrupts */
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
msr primask, r3 /* Restore interrupts */
|
msr primask, r3 /* Restore interrupts */
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,8 +52,39 @@
|
|||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Preprocessor Definitions
|
* Preprocessor Definitions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
/* Memory Map:
|
/* Configuration ********************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
/* In kernel mode without an interrupt stack, this interrupt handler will set the
|
||||||
|
* MSP to the stack pointer of the interrupted thread. If the interrupted thread
|
||||||
|
* was a privileged thread, that will be the MSP otherwise it will be the PSP. If
|
||||||
|
* the PSP is used, then the value of the MSP will be invalid when the interrupt
|
||||||
|
* handler returns because it will be a pointer to an old position in the
|
||||||
|
* unprivileged stack. Then when the high priority interrupt occurs and uses this
|
||||||
|
* stale MSP, there will most likely be a system failure.
|
||||||
*
|
*
|
||||||
|
* If the interrupt stack is selected, on the other hand, then the interrupt
|
||||||
|
* handler will always set the the MSP to the interrupt stack. So when the high
|
||||||
|
* priority interrupt occurs, it will either use the MSP of the last privileged
|
||||||
|
* thread to run or, in the case of the nested interrupt, the interrupt stack if
|
||||||
|
* no privileged task has run.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# if defined(CONFIG_NUTTX_KERNEL) && CONFIG_ARCH_INTERRUPTSTACK < 4
|
||||||
|
# error Interrupt stack must be used with high priority interrupts in kernel mode
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Use the the BASEPRI to control interrupts is required if nested, high
|
||||||
|
* priority interrupts are supported.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# ifndef CONFIG_ARMV7M_USEBASEPRI
|
||||||
|
# error CONFIG_ARMV7M_USEBASEPRI must be used with CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Memory Map ***********************************************************************/
|
||||||
|
/*
|
||||||
* 0x0800:0000 - Beginning of FLASH. Address of vectors (if not using bootloader)
|
* 0x0800:0000 - Beginning of FLASH. Address of vectors (if not using bootloader)
|
||||||
* Mapped to address 0x0000:0000 at boot time.
|
* Mapped to address 0x0000:0000 at boot time.
|
||||||
* 0x0800:3000 - Address of vectors if using bootloader
|
* 0x0800:3000 - Address of vectors if using bootloader
|
||||||
@ -262,23 +293,39 @@ stm32_common:
|
|||||||
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
stmdb r1!, {r2-r11} /* Save the remaining registers plus the SP value */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
/* Disable interrupts, select the stack to use for interrupt handling
|
/* Disable interrupts, select the stack to use for interrupt handling
|
||||||
* and call up_doirq to handle the interrupt
|
* and call up_doirq to handle the interrupt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cpsid i /* Disable further interrupts */
|
cpsid i /* Disable further interrupts */
|
||||||
|
|
||||||
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt
|
#else
|
||||||
* stack pointer. The way that this is done here prohibits nested interrupts!
|
/* Set the BASEPRI register so that further normal interrupts will be
|
||||||
* Otherwise, we will re-use the main stack for interrupt level processing.
|
* masked. Nested, high priority may still occur, however.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mov r2, #NVIC_SYSH_DISABLE_PRIORITY
|
||||||
|
msr basepri, r2 /* Set the BASEPRI */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||||
|
/* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will set the MSP to use
|
||||||
|
* a special special interrupt stack pointer. The way that this is done
|
||||||
|
* here prohibits nested interrupts without some additional logic!
|
||||||
|
*/
|
||||||
|
|
||||||
ldr sp, =g_intstackbase
|
ldr sp, =g_intstackbase
|
||||||
str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
|
str r1, [sp, #-4]! /* Save the MSP on the interrupt stack */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
||||||
ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
|
ldr r1, [sp, #+4]! /* Recover R1=main stack pointer */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
/* Otherwise, we will re-use the interrupted thread's stack. That may
|
||||||
|
* mean using either MSP or PSP stack for interrupt level processing (in
|
||||||
|
* kernel mode).
|
||||||
|
*/
|
||||||
|
|
||||||
mov sp, r1 /* We are using the main stack pointer */
|
mov sp, r1 /* We are using the main stack pointer */
|
||||||
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
bl up_doirq /* R0=IRQ, R1=register save (msp) */
|
||||||
mov r1, sp /* Recover R1=main stack pointer */
|
mov r1, sp /* Recover R1=main stack pointer */
|
||||||
@ -391,7 +438,10 @@ stm32_common:
|
|||||||
|
|
||||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||||
msr basepri, r3 /* Restore interrupts priority masking */
|
msr basepri, r3 /* Restore interrupts priority masking */
|
||||||
|
#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||||
cpsie i /* Re-enable interrupts */
|
cpsie i /* Re-enable interrupts */
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
msr primask, r3 /* Restore interrupts */
|
msr primask, r3 /* Restore interrupts */
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user