diff --git a/ChangeLog b/ChangeLog index b0f4e6b082..3320f5250a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6238,7 +6238,7 @@ * Makefile.unix: Now has supports qconfig and gconfig targets. These tools will use the Qt and GTK versions of the kconfig- frontends configuration tools (if you built them) (2013-12-16) - * arch/arm/src/armv7-a/arm_head.h: Fixe some errors in the cache + * arch/arm/src/armv7-a/arm_head.h: Fix some errors in the cache invalidation logic (only seem to matter for Cortex-A8) (21-3-12-19). * Kconfig and all Make.defs files: Add CONFIG_DEBUG_NOOPT. Now you can indepenently enable/disable debug symbols and optimization @@ -6250,4 +6250,7 @@ autogenerated Documentation/NuttXConfigVariables.html file. This old configuration variable documentation is now a liability and, hence, was removed (2013-12-20). - + * nuttx/arch/Kconfig, nuttx/arch/arm/Kconfig, nuttx/arch/arm/include/x/chip.h, + and nuttx/arch/arm/src/x/x_irq.c where x={kinetis, lm, lpc17xx, lpc43xx, + sam34, or stm32}: Beginning of support for nested, high priority + interrupts. Lots more still needs to be done (2013-12-21). diff --git a/arch/Kconfig b/arch/Kconfig index 9d87a1b33a..e9fc690ab5 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -44,7 +44,7 @@ config ARCH_MIPS config ARCH_RGMP bool "RGMP" ---help--- - RTOS and GPOS on Multi-Processor (RGMP) architecture. See + RTOS and GPOS on Multi-Processor (RGMP) architecture. See http://rgmp.sourceforge.net/wiki/index.php/Main_Page. config ARCH_SH @@ -208,8 +208,11 @@ config ARCH_CALIBRATION watch to measure the actual delay then adjust BOARD_LOOPSPERMSEC until the actual delay is 100 seconds. +comment "Interrupt options" + config ARCH_HAVE_INTERRUPTSTACK bool + default n config ARCH_INTERRUPTSTACK int "Interrupt Stack Size" @@ -221,6 +224,96 @@ config ARCH_INTERRUPTSTACK defined to be zero), the user task stacks will be used during interrupt handling. +config ARCH_HAVE_HIPRI_INTERRUPT + bool + default n + +config ARCH_HIPRI_INTERRUPT + bool "High priority interrupts" + default n + depends on ARCH_HAVE_HIPRI_INTERRUPT && ARCH_HAVE_IRQPRIO + select ARMV7M_USEBASEPRI + select ARCH_IRQPRIO + ---help--- + NOTE: This description is currently unique to the Cortex-M family + which is the only family that currently supports this feature. The + general feature is not conceptually unique to the Cortex-M but it + is extended to any other family, then this discussion will have to + be generalized. + + If ARMV7M_USEBASEPRI is selected, then interrupts will be disabled + by setting the BASEPRI register to NVIC_SYSH_DISABLE_PRIORITY so + that most interrupts will not have execution priority. SVCall must + have execution priority in all cases. + + In the normal cases, interrupts are not nest-able and all interrupts + run at an execution priority between NVIC_SYSH_PRIORITY_MIN and + NVIC_SYSH_PRIORITY_MAX (with NVIC_SYSH_PRIORITY_MAX reserved for + SVCall). + + If, in addition, ARCH_HIPRI_INTERRUPT is defined, then special high + priority interrupts are supported. These are not "nested" in the + normal sense of the word. These high priority interrupts can + interrupt normal processing but execute outside of OS (although they + can "get back into the game" via a PendSV interrupt). + + How do you specify a high priority interrupt? You need to do two + things: + + 1) You need to change the address in the vector table so that + the high priority interrupt vectors to your special C + interrupt handler. There are two ways to do this: + + a) If you select CONFIG_ARCH_RAMVECTORS, then vectors will + be kept in RAM and the system will support the interface: + + int up_ramvec_attach(int irq, up_vector_t vector) + + that can be used to attach your C interrupt handler to the + vector at run time. + + b) Alternatively, you could keep your vectors in FLASH but in + order to this, you would have to develop your own custom + vector table. + + 2) Then set the priority of your interrupt to NVIC to + NVIC_SYSH_HIGH_PRIORITY using the standard interface: + + int up_prioritize_irq(int irq, int priority) + +config ARCH_INT_DISABLEALL + bool "Disable high priority interrupts" + default y + depends on ARCH_HIPRI_INTERRUPT + ---help--- + If ARCH_HIPRI_INTERRUPT is defined, then special high priority + interrupts are supported. These are not "nested" in the normal + sense of the word. These high priority interrupts can interrupt + normal processing but execute outside of OS (although they can "get + back into the game" via a PendSV interrupt). + + In the normal course of things, interrupts must occasionally be + disabled using the irqsave() inline function to prevent contention + in use of resources that may be shared between interrupt level and + non-interrupt level logic. Now the question arises, if + ARCH_HIPRI_INTERRUPT, do we disable all interrupts (except SVCall), + or do we only disable the "normal" interrupts. Since the high + priority interrupts cannot interact with the OS, you may want to + permit the high priority interrupts even if interrupts are + disabled. The setting ARCH_INT_DISABLEALL can be used to select + either behavior: + + ----------------------------+--------------+---------------------------- + CONFIG_ARCH_HIPRI_INTERRUPT | NO | YES + ----------------------------+--------------+--------------+------------- + CONFIG_ARCH_INT_DISABLEALL | N/A | YES | NO + ----------------------------+--------------+--------------+------------- + | | | SVCall + | SVCall | SVCall | HIGH + Disable here and below --------> MAXNORMAL ---> HIGH --------> MAXNORMAL + | | MAXNORMAL | + ----------------------------+--------------+--------------+------------- + comment "Boot options" choice diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2ec96c66b9..0e721697f3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -176,12 +176,14 @@ config ARCH_CORTEXM3 default n select ARCH_HAVE_IRQPRIO select ARCH_HAVE_RAMVECTORS + select ARCH_HAVE_HIPRI_INTERRUPT config ARCH_CORTEXM4 bool default n select ARCH_HAVE_IRQPRIO select ARCH_HAVE_RAMVECTORS + select ARCH_HAVE_HIPRI_INTERRUPT config ARCH_CORTEXA5 bool diff --git a/arch/arm/include/kinetis/chip.h b/arch/arm/include/kinetis/chip.h index cb686c5d62..bd9909050c 100644 --- a/arch/arm/include/kinetis/chip.h +++ b/arch/arm/include/kinetis/chip.h @@ -832,8 +832,54 @@ #define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ #define NVIC_SYSH_PRIORITY_STEP 0x10 /* Steps between supported priority values */ -#define NVIC_SYSH_DISABLE_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) -#define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +/* If CONFIG_ARMV7M_USEBASEPRI is selected, then interrupts will be disabled + * by setting the BASEPRI register to NVIC_SYSH_DISABLE_PRIORITY so that most + * interrupts will not have execution priority. SVCall must have execution + * priority in all cases. + * + * In the normal cases, interrupts are not nest-able and all interrupts run + * at an execution priority between NVIC_SYSH_PRIORITY_MIN and + * NVIC_SYSH_PRIORITY_MAX (with NVIC_SYSH_PRIORITY_MAX reserved for SVCall). + * + * If, in addition, CONFIG_ARCH_HIPRI_INTERRUPT is defined, then special + * high priority interrupts are supported. These are not "nested" in the + * normal sense of the word. These high priority interrupts can interrupt + * normal processing but execute outside of OS (although they can "get back + * into the game" via a PendSV interrupt). + * + * In the normal course of things, interrupts must occasionally be disabled + * using the irqsave() inline function to prevent contention in use of + * resources that may be shared between interrupt level and non-interrupt + * level logic. Now the question arises, if CONFIG_ARCH_HIPRI_INTERRUPT, + * do we disable all interrupts (except SVCall), or do we only disable the + * "normal" interrupts. Since the high priority interrupts cannot interact + * with the OS, you may want to permit the high priority interrupts even if + * interrupts are disabled. The setting CONFIG_ARCH_INT_DISABLEALL can be + * used to select either behavior: + * + * ----------------------------+--------------+---------------------------- + * CONFIG_ARCH_HIPRI_INTERRUPT | NO | YES + * ----------------------------+--------------+--------------+------------- + * CONFIG_ARCH_INT_DISABLEALL | N/A | YES | NO + * ----------------------------+--------------+--------------+------------- + * | | | SVCall + * | SVCall | SVCall | HIGH + * Disable here and below --------> MAXNORMAL ---> HIGH --------> MAXNORMAL + * | | MAXNORMAL | + * ----------------------------+--------------+--------------+------------- + */ + +#if defined(CONFIG_ARCH_HIPRI_INTERRUPT) && defined(CONFIG_ARCH_INT_DISABLEALL) +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + 2*NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_HIGH_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#else +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY NVIC_SYSH_PRIORITY_MAX +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_MAXNORMAL_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#endif /************************************************************************************ * Public Types diff --git a/arch/arm/include/lm/chip.h b/arch/arm/include/lm/chip.h index 86e21c14dd..53ca4d9f0b 100644 --- a/arch/arm/include/lm/chip.h +++ b/arch/arm/include/lm/chip.h @@ -94,7 +94,7 @@ # define LM_NQEI 2 /* Two quadrature encoders */ # define LM_NPORTS 7 /* 7 Ports (GPIOA-G), 0-42 GPIOs */ # define LM_NCANCONTROLLER 0 /* No CAN controllers */ -#elif defined(CONFIG_ARCH_CHIP_LM3S9B96) +#elif defined(CONFIG_ARCH_CHIP_LM3S9B96) # define LM3S 1 /* LM3S family */ # undef LM4F /* Not LM4F family */ # define LM_NTIMERS 4 /* Four general purpose timers */ @@ -153,8 +153,54 @@ #define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ #define NVIC_SYSH_PRIORITY_STEP 0x20 /* Three bits of interrupt priority used */ -#define NVIC_SYSH_DISABLE_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) -#define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +/* If CONFIG_ARMV7M_USEBASEPRI is selected, then interrupts will be disabled + * by setting the BASEPRI register to NVIC_SYSH_DISABLE_PRIORITY so that most + * interrupts will not have execution priority. SVCall must have execution + * priority in all cases. + * + * In the normal cases, interrupts are not nest-able and all interrupts run + * at an execution priority between NVIC_SYSH_PRIORITY_MIN and + * NVIC_SYSH_PRIORITY_MAX (with NVIC_SYSH_PRIORITY_MAX reserved for SVCall). + * + * If, in addition, CONFIG_ARCH_HIPRI_INTERRUPT is defined, then special + * high priority interrupts are supported. These are not "nested" in the + * normal sense of the word. These high priority interrupts can interrupt + * normal processing but execute outside of OS (although they can "get back + * into the game" via a PendSV interrupt). + * + * In the normal course of things, interrupts must occasionally be disabled + * using the irqsave() inline function to prevent contention in use of + * resources that may be shared between interrupt level and non-interrupt + * level logic. Now the question arises, if CONFIG_ARCH_HIPRI_INTERRUPT, + * do we disable all interrupts (except SVCall), or do we only disable the + * "normal" interrupts. Since the high priority interrupts cannot interact + * with the OS, you may want to permit the high priority interrupts even if + * interrupts are disabled. The setting CONFIG_ARCH_INT_DISABLEALL can be + * used to select either behavior: + * + * ----------------------------+--------------+---------------------------- + * CONFIG_ARCH_HIPRI_INTERRUPT | NO | YES + * ----------------------------+--------------+--------------+------------- + * CONFIG_ARCH_INT_DISABLEALL | N/A | YES | NO + * ----------------------------+--------------+--------------+------------- + * | | | SVCall + * | SVCall | SVCall | HIGH + * Disable here and below --------> MAXNORMAL ---> HIGH --------> MAXNORMAL + * | | MAXNORMAL | + * ----------------------------+--------------+--------------+------------- + */ + +#if defined(CONFIG_ARCH_HIPRI_INTERRUPT) && defined(CONFIG_ARCH_INT_DISABLEALL) +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + 2*NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_HIGH_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#else +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY NVIC_SYSH_PRIORITY_MAX +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_MAXNORMAL_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#endif /************************************************************************************ * Public Types diff --git a/arch/arm/include/lpc17xx/chip.h b/arch/arm/include/lpc17xx/chip.h index 3880268c9d..f03785e19a 100644 --- a/arch/arm/include/lpc17xx/chip.h +++ b/arch/arm/include/lpc17xx/chip.h @@ -1,7 +1,7 @@ /************************************************************************************ * arch/arm/include/lpc17xx/chip.h * - * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2010-2011, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * with LPC178x support from Rommel Marcelo * @@ -373,8 +373,54 @@ #define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ #define NVIC_SYSH_PRIORITY_STEP 0x08 /* Five bits of interrupt priority used */ -#define NVIC_SYSH_DISABLE_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) -#define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +/* If CONFIG_ARMV7M_USEBASEPRI is selected, then interrupts will be disabled + * by setting the BASEPRI register to NVIC_SYSH_DISABLE_PRIORITY so that most + * interrupts will not have execution priority. SVCall must have execution + * priority in all cases. + * + * In the normal cases, interrupts are not nest-able and all interrupts run + * at an execution priority between NVIC_SYSH_PRIORITY_MIN and + * NVIC_SYSH_PRIORITY_MAX (with NVIC_SYSH_PRIORITY_MAX reserved for SVCall). + * + * If, in addition, CONFIG_ARCH_HIPRI_INTERRUPT is defined, then special + * high priority interrupts are supported. These are not "nested" in the + * normal sense of the word. These high priority interrupts can interrupt + * normal processing but execute outside of OS (although they can "get back + * into the game" via a PendSV interrupt). + * + * In the normal course of things, interrupts must occasionally be disabled + * using the irqsave() inline function to prevent contention in use of + * resources that may be shared between interrupt level and non-interrupt + * level logic. Now the question arises, if CONFIG_ARCH_HIPRI_INTERRUPT, + * do we disable all interrupts (except SVCall), or do we only disable the + * "normal" interrupts. Since the high priority interrupts cannot interact + * with the OS, you may want to permit the high priority interrupts even if + * interrupts are disabled. The setting CONFIG_ARCH_INT_DISABLEALL can be + * used to select either behavior: + * + * ----------------------------+--------------+---------------------------- + * CONFIG_ARCH_HIPRI_INTERRUPT | NO | YES + * ----------------------------+--------------+--------------+------------- + * CONFIG_ARCH_INT_DISABLEALL | N/A | YES | NO + * ----------------------------+--------------+--------------+------------- + * | | | SVCall + * | SVCall | SVCall | HIGH + * Disable here and below --------> MAXNORMAL ---> HIGH --------> MAXNORMAL + * | | MAXNORMAL | + * ----------------------------+--------------+--------------+------------- + */ + +#if defined(CONFIG_ARCH_HIPRI_INTERRUPT) && defined(CONFIG_ARCH_INT_DISABLEALL) +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + 2*NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_HIGH_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#else +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY NVIC_SYSH_PRIORITY_MAX +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_MAXNORMAL_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#endif /************************************************************************************ * Public Types diff --git a/arch/arm/include/lpc43xx/chip.h b/arch/arm/include/lpc43xx/chip.h index 7ff787e489..6168672ea8 100644 --- a/arch/arm/include/lpc43xx/chip.h +++ b/arch/arm/include/lpc43xx/chip.h @@ -568,8 +568,54 @@ #define NVIC_SYSH_PRIORITY_MAX LPC43M4_SYSH_PRIORITY_MAX #define NVIC_SYSH_PRIORITY_STEP LPC43M4_SYSH_PRIORITY_INCR -#define NVIC_SYSH_DISABLE_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) -#define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +/* If CONFIG_ARMV7M_USEBASEPRI is selected, then interrupts will be disabled + * by setting the BASEPRI register to NVIC_SYSH_DISABLE_PRIORITY so that most + * interrupts will not have execution priority. SVCall must have execution + * priority in all cases. + * + * In the normal cases, interrupts are not nest-able and all interrupts run + * at an execution priority between NVIC_SYSH_PRIORITY_MIN and + * NVIC_SYSH_PRIORITY_MAX (with NVIC_SYSH_PRIORITY_MAX reserved for SVCall). + * + * If, in addition, CONFIG_ARCH_HIPRI_INTERRUPT is defined, then special + * high priority interrupts are supported. These are not "nested" in the + * normal sense of the word. These high priority interrupts can interrupt + * normal processing but execute outside of OS (although they can "get back + * into the game" via a PendSV interrupt). + * + * In the normal course of things, interrupts must occasionally be disabled + * using the irqsave() inline function to prevent contention in use of + * resources that may be shared between interrupt level and non-interrupt + * level logic. Now the question arises, if CONFIG_ARCH_HIPRI_INTERRUPT, + * do we disable all interrupts (except SVCall), or do we only disable the + * "normal" interrupts. Since the high priority interrupts cannot interact + * with the OS, you may want to permit the high priority interrupts even if + * interrupts are disabled. The setting CONFIG_ARCH_INT_DISABLEALL can be + * used to select either behavior: + * + * ----------------------------+--------------+---------------------------- + * CONFIG_ARCH_HIPRI_INTERRUPT | NO | YES + * ----------------------------+--------------+--------------+------------- + * CONFIG_ARCH_INT_DISABLEALL | N/A | YES | NO + * ----------------------------+--------------+--------------+------------- + * | | | SVCall + * | SVCall | SVCall | HIGH + * Disable here and below --------> MAXNORMAL ---> HIGH --------> MAXNORMAL + * | | MAXNORMAL | + * ----------------------------+--------------+--------------+------------- + */ + +#if defined(CONFIG_ARCH_HIPRI_INTERRUPT) && defined(CONFIG_ARCH_INT_DISABLEALL) +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + 2*NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_HIGH_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#else +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY NVIC_SYSH_PRIORITY_MAX +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_MAXNORMAL_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#endif /************************************************************************************ * Public Types diff --git a/arch/arm/include/sam34/chip.h b/arch/arm/include/sam34/chip.h index 27b4a9231c..0e63fd4b5f 100644 --- a/arch/arm/include/sam34/chip.h +++ b/arch/arm/include/sam34/chip.h @@ -806,8 +806,54 @@ #define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ #define NVIC_SYSH_PRIORITY_STEP 0x10 /* Four bits of interrupt priority used */ -#define NVIC_SYSH_DISABLE_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) -#define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +/* If CONFIG_ARMV7M_USEBASEPRI is selected, then interrupts will be disabled + * by setting the BASEPRI register to NVIC_SYSH_DISABLE_PRIORITY so that most + * interrupts will not have execution priority. SVCall must have execution + * priority in all cases. + * + * In the normal cases, interrupts are not nest-able and all interrupts run + * at an execution priority between NVIC_SYSH_PRIORITY_MIN and + * NVIC_SYSH_PRIORITY_MAX (with NVIC_SYSH_PRIORITY_MAX reserved for SVCall). + * + * If, in addition, CONFIG_ARCH_HIPRI_INTERRUPT is defined, then special + * high priority interrupts are supported. These are not "nested" in the + * normal sense of the word. These high priority interrupts can interrupt + * normal processing but execute outside of OS (although they can "get back + * into the game" via a PendSV interrupt). + * + * In the normal course of things, interrupts must occasionally be disabled + * using the irqsave() inline function to prevent contention in use of + * resources that may be shared between interrupt level and non-interrupt + * level logic. Now the question arises, if CONFIG_ARCH_HIPRI_INTERRUPT, + * do we disable all interrupts (except SVCall), or do we only disable the + * "normal" interrupts. Since the high priority interrupts cannot interact + * with the OS, you may want to permit the high priority interrupts even if + * interrupts are disabled. The setting CONFIG_ARCH_INT_DISABLEALL can be + * used to select either behavior: + * + * ----------------------------+--------------+---------------------------- + * CONFIG_ARCH_HIPRI_INTERRUPT | NO | YES + * ----------------------------+--------------+--------------+------------- + * CONFIG_ARCH_INT_DISABLEALL | N/A | YES | NO + * ----------------------------+--------------+--------------+------------- + * | | | SVCall + * | SVCall | SVCall | HIGH + * Disable here and below --------> MAXNORMAL ---> HIGH --------> MAXNORMAL + * | | MAXNORMAL | + * ----------------------------+--------------+--------------+------------- + */ + +#if defined(CONFIG_ARCH_HIPRI_INTERRUPT) && defined(CONFIG_ARCH_INT_DISABLEALL) +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + 2*NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_HIGH_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#else +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY NVIC_SYSH_PRIORITY_MAX +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_MAXNORMAL_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#endif /************************************************************************************ * Public Types diff --git a/arch/arm/include/stm32/chip.h b/arch/arm/include/stm32/chip.h index 240796a030..12fb73f7c7 100644 --- a/arch/arm/include/stm32/chip.h +++ b/arch/arm/include/stm32/chip.h @@ -1,7 +1,7 @@ /************************************************************************************ * arch/arm/include/stm32/chip.h * - * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -1636,8 +1636,54 @@ #define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ #define NVIC_SYSH_PRIORITY_STEP 0x10 /* Four bits of interrupt priority used */ -#define NVIC_SYSH_DISABLE_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) -#define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +/* If CONFIG_ARMV7M_USEBASEPRI is selected, then interrupts will be disabled + * by setting the BASEPRI register to NVIC_SYSH_DISABLE_PRIORITY so that most + * interrupts will not have execution priority. SVCall must have execution + * priority in all cases. + * + * In the normal cases, interrupts are not nest-able and all interrupts run + * at an execution priority between NVIC_SYSH_PRIORITY_MIN and + * NVIC_SYSH_PRIORITY_MAX (with NVIC_SYSH_PRIORITY_MAX reserved for SVCall). + * + * If, in addition, CONFIG_ARCH_HIPRI_INTERRUPT is defined, then special + * high priority interrupts are supported. These are not "nested" in the + * normal sense of the word. These high priority interrupts can interrupt + * normal processing but execute outside of OS (although they can "get back + * into the game" via a PendSV interrupt). + * + * In the normal course of things, interrupts must occasionally be disabled + * using the irqsave() inline function to prevent contention in use of + * resources that may be shared between interrupt level and non-interrupt + * level logic. Now the question arises, if CONFIG_ARCH_HIPRI_INTERRUPT, + * do we disable all interrupts (except SVCall), or do we only disable the + * "normal" interrupts. Since the high priority interrupts cannot interact + * with the OS, you may want to permit the high priority interrupts even if + * interrupts are disabled. The setting CONFIG_ARCH_INT_DISABLEALL can be + * used to select either behavior: + * + * ----------------------------+--------------+---------------------------- + * CONFIG_ARCH_HIPRI_INTERRUPT | NO | YES + * ----------------------------+--------------+--------------+------------- + * CONFIG_ARCH_INT_DISABLEALL | N/A | YES | NO + * ----------------------------+--------------+--------------+------------- + * | | | SVCall + * | SVCall | SVCall | HIGH + * Disable here and below --------> MAXNORMAL ---> HIGH --------> MAXNORMAL + * | | MAXNORMAL | + * ----------------------------+--------------+--------------+------------- + */ + +#if defined(CONFIG_ARCH_HIPRI_INTERRUPT) && defined(CONFIG_ARCH_INT_DISABLEALL) +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + 2*NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_HIGH_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#else +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY NVIC_SYSH_PRIORITY_MAX +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_MAXNORMAL_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#endif #endif /* __ARCH_ARM_INCLUDE_STM32_CHIP_H */ diff --git a/arch/arm/src/armv7-m/up_initialstate.c b/arch/arm/src/armv7-m/up_initialstate.c index c19d32f116..7b6eb30420 100644 --- a/arch/arm/src/armv7-m/up_initialstate.c +++ b/arch/arm/src/armv7-m/up_initialstate.c @@ -96,7 +96,7 @@ void up_initial_state(struct tcb_s *tcb) /* Save the task entry point (stripping off the thumb bit) */ xcp->regs[REG_PC] = (uint32_t)tcb->start & ~1; - + /* Specify thumb mode */ xcp->regs[REG_XPSR] = ARMV7M_XPSR_T; diff --git a/arch/arm/src/kinetis/kinetis_irq.c b/arch/arm/src/kinetis/kinetis_irq.c index bf4585d9b0..5deda2a16d 100644 --- a/arch/arm/src/kinetis/kinetis_irq.c +++ b/arch/arm/src/kinetis/kinetis_irq.c @@ -512,14 +512,8 @@ int up_prioritize_irq(int irq, int priority) uint32_t regval; int shift; -#ifdef CONFIG_ARMV7M_USEBASEPRI - DEBUGASSERT(irq >= KINETIS_IRQ_MEMFAULT && irq < NR_IRQS && - priority >= NVIC_SYSH_DISABLE_PRIORITY && - priority <= NVIC_SYSH_PRIORITY_MIN); -#else DEBUGASSERT(irq >= KINETIS_IRQ_MEMFAULT && irq < NR_IRQS && (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); -#endif if (irq < KINETIS_IRQ_EXTINT) { diff --git a/arch/arm/src/lm/lm_irq.c b/arch/arm/src/lm/lm_irq.c index 8d7997a13f..0ef8d21975 100644 --- a/arch/arm/src/lm/lm_irq.c +++ b/arch/arm/src/lm/lm_irq.c @@ -461,14 +461,8 @@ int up_prioritize_irq(int irq, int priority) uint32_t regval; int shift; -#ifdef CONFIG_ARMV7M_USEBASEPRI DEBUGASSERT(irq >= LM_IRQ_MEMFAULT && irq < NR_IRQS && - priority >= NVIC_SYSH_DISABLE_PRIORITY && - priority <= NVIC_SYSH_PRIORITY_MIN); -#else - DEBUGASSERT(irq >= LM_IRQ_MEMFAULT && irq < NR_IRQS && - (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); -#endif + (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); if (irq < LM_IRQ_INTERRUPTS) { diff --git a/arch/arm/src/lpc17xx/lpc17_irq.c b/arch/arm/src/lpc17xx/lpc17_irq.c index 8ab0a94d0e..840574fab7 100644 --- a/arch/arm/src/lpc17xx/lpc17_irq.c +++ b/arch/arm/src/lpc17xx/lpc17_irq.c @@ -475,14 +475,8 @@ int up_prioritize_irq(int irq, int priority) uint32_t regval; int shift; -#ifdef CONFIG_ARMV7M_USEBASEPRI - DEBUGASSERT(irq >= LPC17_IRQ_MEMFAULT && irq < LPC17_IRQ_NIRQS && - priority >= NVIC_SYSH_DISABLE_PRIORITY && - priority <= NVIC_SYSH_PRIORITY_MIN); -#else DEBUGASSERT(irq >= LPC17_IRQ_MEMFAULT && irq < LPC17_IRQ_NIRQS && (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); -#endif if (irq < LPC17_IRQ_EXTINT) { diff --git a/arch/arm/src/lpc43xx/lpc43_irq.c b/arch/arm/src/lpc43xx/lpc43_irq.c index fb316e0d2e..779a9c50c4 100644 --- a/arch/arm/src/lpc43xx/lpc43_irq.c +++ b/arch/arm/src/lpc43xx/lpc43_irq.c @@ -513,14 +513,8 @@ int up_prioritize_irq(int irq, int priority) uint32_t regval; int shift; -#ifdef CONFIG_ARMV7M_USEBASEPRI DEBUGASSERT(irq >= LPC43_IRQ_MEMFAULT && irq < NR_IRQS && - priority >= NVIC_SYSH_DISABLE_PRIORITY && - priority <= NVIC_SYSH_PRIORITY_MIN); -#else - DEBUGASSERT(irq >= LPC43_IRQ_MEMFAULT && irq < NR_IRQS && - (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); -#endif + (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); if (irq < LPC43_IRQ_EXTINT) { diff --git a/arch/arm/src/sam34/sam_irq.c b/arch/arm/src/sam34/sam_irq.c index 3ffe4d3f9d..0a868530e2 100644 --- a/arch/arm/src/sam34/sam_irq.c +++ b/arch/arm/src/sam34/sam_irq.c @@ -535,14 +535,8 @@ int up_prioritize_irq(int irq, int priority) uint32_t regval; int shift; -#ifdef CONFIG_ARMV7M_USEBASEPRI - DEBUGASSERT(irq >= SAM_IRQ_MEMFAULT && irq < SAM_IRQ_NIRQS && - priority >= NVIC_SYSH_DISABLE_PRIORITY && - priority <= NVIC_SYSH_PRIORITY_MIN); -#else DEBUGASSERT(irq >= SAM_IRQ_MEMFAULT && irq < SAM_IRQ_NIRQS && (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); -#endif if (irq < SAM_IRQ_EXTINT) { diff --git a/arch/arm/src/stm32/stm32_irq.c b/arch/arm/src/stm32/stm32_irq.c index ce931afa74..27b0c10fed 100644 --- a/arch/arm/src/stm32/stm32_irq.c +++ b/arch/arm/src/stm32/stm32_irq.c @@ -486,14 +486,8 @@ int up_prioritize_irq(int irq, int priority) uint32_t regval; int shift; -#ifdef CONFIG_ARMV7M_USEBASEPRI - DEBUGASSERT(irq >= STM32_IRQ_MEMFAULT && irq < NR_IRQS && - priority >= NVIC_SYSH_DISABLE_PRIORITY && - priority <= NVIC_SYSH_PRIORITY_MIN); -#else DEBUGASSERT(irq >= STM32_IRQ_MEMFAULT && irq < NR_IRQS && (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); -#endif if (irq < STM32_IRQ_INTERRUPTS) {