From 545cfada384a1486d55738b448f87d4c60ead8c3 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 9 Aug 2019 10:52:35 -0600 Subject: [PATCH] This commit removes CONFIG_ARCH_INT_DISABLEALL. In the normal course of things, interrupts must occasionally be disabled using the up_irq_save() 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 we are using BASEPRI to disable interrupts and have high priority interrupts enabled (CONFIG_ARCH_HIPRI_INTERRUPT=y), do we disable all interrupts except SVCall (we cannot disable SVCall interrupts). Or do we only disable the "normal" interrupts? If we are using the BASEPRI register to disable interrupts, then the answer is that we must disable ONLY the "normal interrupts". That is because we cannot disable SVCALL interrupts and we cannot permit SVCAll interrupts running at a higher priority than the high priority interrupts (otherwise, they will introduce jitter in the high priority interrupt response time.) Hence, if you need to disable the high priority interrupt, you will have to disable the interrupt either at the peripheral that generates the interrupt or at the NVIC. Disabling global interrupts via the BASEPRI register cannot effect high priority interrupts. --- arch/Kconfig | 38 ------------------- arch/arm/include/armv7-m/nvicpri.h | 60 +++++++++++------------------- arch/arm/include/cxd56xx/chip.h | 52 +++++++++++++------------- 3 files changed, 47 insertions(+), 103 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index efb95eb2d4..b3ef50d7a8 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -898,44 +898,6 @@ config ARCH_HIPRI_INTERRUPT the nested interrupt, the interrupt stack if no privileged task has run -config ARCH_INT_DISABLEALL - bool "Disable high priority interrupts" - default y - depends on ARCH_HIPRI_INTERRUPT && EXPERIMENTAL - ---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 up_irq_save() 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 | - ----------------------------+--------------+--------------+------------- - - NOTE: This does not work now because interrupts get disabled in the - standard interrupt handling, prohibiting nesting. Fix is simple: Need - to used more priority levels so that we can make a cleaner distinction - with the standard interrupt handler. - comment "Boot options" choice diff --git a/arch/arm/include/armv7-m/nvicpri.h b/arch/arm/include/armv7-m/nvicpri.h index 0ce85b00f8..c1fe4a8e26 100644 --- a/arch/arm/include/armv7-m/nvicpri.h +++ b/arch/arm/include/armv7-m/nvicpri.h @@ -65,49 +65,33 @@ * In the normal course of things, interrupts must occasionally be disabled * using the up_irq_save() 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: + * level logic. Now the question arises, if we are using + * CONFIG_ARCH_HIPRI_INTERRUPT=y, do we disable all interrupts except + * SVCall (we cannot disable SVCall interrupts). Or do we only disable the + * "normal" interrupts? * - * ----------------------------+--------------+---------------------------- - * 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 we are using the BASEPRI register to disable interrupts, then the + * answer is that we must disable ONLY the "normal interrupts". That + * is because we cannot disable SVCALL interrupts and we cannot permit + * SVCAll interrupts running at a higher priority than the high priority + * interrupts (otherwise, they will introduce jitter in the high priority + * interrupt response time.) * + * Hence, if you need to disable the high priority interrupt, you will have + * to disable the interrupt either at the peripheral that generates the + * interrupt or at the NVIC. Disabling global interrupts via the BASEPRI + * register cannot effect high priority interrupts. */ -#if defined(CONFIG_ARCH_HIPRI_INTERRUPT) && defined(CONFIG_ARCH_INT_DISABLEALL) - -/* In this case, disabling interrupts will disable all interrupts EXCEPT - * SVCALL. NOTE that this will add jitter to the high priority interrupt - * response because it may be deferred by SVCALL interupt handling. +/* The high priority interrupt must be highest priority. This prevents + * SVCALL handling from adding jitter to high priority interrupt response. + * Disabling interrupts will disable all interrupts EXCEPT SVCALL and the + * high priority interrupts. */ -# define NVIC_SYSH_MAXNORMAL_PRIORITY NVIC_SYSH_PRIORITY_DEFAULT -# define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_DEFAULT - 1*NVIC_SYSH_PRIORITY_STEP) -# define NVIC_SYSH_DISABLE_PRIORITY (NVIC_SYSH_PRIORITY_DEFAULT - 1*NVIC_SYSH_PRIORITY_STEP) -# define NVIC_SYSH_SVCALL_PRIORITY (NVIC_SYSH_PRIORITY_DEFAULT - 2*NVIC_SYSH_PRIORITY_STEP) -#else - -/* In this case, the high priority interrupt must be highest priority. This - * prevents SVCALL handling from adding jitter to high priority interrupt - * response. Disabling interrupts will disable all interrupts EXCEPT SVCALL - * and the high priority interrupts. - */ - -# define NVIC_SYSH_MAXNORMAL_PRIORITY NVIC_SYSH_PRIORITY_DEFAULT -# define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_DEFAULT - 2*NVIC_SYSH_PRIORITY_STEP) -# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_PRIORITY_DEFAULT -# define NVIC_SYSH_SVCALL_PRIORITY (NVIC_SYSH_PRIORITY_DEFAULT - 1*NVIC_SYSH_PRIORITY_STEP) -#endif +#define NVIC_SYSH_MAXNORMAL_PRIORITY NVIC_SYSH_PRIORITY_DEFAULT +#define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_DEFAULT - 2*NVIC_SYSH_PRIORITY_STEP) +#define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_PRIORITY_DEFAULT +#define NVIC_SYSH_SVCALL_PRIORITY (NVIC_SYSH_PRIORITY_DEFAULT - 1*NVIC_SYSH_PRIORITY_STEP) #endif /* __ARCH_ARM_INCLUDE_ARM7_M_NVICPRI_H */ diff --git a/arch/arm/include/cxd56xx/chip.h b/arch/arm/include/cxd56xx/chip.h index 9a790817d2..2763f6bc04 100644 --- a/arch/arm/include/cxd56xx/chip.h +++ b/arch/arm/include/cxd56xx/chip.h @@ -70,35 +70,33 @@ * In the normal course of things, interrupts must occasionally be disabled * using the up_irq_save() 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: + * level logic. Now the question arises, if we are using + * CONFIG_ARCH_HIPRI_INTERRUPT=y, do we disable all interrupts except + * SVCall (we cannot disable SVCall interrupts). Or do we only disable the + * "normal" interrupts? * - * ----------------------------+--------------+---------------------------- - * 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 we are using the BASEPRI register to disable interrupts, then the + * answer is that we must disable ONLY the "normal interrupts". That + * is because we cannot disable SVCALL interrupts and we cannot permit + * SVCAll interrupts running at a higher priority than the high priority + * interrupts (otherwise, they will introduce jitter in the high priority + * interrupt response time.) + * + * Hence, if you need to disable the high priority interrupt, you will have + * to disable the interrupt either at the peripheral that generates the + * interrupt or at the NVIC. Disabling global interrupts via the BASEPRI + * register cannot effect high priority interrupts. */ -#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 +/* The high priority interrupt must be highest priority. This prevents + * SVCALL handling from adding jitter to high priority interrupt response. + * Disabling interrupts will disable all interrupts EXCEPT SVCALL and the + * high priority interrupts. + */ + +#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 /* __ARCH_ARM_INCLUDE_CXD56XX_CHIP_H */