RTX5: updated to use OS Tick API
diff --git a/ARM.CMSIS.pdsc b/ARM.CMSIS.pdsc
index 84c7fc6..dbbeccd 100644
--- a/ARM.CMSIS.pdsc
+++ b/ARM.CMSIS.pdsc
@@ -843,18 +843,6 @@
<require Dcore="ARMV8MML" Ddsp="DSP" Dfpu="SP_FPU"/>
</condition>
- <!-- Cortex-A Devices -->
- <condition id="RZ_A Device">
- <description>Renesas RZ_A Device</description>
- <require Dvendor="Renesas:117"/>
- <require Dfamily="RZ_A"/>
- </condition>
- <condition id="Unknown Cortex-A Device">
- <description>Unknown Cortex-A Device</description>
- <require condition="ARMv7-A Device"/>
- <deny condition="RZ_A Device"/>
- </condition>
-
<!-- ARMCC compiler -->
<condition id="CA_ARMCC5">
<description>Cortex-A5, Cortex-A7 or Cortex-A9 processor based device for the ARM Compiler 5</description>
@@ -1834,12 +1822,19 @@
</condition>
<condition id="RTOS2 RTX5">
<description>Components required for RTOS2 RTX5</description>
- <accept condition="ARMv6_7_8-M Device"/>
- <accept condition="ARMv7-A Device"/>
+ <require condition="ARMv6_7_8-M Device"/>
<require condition="ARMCC GCC IAR"/>
<require Cclass="CMSIS" Cgroup="CORE"/>
<require Cclass="Device" Cgroup="Startup"/>
</condition>
+ <condition id="RTOS2 RTX5 v7-A">
+ <description>Components required for RTOS2 RTX5 v7-A</description>
+ <require condition="ARMv7-A Device"/>
+ <require condition="ARMCC GCC IAR"/>
+ <require Cclass="CMSIS" Cgroup="CORE"/>
+ <require Cclass="Device" Cgroup="Startup"/>
+ <require Cclass="Device" Cgroup="OS Tick"/>
+ </condition>
<condition id="RTOS2 RTX5 Lib">
<description>Components required for RTOS2 RTX5 Library</description>
<require condition="ARMv6_7_8-M Device"/>
@@ -2526,12 +2521,8 @@
<file category="header" name="CMSIS/RTOS2/RTX/Include/rtx_os.h"/>
<!-- RTX configuration -->
- <file category="header" attr="config" name="CMSIS/RTOS2/RTX/Config/RTX_Config.h" version="5.1.0"/>
- <file category="source" attr="config" name="CMSIS/RTOS2/RTX/Config/RTX_Config.c" version="5.1.0" condition="ARMv6_7_8-M Device" />
- <file category="source" attr="config" name="CMSIS/RTOS2/RTX/Config/Cortex_A/RTX_Config.c" version="5.1.0" condition="Unknown Cortex-A Device"/>
- <file category="source" attr="config" name="CMSIS/RTOS2/RTX/Config/Renesas/RZ_A/RTX_Config.c" version="5.1.0" condition="RZ_A Device"/>
-
- <file category="source" attr="config" name="CMSIS/RTOS2/RTX/Config/handlers.c" version="5.1.0" condition="ARMv7-A Device"/>
+ <file category="header" attr="config" name="CMSIS/RTOS2/RTX/Config/RTX_Config.h" version="5.1.0"/>
+ <file category="source" attr="config" name="CMSIS/RTOS2/RTX/Config/RTX_Config.c" version="5.1.0"/>
<!-- RTX templates -->
<file category="source" attr="template" name="CMSIS/RTOS2/RTX/Template/main.c" version="2.0.0" select="CMSIS-RTOS2 'main' function"/>
@@ -2557,12 +2548,9 @@
<file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_msgqueue.c"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_system.c"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_evr.c"/>
- <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_gic.c" condition="ARMv7-A Device"/>
<!-- RTX sources (library configuration) -->
<file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_lib.c"/>
<!-- RTX sources (handlers ARMCC) -->
- <file category="source" name="CMSIS/RTOS2/RTX/Source/ARM/irq_ca.s" condition="CA_ARMCC5"/>
- <file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_ca.S" condition="CA_ARMCC6"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/ARM/irq_cm0.s" condition="CM0_ARMCC"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/ARM/irq_cm3.s" condition="CM3_ARMCC"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/ARM/irq_cm3.s" condition="CM4_ARMCC"/>
@@ -2576,7 +2564,6 @@
<file category="source" name="CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mml.s" condition="ARMv8MML_ARMCC"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mml.s" condition="ARMv8MML_FP_ARMCC"/>
<!-- RTX sources (handlers GCC) -->
- <file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_ca.S" condition="CA_GCC"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_cm0.S" condition="CM0_GCC"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_cm3.S" condition="CM3_GCC"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_cm3.S" condition="CM4_GCC"/>
@@ -2590,13 +2577,71 @@
<file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mml.S" condition="ARMv8MML_GCC"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mml_fp.S" condition="ARMv8MML_FP_GCC"/>
<!-- RTX sources (handlers IAR) -->
- <file category="source" name="CMSIS/RTOS2/RTX/Source/IAR/irq_ca.s" condition="CA_IAR"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/IAR/irq_cm0.s" condition="CM0_IAR"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/IAR/irq_cm3.s" condition="CM3_IAR"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/IAR/irq_cm3.s" condition="CM4_IAR"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/IAR/irq_cm4f.s" condition="CM4_FP_IAR"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/IAR/irq_cm3.s" condition="CM7_IAR"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/IAR/irq_cm4f.s" condition="CM7_FP_IAR"/>
+ <!-- OS Tick (SysTick) -->
+ <file category="source" name="CMSIS/RTOS2/Source/os_systick.c"/>
+ </files>
+ </component>
+ <component Cclass="CMSIS" Cgroup="RTOS2" Csub="Keil RTX5" Cvariant="Source" Cversion="5.2.0" Capiversion="2.1.1" condition="RTOS2 RTX5 v7-A">
+ <description>CMSIS-RTOS2 RTX5 for ARMv7-A (Source)</description>
+ <RTE_Components_h>
+ <!-- the following content goes into file 'RTE_Components.h' -->
+ #define RTE_CMSIS_RTOS2 /* CMSIS-RTOS2 */
+ #define RTE_CMSIS_RTOS2_RTX5 /* CMSIS-RTOS2 Keil RTX5 */
+ #define RTE_CMSIS_RTOS2_RTX5_SOURCE /* CMSIS-RTOS2 Keil RTX5 Source */
+ </RTE_Components_h>
+ <files>
+ <!-- RTX documentation -->
+ <file category="doc" name="CMSIS/Documentation/RTOS2/html/rtx5_impl.html"/>
+
+ <!-- RTX header files -->
+ <file category="header" name="CMSIS/RTOS2/RTX/Include/rtx_os.h"/>
+
+ <!-- RTX configuration -->
+ <file category="header" attr="config" name="CMSIS/RTOS2/RTX/Config/RTX_Config.h" version="5.1.0"/>
+ <file category="source" attr="config" name="CMSIS/RTOS2/RTX/Config/RTX_Config.c" version="5.1.0"/>
+
+ <file category="source" attr="config" name="CMSIS/RTOS2/RTX/Config/handlers.c" version="5.1.0"/>
+
+ <!-- RTX templates -->
+ <file category="source" attr="template" name="CMSIS/RTOS2/RTX/Template/main.c" version="2.0.0" select="CMSIS-RTOS2 'main' function"/>
+ <file category="source" attr="template" name="CMSIS/RTOS2/RTX/Template/Events.c" version="2.0.0" select="CMSIS-RTOS2 Events"/>
+ <file category="source" attr="template" name="CMSIS/RTOS2/RTX/Template/MemPool.c" version="2.0.0" select="CMSIS-RTOS2 Memory Pool"/>
+ <file category="source" attr="template" name="CMSIS/RTOS2/RTX/Template/MsgQueue.c" version="2.0.0" select="CMSIS-RTOS2 Message Queue"/>
+ <file category="source" attr="template" name="CMSIS/RTOS2/RTX/Template/Mutex.c" version="2.0.0" select="CMSIS-RTOS2 Mutex"/>
+ <file category="source" attr="template" name="CMSIS/RTOS2/RTX/Template/Semaphore.c" version="2.0.0" select="CMSIS-RTOS2 Semaphore"/>
+ <file category="source" attr="template" name="CMSIS/RTOS2/RTX/Template/Thread.c" version="2.0.0" select="CMSIS-RTOS2 Thread"/>
+ <file category="source" attr="template" name="CMSIS/RTOS2/RTX/Template/Timer.c" version="2.0.0" select="CMSIS-RTOS2 Timer"/>
+ <file category="other" name="CMSIS/RTOS2/RTX/RTX5.scvd"/>
+
+ <!-- RTX sources (core) -->
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_kernel.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_thread.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_delay.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_timer.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_evflags.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_mutex.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_semaphore.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_memory.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_mempool.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_msgqueue.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_system.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_evr.c"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_gic.c"/>
+ <!-- RTX sources (library configuration) -->
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/rtx_lib.c"/>
+ <!-- RTX sources (handlers ARMCC) -->
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/ARM/irq_ca.s" condition="CA_ARMCC5"/>
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_ca.S" condition="CA_ARMCC6"/>
+ <!-- RTX sources (handlers GCC) -->
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_ca.S" condition="CA_GCC"/>
+ <!-- RTX sources (handlers IAR) -->
+ <file category="source" name="CMSIS/RTOS2/RTX/Source/IAR/irq_ca.s" condition="CA_IAR"/>
</files>
</component>
<component Cclass="CMSIS" Cgroup="RTOS2" Csub="Keil RTX5" Cvariant="Source_NS" Cversion="5.2.0" Capiversion="2.1.1" condition="RTOS2 RTX5 NS">
@@ -2659,6 +2704,8 @@
<file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mbl_ns.S" condition="ARMv8MBL_GCC"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mml_ns.S" condition="ARMv8MML_GCC"/>
<file category="source" name="CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mml_fp_ns.S" condition="ARMv8MML_FP_GCC"/>
+ <!-- OS Tick (SysTick) -->
+ <file category="source" name="CMSIS/RTOS2/Source/os_systick.c"/>
</files>
</component>
diff --git a/CMSIS/RTOS2/RTX/Config/Cortex_A/RTX_Config.c b/CMSIS/RTOS2/RTX/Config/Cortex_A/RTX_Config.c
deleted file mode 100644
index 7e640ad..0000000
--- a/CMSIS/RTOS2/RTX/Config/Cortex_A/RTX_Config.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * -----------------------------------------------------------------------------
- *
- * $Revision: V5.1.0
- *
- * Project: CMSIS-RTOS RTX
- * Title: RTX Configuration
- *
- * -----------------------------------------------------------------------------
- */
-
-#include "RTE_Components.h"
-#include CMSIS_device_header
-
-#include "rtx_os.h"
-
-
-// Setup System Timer.
-// \return system timer IRQ number.
-int32_t osRtxSysTimerSetup (void) {
- // ...
- return (0);
-}
-
-// Enable System Timer.
-void osRtxSysTimerEnable (void) {
- // ...
-}
-
-// Disable System Timer.
-void osRtxSysTimerDisable (void) {
- // ...
-}
-
-// Acknowledge System Timer IRQ.
-void osRtxSysTimerAckIRQ (void) {
- // ...
-}
-
-// Get System Timer count.
-// \return system timer count.
-uint32_t osRtxSysTimerGetCount (void) {
- // ...
- return (0U);
-}
-
-// Get System Timer frequency.
-// \return system timer frequency.
-uint32_t osRtxSysTimerGetFreq (void) {
- // ...
- return (1000000U);
-}
-
-
-// OS Idle Thread
-__WEAK __NO_RETURN void osRtxIdleThread (void *argument) {
- (void)argument;
-
- for (;;) {}
-}
-
-// OS Error Callback function
-__WEAK uint32_t osRtxErrorNotify (uint32_t code, void *object_id) {
- (void)object_id;
-
- switch (code) {
- case osRtxErrorStackUnderflow:
- // Stack underflow detected for thread (thread_id=object_id)
- break;
- case osRtxErrorISRQueueOverflow:
- // ISR Queue overflow detected when inserting object (object_id)
- break;
- case osRtxErrorTimerQueueOverflow:
- // User Timer Callback Queue overflow detected for timer (timer_id=object_id)
- break;
- case osRtxErrorClibSpace:
- // Standard C/C++ library libspace not available: increase OS_THREAD_LIBSPACE_NUM
- break;
- case osRtxErrorClibMutex:
- // Standard C/C++ library mutex initialization failed
- break;
- default:
- break;
- }
- for (;;) {}
-//return 0U;
-}
diff --git a/CMSIS/RTOS2/RTX/Config/Renesas/RZ_A/RTX_Config.c b/CMSIS/RTOS2/RTX/Config/Renesas/RZ_A/RTX_Config.c
deleted file mode 100644
index 8058771..0000000
--- a/CMSIS/RTOS2/RTX/Config/Renesas/RZ_A/RTX_Config.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * -----------------------------------------------------------------------------
- *
- * $Revision: V5.1.0
- *
- * Project: CMSIS-RTOS RTX
- * Title: RTX Configuration
- *
- * -----------------------------------------------------------------------------
- */
-
-#include "RTE_Components.h"
-#include CMSIS_device_header
-
-#include "rtx_os.h"
-
-
-// Define OS Timer channel and interrupt number
-#define OSTM OSTM0
-#define OSTM_IRQn OSTMI0TINT_IRQn
-
-static uint32_t ExtTim_Cnt; // Timer count used for overflow detection
-static uint32_t ExtTim_Freq; // Timer frequency
-
-
-// Get OS Timer current count value
-__STATIC_INLINE uint32_t OSTM_GetCount(void) {
- ExtTim_Cnt = OSTM.OSTMnCNT;
- return (OSTM.OSTMnCMP - ExtTim_Cnt);
-}
-
-// Check if OS Timer counter was reloaded
-__STATIC_INLINE uint32_t OSTM_GetOverflow(void) {
- return ((OSTM.OSTMnCNT > ExtTim_Cnt) ? (1U) : (0U));
-}
-
-// Get OS Timer period
-__STATIC_INLINE uint32_t OSTM_GetPeriod(void) {
- return (OSTM.OSTMnCMP + 1U);
-}
-
-
-// Setup System Timer.
-// \return system timer IRQ number.
-int32_t osRtxSysTimerSetup (void) {
- uint32_t freq;
-
- // Get CPG.FRQCR[IFC] bits
- freq = (CPG.FRQCR >> 8) & 0x03;
-
- // Determine Divider 2 output clock by using SystemCoreClock
- if (freq == 0x03U) {
- freq = (SystemCoreClock * 3U);
- }
- else if (freq == 0x01U) {
- freq = (SystemCoreClock * 3U)/2U;
- }
- else {
- freq = SystemCoreClock;
- }
- // Peripheral clock 0C = (Divider 2 clock * 1/12)
- freq = freq / 12U;
-
- // Determine tick frequency
- freq = freq / osRtxConfig.tick_freq;
-
- // Save frequency for later
- ExtTim_Freq = freq;
-
- // Enable OSTM clock
- CPG.STBCR5 &= ~(CPG_STBCR5_BIT_MSTP51);
-
- // Stop the OSTM counter
- OSTM.OSTMnTT = 0x01U;
-
- // Set interval timer mode and disable interrupts when counting starts
- OSTM.OSTMnCTL = 0x00U;
-
- // Set compare value
- OSTM.OSTMnCMP = freq - 1U;
-
- return (OSTM_IRQn);
-}
-
-// Enable System Timer.
-void osRtxSysTimerEnable (void) {
- /* Start the OSTM counter */
- OSTM.OSTMnTS = 0x01U;
-}
-
-// Disable System Timer.
-void osRtxSysTimerDisable (void) {
- // Stop the OSTM counter
- OSTM.OSTMnTT = 0x01U;
-}
-
-// Acknowledge System Timer IRQ.
-void osRtxSysTimerAckIRQ (void) {
- // Acknowledge OSTM interrupt
- GIC_ClearPendingIRQ (OSTM_IRQn);
-}
-
-// Get System Timer count.
-// \return system timer count.
-uint32_t osRtxSysTimerGetCount (void) {
- uint32_t tick;
- uint32_t val;
-
- tick = (uint32_t)osRtxInfo.kernel.tick;
- val = OSTM_GetCount();
- if (OSTM_GetOverflow()) {
- val = OSTM_GetCount();
- tick++;
- }
- val += tick * OSTM_GetPeriod();
-
- return val;
-}
-
-// Get System Timer frequency.
-// \return system timer frequency.
-uint32_t osRtxSysTimerGetFreq (void) {
- return ExtTim_Freq;
-}
-
-
-// OS Idle Thread
-__WEAK __NO_RETURN void osRtxIdleThread (void *argument) {
- (void)argument;
-
- for (;;) {}
-}
-
-// OS Error Callback function
-__WEAK uint32_t osRtxErrorNotify (uint32_t code, void *object_id) {
- (void)object_id;
-
- switch (code) {
- case osRtxErrorStackUnderflow:
- // Stack underflow detected for thread (thread_id=object_id)
- break;
- case osRtxErrorISRQueueOverflow:
- // ISR Queue overflow detected when inserting object (object_id)
- break;
- case osRtxErrorTimerQueueOverflow:
- // User Timer Callback Queue overflow detected for timer (timer_id=object_id)
- break;
- case osRtxErrorClibSpace:
- // Standard C/C++ library libspace not available: increase OS_THREAD_LIBSPACE_NUM
- break;
- case osRtxErrorClibMutex:
- // Standard C/C++ library mutex initialization failed
- break;
- default:
- break;
- }
- for (;;) {}
-//return 0U;
-}
diff --git a/CMSIS/RTOS2/RTX/Include/rtx_os.h b/CMSIS/RTOS2/RTX/Include/rtx_os.h
index 2ce7de1..f4cfbad 100644
--- a/CMSIS/RTOS2/RTX/Include/rtx_os.h
+++ b/CMSIS/RTOS2/RTX/Include/rtx_os.h
@@ -38,7 +38,7 @@
/// Kernel Information
#define osRtxVersionAPI 20010001 ///< API version (2.1.1)
-#define osRtxVersionKernel 50020001 ///< Kernel version (5.2.0)
+#define osRtxVersionKernel 50020000 ///< Kernel version (5.2.0)
#define osRtxKernelId "RTX V5.2.0" ///< Kernel identification string
@@ -282,11 +282,9 @@
struct { ///< Kernel Info
uint8_t state; ///< State
volatile uint8_t blocked; ///< Blocked
- uint8_t pendISR; ///< Pending ISR (SV and SysTick)
uint8_t pendSV; ///< Pending SV
- uint32_t sys_freq; ///< System Frequency
+ uint8_t reserved;
uint32_t tick; ///< Tick counter
- uint32_t reserved;
} kernel;
int32_t tick_irqn; ///< Tick Timer IRQ Number
struct { ///< Thread Info
@@ -341,7 +339,6 @@
osRtxMpInfo_t *memory_pool; ///< Memory Pool Control Blocks
osRtxMpInfo_t *message_queue; ///< Message Queue Control Blocks
} mpi;
- uint32_t padding;
} osRtxInfo_t;
extern osRtxInfo_t osRtxInfo; ///< OS Runtime Information
@@ -398,30 +395,6 @@
extern void SysTick_Handler (void);
-/// OS System Timer functions (default implementation uses SysTick)
-
-/// Setup System Timer.
-/// \return system timer IRQ number.
-extern int32_t osRtxSysTimerSetup (void);
-
-/// Enable System Timer.
-extern void osRtxSysTimerEnable (void);
-
-/// Disable System Timer.
-extern void osRtxSysTimerDisable (void);
-
-/// Acknowledge System Timer IRQ.
-extern void osRtxSysTimerAckIRQ (void);
-
-/// Get System Timer count.
-/// \return system timer count.
-extern uint32_t osRtxSysTimerGetCount (void);
-
-/// Get System Timer frequency.
-/// \return system timer frequency.
-extern uint32_t osRtxSysTimerGetFreq (void);
-
-
// ==== OS External Configuration ====
/// OS Configuration flags
diff --git a/CMSIS/RTOS2/RTX/RTX5.scvd b/CMSIS/RTOS2/RTX/RTX5.scvd
index b75b9a2..27eb2e9 100644
--- a/CMSIS/RTOS2/RTX/RTX5.scvd
+++ b/CMSIS/RTOS2/RTX/RTX5.scvd
@@ -342,7 +342,7 @@
</typedef>
<!-- OS Runtime Information structure -->
- <typedef name="osRtxInfo_t" info="OS Runtime Information" size="172">
+ <typedef name="osRtxInfo_t" info="OS Runtime Information" size="164">
<member name="os_id" type="uint32_t" offset="0" info="OS Identification (type is *uint8_t)"/>
<member name="version" type="uint32_t" offset="4" info="OS Version"/>
<member name="kernel_state" type="uint8_t" offset="8" info="Kernel state">
@@ -354,61 +354,59 @@
<enum name="osKernelError" value="5" info="Error"/>
</member>
<member name="kernel_blocked" type="uint8_t" offset="9" info="Kernel blocked"/>
- <member name="kernel_pendISR" type="uint8_t" offset="10" info="Kernel pending ISR"/>
- <member name="kernel_pendSV" type="uint8_t" offset="11" info="Kernel pending SV"/>
- <member name="kernel_sys_freq" type="uint32_t" offset="12" info="Kernel system frequency"/>
- <member name="kernel_tick" type="uint32_t" offset="16" info="Kernel tick counter"/>
- <member name="tick_irqn" type="int32_t" offset="24" info="Tick timer IRQ number"/>
- <member name="thread_run_curr" type="*osRtxThread_t" offset="28" info="Current running thread"/>
- <member name="thread_run_next" type="*osRtxThread_t" offset="32" info="Next thread to run"/>
+ <member name="kernel_pendSV" type="uint8_t" offset="10" info="Kernel pending SV"/>
+ <member name="kernel_tick" type="uint32_t" offset="12" info="Kernel tick counter"/>
+ <member name="tick_irqn" type="int32_t" offset="16" info="Tick timer IRQ number"/>
+ <member name="thread_run_curr" type="*osRtxThread_t" offset="20" info="Current running thread"/>
+ <member name="thread_run_next" type="*osRtxThread_t" offset="24" info="Next thread to run"/>
- <!-- Inlined "osRtxObject_t" structure at offset: 36 -->
- <member name="thread_ready_id" type="uint8_t" offset="36+0" info="Object Identifier" />
- <member name="thread_ready_state" type="uint8_t" offset="36+1" info="Object State" />
- <member name="thread_ready_flags" type="uint8_t" offset="36+2" info="Object Flags" />
- <member name="thread_ready_rsvd" type="uint8_t" offset="36+3" info="Reserved" />
- <member name="thread_ready_name" type="uint32_t" offset="36+4" info="Object Name (type is *uint8_t)" />
- <member name="thread_ready_thread_list" type="*osRtxThread_t" offset="36+8" info="Threads List" />
+ <!-- Inlined "osRtxObject_t" structure at offset: 28 -->
+ <member name="thread_ready_id" type="uint8_t" offset="28+0" info="Object Identifier" />
+ <member name="thread_ready_state" type="uint8_t" offset="28+1" info="Object State" />
+ <member name="thread_ready_flags" type="uint8_t" offset="28+2" info="Object Flags" />
+ <member name="thread_ready_rsvd" type="uint8_t" offset="28+3" info="Reserved" />
+ <member name="thread_ready_name" type="uint32_t" offset="28+4" info="Object Name (type is *uint8_t)" />
+ <member name="thread_ready_thread_list" type="*osRtxThread_t" offset="28+8" info="Threads List" />
- <member name="thread_idle" type="*osRtxThread_t" offset="48" info="Idle thread"/>
- <member name="thread_delay_list" type="*osRtxThread_t" offset="52" info="Delay list"/>
- <member name="thread_wait_list" type="*osRtxThread_t" offset="56" info="Wait list (no timeout)"/>
- <member name="thread_terminate_list" type="*osRtxThread_t" offset="60" info="Terminate list"/>
+ <member name="thread_idle" type="*osRtxThread_t" offset="40" info="Idle thread"/>
+ <member name="thread_delay_list" type="*osRtxThread_t" offset="44" info="Delay list"/>
+ <member name="thread_wait_list" type="*osRtxThread_t" offset="48" info="Wait list (no timeout)"/>
+ <member name="thread_terminate_list" type="*osRtxThread_t" offset="52" info="Terminate list"/>
- <member name="thread_robin_thread" type="*osRtxThread_t" offset="64" info="Round Robin thread"/>
- <member name="thread_robin_tick" type="uint32_t" offset="68" info="Round Robin time tick"/>
- <member name="thread_timeout" type="uint32_t" offset="72" info="Round Robin timeout"/>
+ <member name="thread_robin_thread" type="*osRtxThread_t" offset="56" info="Round Robin thread"/>
+ <member name="thread_robin_tick" type="uint32_t" offset="60" info="Round Robin time tick"/>
+ <member name="thread_timeout" type="uint32_t" offset="64" info="Round Robin timeout"/>
- <member name="timer_list" type="*osRtxTimer_t" offset="76" info="Active timer list"/>
- <member name="timer_thread" type="*osRtxThread_t" offset="80" info="Timer thread"/>
- <member name="timer_mq" type="*osRtxMessageQueue_t" offset="84" info="Timer message queue"/>
- <member name="timer_tick" type="uint32_t" offset="88" info="Timer tick function (type is func *)"/>
+ <member name="timer_list" type="*osRtxTimer_t" offset="68" info="Active timer list"/>
+ <member name="timer_thread" type="*osRtxThread_t" offset="72" info="Timer thread"/>
+ <member name="timer_mq" type="*osRtxMessageQueue_t" offset="76" info="Timer message queue"/>
+ <member name="timer_tick" type="uint32_t" offset="80" info="Timer tick function (type is func *)"/>
- <member name="isr_queue_max" type="uint16_t" offset="92" info="Maximum items"/>
- <member name="isr_queue_cnt" type="uint16_t" offset="94" info="Item count"/>
- <member name="isr_queue_in" type="uint16_t" offset="96" info="Incoming item index"/>
- <member name="isr_queue_out" type="uint16_t" offset="98" info="Outgoing item index"/>
- <member name="isr_queue_data" type="uint32_t" offset="100" info="Queue data (type is void **)"/>
+ <member name="isr_queue_max" type="uint16_t" offset="84" info="Maximum items"/>
+ <member name="isr_queue_cnt" type="uint16_t" offset="86" info="Item count"/>
+ <member name="isr_queue_in" type="uint16_t" offset="88" info="Incoming item index"/>
+ <member name="isr_queue_out" type="uint16_t" offset="90" info="Outgoing item index"/>
+ <member name="isr_queue_data" type="uint32_t" offset="92" info="Queue data (type is void **)"/>
- <member name="post_process_thread" type="uint32_t" offset="104" info="Thread post processing function (type is func *)"/>
- <member name="post_process_event_flags" type="uint32_t" offset="108" info="Event flags post processing function (type is func *)"/>
- <member name="post_process_semaphore" type="uint32_t" offset="112" info="Semaphore post processing function (type is func *)"/>
- <member name="post_process_memory_pool" type="uint32_t" offset="116" info="Memory pool post processing function (type is func *)"/>
- <member name="post_process_message_queue" type="uint32_t" offset="120" info="Message queue post processing function (type is func *)"/>
+ <member name="post_process_thread" type="uint32_t" offset="96" info="Thread post processing function (type is func *)"/>
+ <member name="post_process_event_flags" type="uint32_t" offset="100" info="Event flags post processing function (type is func *)"/>
+ <member name="post_process_semaphore" type="uint32_t" offset="104" info="Semaphore post processing function (type is func *)"/>
+ <member name="post_process_memory_pool" type="uint32_t" offset="108" info="Memory pool post processing function (type is func *)"/>
+ <member name="post_process_message_queue" type="uint32_t" offset="112" info="Message queue post processing function (type is func *)"/>
- <member name="mem_stack" type="uint32_t" offset="124" info="Stack memory (type is void *)"/>
- <member name="mem_mp_data" type="uint32_t" offset="128" info="Memory pool data memory (type is void *)"/>
- <member name="mem_mq_data" type="uint32_t" offset="132" info="Message queue Data memory (type is void *)"/>
- <member name="mem_common" type="uint32_t" offset="136" info="Common memory address (type is void *)"/>
+ <member name="mem_stack" type="uint32_t" offset="116" info="Stack memory (type is void *)"/>
+ <member name="mem_mp_data" type="uint32_t" offset="120" info="Memory pool data memory (type is void *)"/>
+ <member name="mem_mq_data" type="uint32_t" offset="124" info="Message queue Data memory (type is void *)"/>
+ <member name="mem_common" type="uint32_t" offset="128" info="Common memory address (type is void *)"/>
- <member name="mpi_stack" type="*osRtxMpInfo_t" offset="140" info="Stack for threads"/>
- <member name="mpi_thread" type="*osRtxMpInfo_t" offset="144" info="Thread control blocks"/>
- <member name="mpi_timer" type="*osRtxMpInfo_t" offset="148" info="Timer control blocks"/>
- <member name="mpi_event_flags" type="*osRtxMpInfo_t" offset="152" info="Event flags control blocks"/>
- <member name="mpi_mutex" type="*osRtxMpInfo_t" offset="156" info="Mutex control blocks"/>
- <member name="mpi_semaphore" type="*osRtxMpInfo_t" offset="160" info="Semaphore control blocks"/>
- <member name="mpi_memory_pool" type="*osRtxMpInfo_t" offset="164" info="Memory pool control blocks"/>
- <member name="mpi_message_queue" type="*osRtxMpInfo_t" offset="168" info="Message queue control blocks"/>
+ <member name="mpi_stack" type="*osRtxMpInfo_t" offset="132" info="Stack for threads"/>
+ <member name="mpi_thread" type="*osRtxMpInfo_t" offset="136" info="Thread control blocks"/>
+ <member name="mpi_timer" type="*osRtxMpInfo_t" offset="140" info="Timer control blocks"/>
+ <member name="mpi_event_flags" type="*osRtxMpInfo_t" offset="144" info="Event flags control blocks"/>
+ <member name="mpi_mutex" type="*osRtxMpInfo_t" offset="148" info="Mutex control blocks"/>
+ <member name="mpi_semaphore" type="*osRtxMpInfo_t" offset="152" info="Semaphore control blocks"/>
+ <member name="mpi_memory_pool" type="*osRtxMpInfo_t" offset="156" info="Memory pool control blocks"/>
+ <member name="mpi_message_queue" type="*osRtxMpInfo_t" offset="160" info="Message queue control blocks"/>
</typedef>
<!-- OS Configuration structure -->
@@ -1070,7 +1068,6 @@
<item property="Kernel State" value="%E[os_Info.kernel_state]" cond="RTX_En != 0"/>
<item property="Kernel Tick Count" value="%d[os_Info.kernel_tick]" cond="RTX_En != 0"/>
<item property="Kernel Tick Frequency" value="%d[os_Config.tick_freq]" cond="RTX_En != 0" />
- <item property="System Timer Frequency" value="%d[os_Info.kernel_sys_freq]" cond="RTX_En != 0" />
<item property="Round Robin" value="Disabled" cond="(os_Config.robin_timeout == 0) && (RTX_En != 0)" />
<item property="Round Robin Tick Count" value="%d[os_Info.thread_robin_tick]" cond="(os_Config.robin_timeout > 0) && (RTX_En != 0)" />
<item property="Round Robin Timeout" value="%d[os_Config.robin_timeout]" cond="(os_Config.robin_timeout > 0) && (RTX_En != 0)" />
diff --git a/CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mbl.s b/CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mbl.s
index 22baabd..1586a95 100644
--- a/CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mbl.s
+++ b/CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mbl.s
@@ -28,7 +28,7 @@
__DOMAIN_NS EQU 0
ENDIF
-I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
+I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
TCB_SM_OFS EQU 48 ; TCB.stack_mem offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
TCB_SF_OFS EQU 34 ; TCB.stack_frame offset
diff --git a/CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mml.s b/CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mml.s
index f6d7c95..b8b25a1 100644
--- a/CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mml.s
+++ b/CMSIS/RTOS2/RTX/Source/ARM/irq_armv8mml.s
@@ -34,7 +34,7 @@
__FPU_USED EQU 0
ENDIF
-I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
+I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
TCB_SM_OFS EQU 48 ; TCB.stack_mem offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
TCB_SF_OFS EQU 34 ; TCB.stack_frame offset
diff --git a/CMSIS/RTOS2/RTX/Source/ARM/irq_ca.s b/CMSIS/RTOS2/RTX/Source/ARM/irq_ca.s
index b7e89e8..87f7c07 100644
--- a/CMSIS/RTOS2/RTX/Source/ARM/irq_ca.s
+++ b/CMSIS/RTOS2/RTX/Source/ARM/irq_ca.s
@@ -18,17 +18,11 @@
; * -----------------------------------------------------------------------------
; *
; * Project: CMSIS-RTOS RTX
-; * Title: Cortex-A Exception handlers (using GIC)
+; * Title: Cortex-A Exception handlers
; *
; * -----------------------------------------------------------------------------
; */
-ICDABR0_OFFSET EQU 0x00000300 ; GICD: Active Bit Register 0 offset
-ICDIPR0_OFFSET EQU 0x00000400 ; GICD: Interrupt Priority Register 0 offset
-ICCIAR_OFFSET EQU 0x0000000C ; GICI: Interrupt Acknowledge Register offset
-ICCEOIR_OFFSET EQU 0x00000010 ; GICI: End of Interrupt Register offset
-ICCHPIR_OFFSET EQU 0x00000018 ; GICI: Highest Pending Interrupt Register offset
-
MODE_FIQ EQU 0x11
MODE_IRQ EQU 0x12
MODE_SVC EQU 0x13
@@ -37,7 +31,7 @@
CPSR_BIT_T EQU 0x20
-I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
+I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
TCB_SP_FRAME EQU 34 ; osRtxThread_t.stack_frame offset
TCB_SP_OFS EQU 56 ; osRtxThread_t.sp offset
@@ -52,7 +46,10 @@
AREA |.data|, DATA, READWRITE
-ID0_Active DCB 4 ; Flag used to workaround GIC 390 errata 733075
+ EXPORT IRQ_PendSV
+IRQ_NestLevel DCD 0 ; IRQ nesting level counter
+IRQ_PendSV DCB 0 ; Pending SVC flag
+SVC_Active DCB 0 ; SVC handler execution active flag
AREA |.text|, CODE, READONLY
@@ -168,100 +165,96 @@
IRQ_Handler\
PROC
EXPORT IRQ_Handler
- IMPORT IRQTable
- IMPORT IRQCount
- IMPORT osRtxIrqHandler
- IMPORT irqRtxGicBase
+ IMPORT osRtxInfo
+ IMPORT osRtxIrqGetId
+ IMPORT osRtxIrqGetHandler
+ IMPORT osRtxIrqSetEnd
SUB LR, LR, #4 ; Pre-adjust LR
SRSFD SP!, #MODE_IRQ ; Save LR_irq and SPRS_irq
PUSH {R0-R3, R12, LR} ; Save APCS corruptible registers
- ; Identify and acknowledge interrupt
- LDR R1, =irqRtxGicBase;
- LDR R1, [R1, #4]
- LDR R0, [R1, #ICCHPIR_OFFSET] ; Dummy Read GICI ICCHPIR to avoid GIC 390 errata 801120
- LDR R0, [R1, #ICCIAR_OFFSET] ; Read GICI ICCIAR
- DSB ; Ensure that interrupt acknowledge completes before re-enabling interrupts
+ MOV R3, SP ; Move SP into R3
+ AND R3, R3, #4 ; Get stack adjustment to ensure 8-byte alignment
+ SUB SP, SP, R3 ; Adjust stack
+ PUSH {R3, R4} ; Store stack adjustment(R3) and user data(R4)
- ; Workaround GIC 390 errata 733075 - see GIC-390_Errata_Notice_v6.pdf dated 09-Jul-2014
- ; The following workaround code is for a single-core system. It would be different in a multi-core system.
- ; If the ID is 0 or 0x3FE or 0x3FF, then the GIC CPU interface may be locked-up so unlock it, otherwise service the interrupt as normal
- ; Special IDs 1020=0x3FC and 1021=0x3FD are reserved values in GICv1 and GICv2 so will not occur here
- CMP R0, #0
- BEQ IRQ_Unlock
- MOV R2, #0x3FE
- CMP R0, R2
- BLT IRQ_Normal
-IRQ_Unlock
- ; Unlock the CPU interface with a dummy write to ICDIPR0
- LDR R2, =irqRtxGicBase
- LDR R2, [R2]
- LDR R3, [R2, #ICDIPR0_OFFSET]
- STR R3, [R2, #ICDIPR0_OFFSET]
- DSB ; Ensure the write completes before continuing
+ BLX osRtxIrqGetId ; Retrieve interrupt ID into R0
+ CMP R0, #-1 ; Check if interrupt valid
+ BEQ IRQ_Exit ; Spurious interrupt if -1, exit IRQ
+ MOV R4, R0 ; Move interrupt ID to R4
- ; If the ID is 0 and it is active and has not been seen before, then service it as normal,
- ; otherwise the interrupt should be treated as spurious and not serviced.
- CMP R0, #0
- BNE IRQ_Exit ; Not 0, so spurious
- LDR R3, [R2, #ICDABR0_OFFSET] ; Get the interrupt state
- TST R3, #1
- BEQ IRQ_Exit ; Not active, so spurious
- LDR R2, =ID0_Active
- LDRB R3, [R2]
- CMP R3, #1
- BEQ IRQ_Exit ; Seen it before, so spurious
+ LDR R1, =IRQ_NestLevel
+ LDR R3, [R1] ; Load IRQ nest level and increment it
+ ADD R3, R3, #1
+ STR R3, [R1]
- ; Record that ID0 has now been seen, then service it as normal
- MOV R3, #1
- STRB R3, [R2]
- ; End of Workaround GIC 390 errata 733075
-
-IRQ_Normal
- LDR R2, =IRQCount ; Read number of entries in IRQ handler table
- LDR R2, [R2]
- CMP R0, R2 ; Check if IRQ ID is within range
- MOV R2, #0
- BHS IRQ_End ; Out of range, return as normal
- LDR R2, =IRQTable ; Read IRQ handler address from IRQ table
- LDR R2, [R2, R0, LSL #2]
- CMP R2, #0 ; Check if handler address is 0
+ BLX osRtxIrqGetHandler ; Retrieve interrupt handler address for current ID
+ CMP R0, #0 ; Check if handler address is 0
BEQ IRQ_End ; If 0, end interrupt and return
- PUSH {R0, R1} ; Store IRQ ID and GIC CPU Interface base address
CPS #MODE_SVC ; Change to SVC mode
MOV R3, SP ; Move SP into R3
AND R3, R3, #4 ; Get stack adjustment to ensure 8-byte alignment
SUB SP, SP, R3 ; Adjust stack
- PUSH {R2, R3, R12, LR} ; Store handler address(R2), stack adjustment(R3) and user R12, LR
+ PUSH {R3, R4} ; Store stack adjustment(R3) and alignment dummy(R4)
CPSIE i ; Re-enable interrupts
- BLX R2 ; Call IRQ handler
+ BLX R0 ; Call IRQ handler
CPSID i ; Disable interrupts
- POP {R2, R3, R12, LR} ; Restore handler address(R2), stack adjustment(R3) and user R12, LR
+ POP {R3, R4}
ADD SP, SP, R3 ; Unadjust stack
CPS #MODE_IRQ ; Change to IRQ mode
- POP {R0, R1} ; Restore IRQ ID and GIC CPU Interface base address
- DSB ; Ensure that interrupt source is cleared before signalling End Of Interrupt
+
IRQ_End
- ; R0 =IRQ ID, R1 =GICI_BASE
- ; EOI does not need to be written for IDs 1020 to 1023 (0x3FC to 0x3FF)
- STR R0, [R1, #ICCEOIR_OFFSET] ; Normal end-of-interrupt write to EOIR (GIC CPU Interface register) to clear the active bit
+ MOV R0, R4 ; Move interrupt ID to R0
+ BLX osRtxIrqSetEnd
- ; If it was ID0, clear the seen flag, otherwise return as normal
+ LDR R2, =IRQ_NestLevel
+ LDR R1, [R2] ; Load IRQ nest level and
+ SUBS R1, R1, #1 ; decrement it
+ STR R1, [R2]
+ BNE IRQ_Exit ; Not zero, exit from IRQ handler
+
+ LDR R0, =SVC_Active
+ LDRB R0, [R0] ; Load SVC_Active flag
CMP R0, #0
- LDREQ R1, =ID0_Active
- STRBEQ R0, [R1] ; Clear the seen flag, using R0 (which is 0), to save loading another register
+ BNE IRQ_SwitchCheck ; Skip post processing when SVC active
- LDR R3, =osRtxIrqHandler ; Load osRtxIrqHandler function address
- CMP R2, R3 ; If is the same ass current IRQ handler
- BEQ osRtxContextSwitch ; Call context switcher
+ ; RTX IRQ post processing check
+ PUSH {R5, R6} ; Save user R5 and R6
+ MOV R6, #0
+ LDR R5, =IRQ_PendSV ; Load address of IRQ_PendSV flag
+ B IRQ_PendCheck
+IRQ_PendExec
+ STRB R6, [R5] ; Clear PendSV flag
+ CPSIE i ; Re-enable interrupts
+ BLX osRtxPendSV_Handler ; Post process pending objects
+ CPSID i ; Disable interrupts
+IRQ_PendCheck
+ LDRB R0, [R5] ; Load PendSV flag
+ CMP R0, #1 ; Compare PendSV value
+ BEQ IRQ_PendExec ; Branch to IRQ_PendExec if PendSV is set
+ POP {R5, R6} ; Restore user R5 and R6
+
+IRQ_SwitchCheck
+ ; RTX IRQ context switch check
+ LDR R12, =osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.run
+ LDM R12, {R0, R1} ; Load osRtxInfo.thread.run: curr & next
+ CMP R0, R1 ; Check if context switch is required
+ BEQ IRQ_Exit
+
+ POP {R3, R4} ; Restore stack adjustment(R3) and user data(R4)
+ ADD SP, SP, R3 ; Unadjust stack
+ B osRtxContextSwitch
IRQ_Exit
+ POP {R3, R4} ; Restore stack adjustment(R3) and user data(R4)
+ ADD SP, SP, R3 ; Unadjust stack
+
POP {R0-R3, R12, LR} ; Restore stacked APCS registers
RFEFD SP! ; Return from IRQ handler
@@ -271,8 +264,9 @@
SVC_Handler\
PROC
EXPORT SVC_Handler
- IMPORT osRtxIrqLock
- IMPORT osRtxIrqUnlock
+ IMPORT osRtxIrqEnableTick
+ IMPORT osRtxIrqDisableTick
+ IMPORT osRtxPendSV_Handler
IMPORT osRtxUserSVC
IMPORT osRtxInfo
@@ -289,7 +283,10 @@
BNE SVC_User ; Branch if User SVC
PUSH {R0-R3}
- BLX osRtxIrqLock ; Disable RTX interrupt (timer, PendSV)
+ BLX osRtxIrqDisableTick ; Disable System Timer interrupt
+ LDR R0, =SVC_Active
+ MOV R1, #1
+ STRB R1, [R0] ; Set SVC_Active flag
POP {R0-R3}
LDR R12, [SP] ; Reload R12 from stack
@@ -305,7 +302,30 @@
LDMDB R12, {R2,R3} ; Load return values from SVC function
PUSH {R0-R3} ; Push return values to stack
- BLX osRtxIrqUnlock ; Enable RTX interrupt (timer, PendSV)
+ PUSH {R4, R5} ; Save R4 and R5
+ MOV R5, #0
+ LDR R4, =IRQ_PendSV ; Load address of IRQ_PendSV
+ B SVC_PendCheck
+SVC_PendExec
+ STRB R5, [R4] ; Clear IRQ_PendSV flag
+ CPSIE i ; Re-enable interrupts
+ BLX osRtxPendSV_Handler ; Post process pending objects
+ CPSID i ; Disable interrupts
+SVC_PendCheck
+ LDRB R0, [R4] ; Load IRQ_PendSV flag
+ CMP R0, #1 ; Compare IRQ_PendSV value
+ BEQ SVC_PendExec ; Branch to SVC_PendExec if IRQ_PendSV is set
+ POP {R4, R5} ; Restore R4 and R5
+
+ LDR R0, =SVC_Active
+ MOV R1, #0
+ STRB R1, [R0] ; Clear SVC_Active flag
+ BLX osRtxIrqEnableTick ; Enable System Timer interrupt
+
+ LDR R12, =osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.run
+ LDM R12, {R0, R1} ; Load osRtxInfo.thread.run: curr & next
+ CMP R0, R1 ; Check if context switch is required
+ BEQ osRtxContextExit ; Exit if curr and next are equal
B osRtxContextSwitch ; Continue in context switcher
SVC_User
@@ -329,10 +349,9 @@
PROC
EXPORT osRtxContextSwitch
- LDR R12, =osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.run
- LDM R12, {R0, R1} ; Load osRtxInfo.thread.run: curr & next
- CMP R0, R1 ; Check if context switch is required
- BEQ osRtxContextExit ; Exit if curr and next are equal
+ ; R0 = osRtxInfo.thread.run.curr
+ ; R1 = osRtxInfo.thread.run.next
+ ; R12 = &osRtxInfo.thread.run
CMP R0, #0 ; Is osRtxInfo.thread.run.curr == 0
ADDEQ SP, SP, #32 ; Equal, curr deleted, adjust current SP
diff --git a/CMSIS/RTOS2/RTX/Source/ARM/irq_cm0.s b/CMSIS/RTOS2/RTX/Source/ARM/irq_cm0.s
index 74c8a84..8fab32a 100644
--- a/CMSIS/RTOS2/RTX/Source/ARM/irq_cm0.s
+++ b/CMSIS/RTOS2/RTX/Source/ARM/irq_cm0.s
@@ -24,7 +24,7 @@
; */
-I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
+I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
diff --git a/CMSIS/RTOS2/RTX/Source/ARM/irq_cm3.s b/CMSIS/RTOS2/RTX/Source/ARM/irq_cm3.s
index b951538..2fd6618 100644
--- a/CMSIS/RTOS2/RTX/Source/ARM/irq_cm3.s
+++ b/CMSIS/RTOS2/RTX/Source/ARM/irq_cm3.s
@@ -24,7 +24,7 @@
; */
-I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
+I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
diff --git a/CMSIS/RTOS2/RTX/Source/ARM/irq_cm4f.s b/CMSIS/RTOS2/RTX/Source/ARM/irq_cm4f.s
index 746c7c1..f0df8aa 100644
--- a/CMSIS/RTOS2/RTX/Source/ARM/irq_cm4f.s
+++ b/CMSIS/RTOS2/RTX/Source/ARM/irq_cm4f.s
@@ -24,7 +24,7 @@
; */
-I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
+I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
TCB_SF_OFS EQU 34 ; TCB.stack_frame offset
diff --git a/CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mbl.S b/CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mbl.S
index c5f852d..497e5c9 100644
--- a/CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mbl.S
+++ b/CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mbl.S
@@ -31,7 +31,7 @@
.equ __DOMAIN_NS, 0
.endif
- .equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset
+ .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset
.equ TCB_SM_OFS, 48 // TCB.stack_mem offset
.equ TCB_SP_OFS, 56 // TCB.SP offset
.equ TCB_SF_OFS, 34 // TCB.stack_frame offset
diff --git a/CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mml.S b/CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mml.S
index c01721b..3248b9e 100644
--- a/CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mml.S
+++ b/CMSIS/RTOS2/RTX/Source/GCC/irq_armv8mml.S
@@ -35,7 +35,7 @@
.equ __FPU_USED, 0
.endif
- .equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset
+ .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset
.equ TCB_SM_OFS, 48 // TCB.stack_mem offset
.equ TCB_SP_OFS, 56 // TCB.SP offset
.equ TCB_SF_OFS, 34 // TCB.stack_frame offset
diff --git a/CMSIS/RTOS2/RTX/Source/GCC/irq_ca.S b/CMSIS/RTOS2/RTX/Source/GCC/irq_ca.S
index 4c54505..972a398 100644
--- a/CMSIS/RTOS2/RTX/Source/GCC/irq_ca.S
+++ b/CMSIS/RTOS2/RTX/Source/GCC/irq_ca.S
@@ -18,414 +18,433 @@
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
- * Title: Cortex-A Exception handlers (using GIC)
+ * Title: Cortex-A Exception handlers
*
* -----------------------------------------------------------------------------
*/
- .file "irq_ca.S"
- .syntax unified
+ .file "irq_ca.S"
+ .syntax unified
- .equ ICDABR0_OFFSET, 0x00000300 // GICD: Active Bit Register 0 offset
- .equ ICDIPR0_OFFSET, 0x00000400 // GICD: Interrupt Priority Register 0 offset
- .equ ICCIAR_OFFSET, 0x0000000C // GICI: Interrupt Acknowledge Register offset
- .equ ICCEOIR_OFFSET, 0x00000010 // GICI: End of Interrupt Register offset
- .equ ICCHPIR_OFFSET, 0x00000018 // GICI: Highest Pending Interrupt Register offset
+ .equ MODE_FIQ, 0x11
+ .equ MODE_IRQ, 0x12
+ .equ MODE_SVC, 0x13
+ .equ MODE_ABT, 0x17
+ .equ MODE_UND, 0x1B
- .equ MODE_FIQ, 0x11
- .equ MODE_IRQ, 0x12
- .equ MODE_SVC, 0x13
- .equ MODE_ABT, 0x17
- .equ MODE_UND, 0x1B
+ .equ CPSR_BIT_T, 0x20
- .equ CPSR_BIT_T, 0x20
-
- .equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset
- .equ TCB_SP_FRAME, 34 // osRtxThread_t.stack_frame offset
- .equ TCB_SP_OFS, 56 // osRtxThread_t.sp offset
+ .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset
+ .equ TCB_SP_FRAME, 34 // osRtxThread_t.stack_frame offset
+ .equ TCB_SP_OFS, 56 // osRtxThread_t.sp offset
- .section ".rodata"
- .global irqRtxLib // Non weak library reference
+ .section ".rodata"
+ .global irqRtxLib // Non weak library reference
irqRtxLib:
- .byte 0
+ .byte 0
- .section ".data"
-ID0_Active:
- .byte 4 // Flag used to workaround GIC 390 errata 733075
+ .section ".data"
+IRQ_NestLevel:
+ .word 0 // IRQ nesting level counter
+IRQ_PendSV:
+ .byte 0 // Pending SVC flag
+SVC_Active:
+ .byte 0 // SVC handler execution active flag
- .arm
- .section ".text"
- .align 4
+ .arm
+ .section ".text"
+ .align 4
- .type Undef_Handler, %function
- .global Undef_Handler
- .fnstart
- .cantunwind
+ .type Undef_Handler, %function
+ .global Undef_Handler
+ .fnstart
+ .cantunwind
Undef_Handler:
- SRSFD SP!, #MODE_UND
- PUSH {R0-R4, R12} // Save APCS corruptible registers to UND mode stack
+ SRSFD SP!, #MODE_UND
+ PUSH {R0-R4, R12} // Save APCS corruptible registers to UND mode stack
- MRS R0, SPSR
- TST R0, #CPSR_BIT_T // Check mode
- MOVEQ R1, #4 // R1 = 4 ARM mode
- MOVNE R1, #2 // R1 = 2 Thumb mode
- SUB R0, LR, R1
- LDREQ R0, [R0] // ARM mode - R0 points to offending instruction
- BEQ Undef_Cont
+ MRS R0, SPSR
+ TST R0, #CPSR_BIT_T // Check mode
+ MOVEQ R1, #4 // R1 = 4 ARM mode
+ MOVNE R1, #2 // R1 = 2 Thumb mode
+ SUB R0, LR, R1
+ LDREQ R0, [R0] // ARM mode - R0 points to offending instruction
+ BEQ Undef_Cont
- // Thumb instruction
- // Determine if it is a 32-bit Thumb instruction
- LDRH R0, [R0]
- MOV R2, #0x1C
- CMP R2, R0, LSR #11
- BHS Undef_Cont // 16-bit Thumb instruction
+ // Thumb instruction
+ // Determine if it is a 32-bit Thumb instruction
+ LDRH R0, [R0]
+ MOV R2, #0x1C
+ CMP R2, R0, LSR #11
+ BHS Undef_Cont // 16-bit Thumb instruction
- // 32-bit Thumb instruction. Unaligned - reconstruct the offending instruction
- LDRH R2, [LR]
- ORR R0, R2, R0, LSL #16
+ // 32-bit Thumb instruction. Unaligned - reconstruct the offending instruction
+ LDRH R2, [LR]
+ ORR R0, R2, R0, LSL #16
Undef_Cont:
- MOV R2, LR // Set LR to third argument
+ MOV R2, LR // Set LR to third argument
- AND R12, SP, #4 // Ensure stack is 8-byte aligned
- SUB SP, SP, R12 // Adjust stack
- PUSH {R12, LR} // Store stack adjustment and dummy LR
+ AND R12, SP, #4 // Ensure stack is 8-byte aligned
+ SUB SP, SP, R12 // Adjust stack
+ PUSH {R12, LR} // Store stack adjustment and dummy LR
- // R0 =Offending instruction, R1 =2(Thumb) or =4(ARM)
- BL CUndefHandler
+ // R0 =Offending instruction, R1 =2(Thumb) or =4(ARM)
+ BL CUndefHandler
- POP {R12, LR} // Get stack adjustment & discard dummy LR
- ADD SP, SP, R12 // Unadjust stack
+ POP {R12, LR} // Get stack adjustment & discard dummy LR
+ ADD SP, SP, R12 // Unadjust stack
- LDR LR, [SP, #24] // Restore stacked LR and possibly adjust for retry
- SUB LR, LR, R0
- LDR R0, [SP, #28] // Restore stacked SPSR
- MSR SPSR_cxsf, R0
- POP {R0-R4, R12} // Restore stacked APCS registers
- ADD SP, SP, #8 // Adjust SP for already-restored banked registers
- MOVS PC, LR
+ LDR LR, [SP, #24] // Restore stacked LR and possibly adjust for retry
+ SUB LR, LR, R0
+ LDR R0, [SP, #28] // Restore stacked SPSR
+ MSR SPSR_cxsf, R0
+ POP {R0-R4, R12} // Restore stacked APCS registers
+ ADD SP, SP, #8 // Adjust SP for already-restored banked registers
+ MOVS PC, LR
- .fnend
- .size Undef_Handler, .-Undef_Handler
+ .fnend
+ .size Undef_Handler, .-Undef_Handler
- .type PAbt_Handler, %function
- .global PAbt_Handler
- .fnstart
- .cantunwind
+ .type PAbt_Handler, %function
+ .global PAbt_Handler
+ .fnstart
+ .cantunwind
PAbt_Handler:
- SUB LR, LR, #4 // Pre-adjust LR
- SRSFD SP!, #MODE_ABT // Save LR and SPRS to ABT mode stack
- PUSH {R0-R4, R12} // Save APCS corruptible registers to ABT mode stack
- MRC p15, 0, R0, c5, c0, 1 // IFSR
- MRC p15, 0, R1, c6, c0, 2 // IFAR
+ SUB LR, LR, #4 // Pre-adjust LR
+ SRSFD SP!, #MODE_ABT // Save LR and SPRS to ABT mode stack
+ PUSH {R0-R4, R12} // Save APCS corruptible registers to ABT mode stack
+ MRC p15, 0, R0, c5, c0, 1 // IFSR
+ MRC p15, 0, R1, c6, c0, 2 // IFAR
- MOV R2, LR // Set LR to third argument
+ MOV R2, LR // Set LR to third argument
- AND R12, SP, #4 // Ensure stack is 8-byte aligned
- SUB SP, SP, R12 // Adjust stack
- PUSH {R12, LR} // Store stack adjustment and dummy LR
+ AND R12, SP, #4 // Ensure stack is 8-byte aligned
+ SUB SP, SP, R12 // Adjust stack
+ PUSH {R12, LR} // Store stack adjustment and dummy LR
- BL CPAbtHandler
+ BL CPAbtHandler
- POP {R12, LR} // Get stack adjustment & discard dummy LR
- ADD SP, SP, R12 // Unadjust stack
+ POP {R12, LR} // Get stack adjustment & discard dummy LR
+ ADD SP, SP, R12 // Unadjust stack
- POP {R0-R4, R12} // Restore stack APCS registers
- RFEFD SP! // Return from exception
+ POP {R0-R4, R12} // Restore stack APCS registers
+ RFEFD SP! // Return from exception
- .fnend
- .size PAbt_Handler, .-PAbt_Handler
+ .fnend
+ .size PAbt_Handler, .-PAbt_Handler
- .type DAbt_Handler, %function
- .global DAbt_Handler
- .fnstart
- .cantunwind
+ .type DAbt_Handler, %function
+ .global DAbt_Handler
+ .fnstart
+ .cantunwind
DAbt_Handler:
- SUB LR, LR, #8 // Pre-adjust LR
- SRSFD SP!, #MODE_ABT // Save LR and SPRS to ABT mode stack
- PUSH {R0-R4, R12} // Save APCS corruptible registers to ABT mode stack
- CLREX // State of exclusive monitors unknown after taken data abort
- MRC p15, 0, R0, c5, c0, 0 // DFSR
- MRC p15, 0, R1, c6, c0, 0 // DFAR
+ SUB LR, LR, #8 // Pre-adjust LR
+ SRSFD SP!, #MODE_ABT // Save LR and SPRS to ABT mode stack
+ PUSH {R0-R4, R12} // Save APCS corruptible registers to ABT mode stack
+ CLREX // State of exclusive monitors unknown after taken data abort
+ MRC p15, 0, R0, c5, c0, 0 // DFSR
+ MRC p15, 0, R1, c6, c0, 0 // DFAR
- MOV R2, LR // Set LR to third argument
+ MOV R2, LR // Set LR to third argument
- AND R12, SP, #4 // Ensure stack is 8-byte aligned
- SUB SP, SP, R12 // Adjust stack
- PUSH {R12, LR} // Store stack adjustment and dummy LR
+ AND R12, SP, #4 // Ensure stack is 8-byte aligned
+ SUB SP, SP, R12 // Adjust stack
+ PUSH {R12, LR} // Store stack adjustment and dummy LR
- BL CDAbtHandler
+ BL CDAbtHandler
- POP {R12, LR} // Get stack adjustment & discard dummy LR
- ADD SP, SP, R12 // Unadjust stack
+ POP {R12, LR} // Get stack adjustment & discard dummy LR
+ ADD SP, SP, R12 // Unadjust stack
- POP {R0-R4, R12} // Restore stacked APCS registers
- RFEFD SP! // Return from exception
+ POP {R0-R4, R12} // Restore stacked APCS registers
+ RFEFD SP! // Return from exception
- .fnend
- .size DAbt_Handler, .-DAbt_Handler
+ .fnend
+ .size DAbt_Handler, .-DAbt_Handler
- .type IRQ_Handler, %function
- .global IRQ_Handler
- .fnstart
- .cantunwind
+ .type IRQ_Handler, %function
+ .global IRQ_Handler
+ .fnstart
+ .cantunwind
IRQ_Handler:
- SUB LR, LR, #4 // Pre-adjust LR
- SRSFD SP!, #MODE_IRQ // Save LR_irq and SPRS_irq
- PUSH {R0-R3, R12, LR} // Save APCS corruptible registers
+ SUB LR, LR, #4 // Pre-adjust LR
+ SRSFD SP!, #MODE_IRQ // Save LR_irq and SPRS_irq
+ PUSH {R0-R3, R12, LR} // Save APCS corruptible registers
- // Identify and acknowledge interrupt
- LDR R1, =irqRtxGicBase;
- LDR R1, [R1, #4]
- LDR R0, [R1, #ICCHPIR_OFFSET] // Dummy Read GICI ICCHPIR to avoid GIC 390 errata 801120
- LDR R0, [R1, #ICCIAR_OFFSET] // Read GICI ICCIAR
- DSB // Ensure that interrupt acknowledge completes before re-enabling interrupts
+ MOV R3, SP // Move SP into R3
+ AND R3, R3, #4 // Get stack adjustment to ensure 8-byte alignment
+ SUB SP, SP, R3 // Adjust stack
+ PUSH {R3, R4} // Store stack adjustment(R3) and user data(R4)
- // Workaround GIC 390 errata 733075 - see GIC-390_Errata_Notice_v6.pdf dated 09-Jul-2014
- // The following workaround code is for a single-core system. It would be different in a multi-core system.
- // If the ID is 0 or 0x3FE or 0x3FF, then the GIC CPU interface may be locked-up so unlock it, otherwise service the interrupt as normal
- // Special IDs 1020=0x3FC and 1021=0x3FD are reserved values in GICv1 and GICv2 so will not occur here
- CMP R0, #0
- BEQ IRQ_Unlock
- MOVW R2, #0x3FE
- CMP R0, R2
- BLT IRQ_Normal
-IRQ_Unlock:
- // Unlock the CPU interface with a dummy write to ICDIPR0
- LDR R2, =irqRtxGicBase
- LDR R2, [R2]
- LDR R3, [R2, #ICDIPR0_OFFSET]
- STR R3, [R2, #ICDIPR0_OFFSET]
- DSB // Ensure the write completes before continuing
+ BLX osRtxIrqGetId // Retrieve interrupt ID into R0
+ CMP R0, #-1 // Check if interrupt valid
+ BEQ IRQ_Exit // Spurious interrupt if -1, exit IRQ
+ MOV R4, R0 // Move interrupt ID to R4
- // If the ID is 0 and it is active and has not been seen before, then service it as normal,
- // otherwise the interrupt should be treated as spurious and not serviced.
- CMP R0, #0
- BNE IRQ_Exit // Not 0, so spurious
- LDR R3, [R2, #ICDABR0_OFFSET] // Get the interrupt state
- TST R3, #1
- BEQ IRQ_Exit // Not active, so spurious
- LDR R2, =ID0_Active
- LDRB R3, [R2]
- CMP R3, #1
- BEQ IRQ_Exit // Seen it before, so spurious
+ LDR R1, =IRQ_NestLevel
+ LDR R3, [R1] // Load IRQ nest level and increment it
+ ADD R3, R3, #1
+ STR R3, [R1]
- // Record that ID0 has now been seen, then service it as normal
- MOV R3, #1
- STRB R3, [R2]
- // End of Workaround GIC 390 errata 733075
+ BLX osRtxIrqGetHandler // Retrieve interrupt handler address for current ID
+ CMP R0, #0 // Check if handler address is 0
+ BEQ IRQ_End // If 0, end interrupt and return
-IRQ_Normal:
- LDR R2, =IRQCount // Read number of entries in IRQ handler table
- LDR R2, [R2]
- CMP R0, R2 // Check if IRQ ID is within range
- MOV R2, #0
- BHS IRQ_End // Out of range, return as normal
- LDR R2, =IRQTable // Read IRQ handler address from IRQ table
- LDR R2, [R2, R0, LSL #2]
- CMP R2, #0 // Check if handler address is 0
- BEQ IRQ_End // If 0, end interrupt and return
- PUSH {R0, R1} // Store IRQ ID and GIC CPU Interface base address
+ CPS #MODE_SVC // Change to SVC mode
- CPS #MODE_SVC // Change to SVC mode
+ MOV R3, SP // Move SP into R3
+ AND R3, R3, #4 // Get stack adjustment to ensure 8-byte alignment
+ SUB SP, SP, R3 // Adjust stack
+ PUSH {R3, R4} // Store stack adjustment(R3) and alignment dummy(R4)
- MOV R3, SP // Move SP into R3
- AND R3, R3, #4 // Get stack adjustment to ensure 8-byte alignment
- SUB SP, SP, R3 // Adjust stack
- PUSH {R2, R3, R12, LR} // Store handler address(R2), stack adjustment(R3) and user R12, LR
+ CPSIE i // Re-enable interrupts
+ BLX R0 // Call IRQ handler
+ CPSID i // Disable interrupts
- CPSIE i // Re-enable interrupts
- BLX R2 // Call IRQ handler
- CPSID i // Disable interrupts
+ POP {R3, R4}
+ ADD SP, SP, R3 // Unadjust stack
- POP {R2, R3, R12, LR} // Restore handler address(R2), stack adjustment(R3) and user R12, LR
- ADD SP, SP, R3 // Unadjust stack
+ CPS #MODE_IRQ // Change to IRQ mode
- CPS #MODE_IRQ // Change to IRQ mode
- POP {R0, R1} // Restore IRQ ID and GIC CPU Interface base address
- DSB // Ensure that interrupt source is cleared before signalling End Of Interrupt
IRQ_End:
- // R0 =IRQ ID, R1 =GICI_BASE
- // EOI does not need to be written for IDs 1020 to 1023 (0x3FC to 0x3FF)
- STR R0, [R1, #ICCEOIR_OFFSET] // Normal end-of-interrupt write to EOIR (GIC CPU Interface register) to clear the active bit
+ MOV R0, R4 // Move interrupt ID to R0
+ BLX osRtxIrqSetEnd
- // If it was ID0, clear the seen flag, otherwise return as normal
- CMP R0, #0
- LDREQ R1, =ID0_Active
- STRBEQ R0, [R1] // Clear the seen flag, using R0 (which is 0), to save loading another register
+ LDR R2, =IRQ_NestLevel
+ LDR R1, [R2] // Load IRQ nest level and
+ SUBS R1, R1, #1 // decrement it
+ STR R1, [R2]
+ BNE IRQ_Exit // Not zero, exit from IRQ handler
- LDR R3, =osRtxIrqHandler // Load osRtxIrqHandler function address
- CMP R2, R3 // If is the same ass current IRQ handler
- BEQ osRtxContextSwitch // Call context switcher
+ LDR R0, =SVC_Active
+ LDRB R0, [R0] // Load SVC_Active flag
+ CMP R0, #0
+ BNE IRQ_SwitchCheck // Skip post processing when SVC active
+
+ // RTX IRQ post processing check
+ PUSH {R5, R6} // Save user R5 and R6
+ MOV R6, #0
+ LDR R5, =IRQ_PendSV // Load address of IRQ_PendSV flag
+ B IRQ_PendCheck
+IRQ_PendExec:
+ STRB R6, [R5] // Clear PendSV flag
+ CPSIE i // Re-enable interrupts
+ BLX osRtxPendSV_Handler // Post process pending objects
+ CPSID i // Disable interrupts
+IRQ_PendCheck:
+ LDRB R0, [R5] // Load PendSV flag
+ CMP R0, #1 // Compare PendSV value
+ BEQ IRQ_PendExec // Branch to IRQ_PendExec if PendSV is set
+ POP {R5, R6} // Restore user R5 and R6
+
+IRQ_SwitchCheck:
+ // RTX IRQ context switch check
+ LDR R12, =osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
+ LDM R12, {R0, R1} // Load osRtxInfo.thread.run: curr & next
+ CMP R0, R1 // Check if context switch is required
+ BEQ IRQ_Exit
+
+ POP {R3, R4} // Restore stack adjustment(R3) and user data(R4)
+ ADD SP, SP, R3 // Unadjust stack
+ B osRtxContextSwitch
IRQ_Exit:
- POP {R0-R3, R12, LR} // Restore stacked APCS registers
- RFEFD SP! // Return from IRQ handler
+ POP {R3, R4} // Restore stack adjustment(R3) and user data(R4)
+ ADD SP, SP, R3 // Unadjust stack
- .fnend
- .size IRQ_Handler, .-IRQ_Handler
+ POP {R0-R3, R12, LR} // Restore stacked APCS registers
+ RFEFD SP! // Return from IRQ handler
+
+ .fnend
+ .size IRQ_Handler, .-IRQ_Handler
- .type SVC_Handler, %function
- .global SVC_Handler
- .fnstart
- .cantunwind
+ .type SVC_Handler, %function
+ .global SVC_Handler
+ .fnstart
+ .cantunwind
SVC_Handler:
- SRSFD SP!, #MODE_SVC // Store SPSR_svc and LR_svc onto SVC stack
- PUSH {R12, LR}
+ SRSFD SP!, #MODE_SVC // Store SPSR_svc and LR_svc onto SVC stack
+ PUSH {R12, LR}
- MRS R12, SPSR // Load SPSR
- TST R12, #CPSR_BIT_T // Thumb bit set?
- LDRHNE R12, [LR,#-2] // Thumb: load halfword
- BICNE R12, R12, #0xFF00 // extract SVC number
- LDREQ R12, [LR,#-4] // ARM: load word
- BICEQ R12, R12, #0xFF000000 // extract SVC number
- CMP R12, #0 // Compare SVC number
- BNE SVC_User // Branch if User SVC
+ MRS R12, SPSR // Load SPSR
+ TST R12, #CPSR_BIT_T // Thumb bit set?
+ LDRHNE R12, [LR,#-2] // Thumb: load halfword
+ BICNE R12, R12, #0xFF00 // extract SVC number
+ LDREQ R12, [LR,#-4] // ARM: load word
+ BICEQ R12, R12, #0xFF000000 // extract SVC number
+ CMP R12, #0 // Compare SVC number
+ BNE SVC_User // Branch if User SVC
- PUSH {R0-R3}
- BLX osRtxIrqLock // Disable RTX interrupt (timer, PendSV)
- POP {R0-R3}
+ PUSH {R0-R3}
+ BLX osRtxIrqDisableTick // Disable System Timer interrupt
+ LDR R0, =SVC_Active
+ MOV R1, #1
+ STRB R1, [R0] // Set SVC_Active flag
+ POP {R0-R3}
- LDR R12, [SP] // Reload R12 from stack
+ LDR R12, [SP] // Reload R12 from stack
- CPSIE i // Re-enable interrupts
- BLX R12 // Branch to SVC function
- CPSID i // Disable interrupts
+ CPSIE i // Re-enable interrupts
+ BLX R12 // Branch to SVC function
+ CPSID i // Disable interrupts
- SUB SP, SP, #4 // Adjust SP
- STM SP, {SP}^ // Store SP_usr onto stack
- POP {R12} // Pop SP_usr into R12
- SUB R12, R12, #16 // Adjust pointer to SP_usr
- LDMDB R12, {R2,R3} // Load return values from SVC function
- PUSH {R0-R3} // Push return values to stack
+ SUB SP, SP, #4 // Adjust SP
+ STM SP, {SP}^ // Store SP_usr onto stack
+ POP {R12} // Pop SP_usr into R12
+ SUB R12, R12, #16 // Adjust pointer to SP_usr
+ LDMDB R12, {R2,R3} // Load return values from SVC function
+ PUSH {R0-R3} // Push return values to stack
- BLX osRtxIrqUnlock // Enable RTX interrupt (timer, PendSV)
- B osRtxContextSwitch // Continue in context switcher
+ PUSH {R4, R5} // Save R4 and R5
+ MOV R5, #0
+ LDR R4, =IRQ_PendSV // Load address of IRQ_PendSV
+ B SVC_PendCheck
+SVC_PendExec:
+ STRB R5, [R4] // Clear IRQ_PendSV flag
+ CPSIE i // Re-enable interrupts
+ BLX osRtxPendSV_Handler // Post process pending objects
+ CPSID i // Disable interrupts
+SVC_PendCheck:
+ LDRB R0, [R4] // Load IRQ_PendSV flag
+ CMP R0, #1 // Compare IRQ_PendSV value
+ BEQ SVC_PendExec // Branch to SVC_PendExec if IRQ_PendSV is set
+ POP {R4, R5} // Restore R4 and R5
+
+ LDR R0, =SVC_Active
+ MOV R1, #0
+ STRB R1, [R0] // Clear SVC_Active flag
+ BLX osRtxIrqEnableTick // Enable System Timer interrupt
+
+ LDR R12, =osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
+ LDM R12, {R0, R1} // Load osRtxInfo.thread.run: curr & next
+ CMP R0, R1 // Check if context switch is required
+ BEQ osRtxContextExit // Exit if curr and next are equal
+ B osRtxContextSwitch // Continue in context switcher
SVC_User:
- PUSH {R4, R5}
- LDR R5,=osRtxUserSVC // Load address of SVC table
- LDR R4,[R5] // Load SVC maximum number
- CMP R12,R4 // Check SVC number range
- BHI SVC_Done // Branch if out of range
+ PUSH {R4, R5}
+ LDR R5,=osRtxUserSVC // Load address of SVC table
+ LDR R4,[R5] // Load SVC maximum number
+ CMP R12,R4 // Check SVC number range
+ BHI SVC_Done // Branch if out of range
- LDR R12,[R5,R12,LSL #2] // Load SVC Function Address
- BLX R12 // Call SVC Function
+ LDR R12,[R5,R12,LSL #2] // Load SVC Function Address
+ BLX R12 // Call SVC Function
SVC_Done:
- POP {R4, R5, R12, LR}
- RFEFD SP! // Return from exception
+ POP {R4, R5, R12, LR}
+ RFEFD SP! // Return from exception
- .fnend
- .size SVC_Handler, .-SVC_Handler
+ .fnend
+ .size SVC_Handler, .-SVC_Handler
- .type osRtxContextSwitch, %function
- .global osRtxContextSwitch
- .fnstart
- .cantunwind
+ .type osRtxContextSwitch, %function
+ .global osRtxContextSwitch
+ .fnstart
+ .cantunwind
osRtxContextSwitch:
- LDR R12,=osRtxInfo+I_T_RUN_OFS // Load address of osRtxInfo.run
- LDM R12, {R0, R1} // Load osRtxInfo.thread.run: curr & next
- CMP R0, R1 // Check if context switch is required
- BEQ osRtxContextExit // Exit if curr and next are equal
+ // R0 = osRtxInfo.thread.run.curr
+ // R1 = osRtxInfo.thread.run.next
+ // R12 = &osRtxInfo.thread.run
- CMP R0, #0 // Is osRtxInfo.thread.run.curr == 0
- ADDEQ SP, SP, #32 // Equal, curr deleted, adjust current SP
- BEQ osRtxContextRestore // Restore context, run.curr = run.next;
+ CMP R0, #0 // Is osRtxInfo.thread.run.curr == 0
+ ADDEQ SP, SP, #32 // Equal, curr deleted, adjust current SP
+ BEQ osRtxContextRestore // Restore context, run.curr = run.next;
osRtxContextSave:
- SUB SP, SP, #4
- STM SP, {SP}^ // Save SP_usr to current stack
- POP {R3} // Pop SP_usr into R3
+ SUB SP, SP, #4
+ STM SP, {SP}^ // Save SP_usr to current stack
+ POP {R3} // Pop SP_usr into R3
- SUB R3, R3, #64 // Adjust user sp to end of basic frame (R4)
- STMIA R3!, {R4-R11} // Save R4-R11 to user
- POP {R4-R8} // Pop current R0-R12 into R4-R8
- STMIA R3!, {R4-R8} // Store them to user stack
- STM R3, {LR}^ // Store LR_usr directly
- ADD R3, R3, #4 // Adjust user sp to PC
- POP {R4-R6} // Pop current LR, PC, CPSR
- STMIA R3!, {R5-R6} // Restore user PC and CPSR
+ SUB R3, R3, #64 // Adjust user sp to end of basic frame (R4)
+ STMIA R3!, {R4-R11} // Save R4-R11 to user
+ POP {R4-R8} // Pop current R0-R12 into R4-R8
+ STMIA R3!, {R4-R8} // Store them to user stack
+ STM R3, {LR}^ // Store LR_usr directly
+ ADD R3, R3, #4 // Adjust user sp to PC
+ POP {R4-R6} // Pop current LR, PC, CPSR
+ STMIA R3!, {R5-R6} // Restore user PC and CPSR
- SUB R3, R3, #64 // Adjust user sp to R4
+ SUB R3, R3, #64 // Adjust user sp to R4
- // Check if VFP state need to be saved
- MRC p15, 0, R2, c1, c0, 2 // VFP/NEON access enabled? (CPACR)
- AND R2, R2, #0x00F00000
- CMP R2, #0x00F00000
- BNE osRtxContextSave1 // Continue, no VFP
+ // Check if VFP state need to be saved
+ MRC p15, 0, R2, c1, c0, 2 // VFP/NEON access enabled? (CPACR)
+ AND R2, R2, #0x00F00000
+ CMP R2, #0x00F00000
+ BNE osRtxContextSave1 // Continue, no VFP
- VMRS R2, FPSCR
- STMDB R3!, {R2,R12} // Push FPSCR, maintain 8-byte alignment
- #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 16
- VSTMDB R3!, {D0-D15}
- LDRB R2, [R0, #TCB_SP_FRAME] // Record in TCB that VFP/D16 state is stacked
- ORR R2, R2, #2
- STRB R2, [R0, #TCB_SP_FRAME]
- #endif
- #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
- VSTMDB R3!, {D0-D15}
- VSTMDB R3!, {D16-D31}
- LDRB R2, [R0, #TCB_SP_FRAME] // Record in TCB that NEON/D32 state is stacked
- ORR R2, R2, #4
- STRB R2, [R0, #TCB_SP_FRAME]
- #endif
+ VMRS R2, FPSCR
+ STMDB R3!, {R2,R12} // Push FPSCR, maintain 8-byte alignment
+ #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 16
+ VSTMDB R3!, {D0-D15}
+ LDRB R2, [R0, #TCB_SP_FRAME] // Record in TCB that VFP/D16 state is stacked
+ ORR R2, R2, #2
+ STRB R2, [R0, #TCB_SP_FRAME]
+ #endif
+ #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
+ VSTMDB R3!, {D0-D15}
+ VSTMDB R3!, {D16-D31}
+ LDRB R2, [R0, #TCB_SP_FRAME] // Record in TCB that NEON/D32 state is stacked
+ ORR R2, R2, #4
+ STRB R2, [R0, #TCB_SP_FRAME]
+ #endif
osRtxContextSave1:
- STR R3, [R0, #TCB_SP_OFS] // Store user sp to osRtxInfo.thread.run.curr
+ STR R3, [R0, #TCB_SP_OFS] // Store user sp to osRtxInfo.thread.run.curr
osRtxContextRestore:
- STR R1, [R12] // Store run.next to run.curr
- LDR R3, [R1, #TCB_SP_OFS] // Load next osRtxThread_t.sp
- LDRB R2, [R1, #TCB_SP_FRAME] // Load next osRtxThread_t.stack_frame
+ STR R1, [R12] // Store run.next to run.curr
+ LDR R3, [R1, #TCB_SP_OFS] // Load next osRtxThread_t.sp
+ LDRB R2, [R1, #TCB_SP_FRAME] // Load next osRtxThread_t.stack_frame
- ANDS R2, R2, #0x6 // Check stack frame for VFP context
- MRC p15, 0, R2, c1, c0, 2 // Read CPACR
- ANDEQ R2, R2, #0xFF0FFFFF // Disable VFP/NEON access if incoming task does not have stacked VFP/NEON state
- ORRNE R2, R2, #0x00F00000 // Enable VFP/NEON access if incoming task does have stacked VFP/NEON state
- MCR p15, 0, R2, c1, c0, 2 // Write CPACR
- BEQ osRtxContextRestore1 // No VFP
- ISB // Only sync if we enabled VFP, otherwise we will context switch before next VFP instruction anyway
- #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
- VLDMIA R3!, {D16-D31}
- #endif
- VLDMIA R3!, {D0-D15}
- LDR R2, [R3]
- VMSR FPSCR, R2
- ADD R3, R3, #8
+ ANDS R2, R2, #0x6 // Check stack frame for VFP context
+ MRC p15, 0, R2, c1, c0, 2 // Read CPACR
+ ANDEQ R2, R2, #0xFF0FFFFF // Disable VFP/NEON access if incoming task does not have stacked VFP/NEON state
+ ORRNE R2, R2, #0x00F00000 // Enable VFP/NEON access if incoming task does have stacked VFP/NEON state
+ MCR p15, 0, R2, c1, c0, 2 // Write CPACR
+ BEQ osRtxContextRestore1 // No VFP
+ ISB // Only sync if we enabled VFP, otherwise we will context switch before next VFP instruction anyway
+ #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
+ VLDMIA R3!, {D16-D31}
+ #endif
+ VLDMIA R3!, {D0-D15}
+ LDR R2, [R3]
+ VMSR FPSCR, R2
+ ADD R3, R3, #8
osRtxContextRestore1:
- LDMIA R3!, {R4-R11} // Restore R4-R11
- MOV R12, R3 // Move sp pointer to R12
- ADD R3, R3, #32 // Adjust sp
- PUSH {R3} // Push sp onto stack
- LDMIA SP, {SP}^ // Restore SP_usr
- LDMIA R12!, {R0-R3} // Restore User R0-R3
- LDR LR, [R12, #12] // Load SPSR into LR
- MSR SPSR_cxsf, LR // Restore SPSR
- ADD R12, R12, #4 // Adjust pointer to LR
- LDM R12, {LR}^ // Restore LR_usr directly into LR
- LDR LR, [R12, #4] // Restore LR
- LDR R12, [R12, #-4] // Restore R12
+ LDMIA R3!, {R4-R11} // Restore R4-R11
+ MOV R12, R3 // Move sp pointer to R12
+ ADD R3, R3, #32 // Adjust sp
+ PUSH {R3} // Push sp onto stack
+ LDMIA SP, {SP}^ // Restore SP_usr
+ LDMIA R12!, {R0-R3} // Restore User R0-R3
+ LDR LR, [R12, #12] // Load SPSR into LR
+ MSR SPSR_cxsf, LR // Restore SPSR
+ ADD R12, R12, #4 // Adjust pointer to LR
+ LDM R12, {LR}^ // Restore LR_usr directly into LR
+ LDR LR, [R12, #4] // Restore LR
+ LDR R12, [R12, #-4] // Restore R12
- MOVS PC, LR // Return from exception
+ MOVS PC, LR // Return from exception
osRtxContextExit:
- POP {R0-R3, R12, LR} // Restore stacked APCS registers
- RFEFD SP! // Return from exception
+ POP {R0-R3, R12, LR} // Restore stacked APCS registers
+ RFEFD SP! // Return from exception
- .fnend
- .size osRtxContextSwitch, .-osRtxContextSwitch
+ .fnend
+ .size osRtxContextSwitch, .-osRtxContextSwitch
- .end
+ .end
diff --git a/CMSIS/RTOS2/RTX/Source/GCC/irq_cm0.S b/CMSIS/RTOS2/RTX/Source/GCC/irq_cm0.S
index 5362c19..59288e2 100644
--- a/CMSIS/RTOS2/RTX/Source/GCC/irq_cm0.S
+++ b/CMSIS/RTOS2/RTX/Source/GCC/irq_cm0.S
@@ -27,7 +27,7 @@
.file "irq_cm0.S"
.syntax unified
- .equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset
+ .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset
.equ TCB_SP_OFS, 56 // TCB.SP offset
.section ".rodata"
diff --git a/CMSIS/RTOS2/RTX/Source/GCC/irq_cm3.S b/CMSIS/RTOS2/RTX/Source/GCC/irq_cm3.S
index 22ccf36..0bdf091 100644
--- a/CMSIS/RTOS2/RTX/Source/GCC/irq_cm3.S
+++ b/CMSIS/RTOS2/RTX/Source/GCC/irq_cm3.S
@@ -27,7 +27,7 @@
.file "irq_cm3.S"
.syntax unified
- .equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset
+ .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset
.equ TCB_SP_OFS, 56 // TCB.SP offset
.section ".rodata"
diff --git a/CMSIS/RTOS2/RTX/Source/GCC/irq_cm4f.S b/CMSIS/RTOS2/RTX/Source/GCC/irq_cm4f.S
index 23942f7..8d10213 100644
--- a/CMSIS/RTOS2/RTX/Source/GCC/irq_cm4f.S
+++ b/CMSIS/RTOS2/RTX/Source/GCC/irq_cm4f.S
@@ -27,7 +27,7 @@
.file "irq_cm4f.S"
.syntax unified
- .equ I_T_RUN_OFS, 28 // osRtxInfo.thread.run offset
+ .equ I_T_RUN_OFS, 20 // osRtxInfo.thread.run offset
.equ TCB_SP_OFS, 56 // TCB.SP offset
.equ TCB_SF_OFS, 34 // TCB.stack_frame offset
diff --git a/CMSIS/RTOS2/RTX/Source/IAR/irq_ca.s b/CMSIS/RTOS2/RTX/Source/IAR/irq_ca.s
index aa8dbfc..324fcbc 100644
--- a/CMSIS/RTOS2/RTX/Source/IAR/irq_ca.s
+++ b/CMSIS/RTOS2/RTX/Source/IAR/irq_ca.s
@@ -18,19 +18,13 @@
; * -----------------------------------------------------------------------------
; *
; * Project: CMSIS-RTOS RTX
-; * Title: Cortex-A Exception handlers (using GIC)
+; * Title: Cortex-A Exception handlers
; *
; * -----------------------------------------------------------------------------
; */
NAME irq_ca.s
-ICDABR0_OFFSET EQU 0x00000300 ; GICD: Active Bit Register 0 offset
-ICDIPR0_OFFSET EQU 0x00000400 ; GICD: Interrupt Priority Register 0 offset
-ICCIAR_OFFSET EQU 0x0000000C ; GICI: Interrupt Acknowledge Register offset
-ICCEOIR_OFFSET EQU 0x00000010 ; GICI: End of Interrupt Register offset
-ICCHPIR_OFFSET EQU 0x00000018 ; GICI: Highest Pending Interrupt Register offset
-
MODE_FIQ EQU 0x11
MODE_IRQ EQU 0x12
MODE_SVC EQU 0x13
@@ -39,7 +33,7 @@
CPSR_BIT_T EQU 0x20
-I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
+I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
TCB_SP_FRAME EQU 34 ; osRtxThread_t.stack_frame offset
TCB_SP_OFS EQU 56 ; osRtxThread_t.sp offset
@@ -54,7 +48,10 @@
SECTION .data:DATA:NOROOT(2)
-ID0_Active DCB 4 ; Flag used to workaround GIC 390 errata 733075
+ EXPORT IRQ_PendSV
+IRQ_NestLevel DCD 0 ; IRQ nesting level counter
+IRQ_PendSV DCB 0 ; Pending SVC flag
+SVC_Active DCB 0 ; SVC handler execution active flag
SECTION .text:CODE:NOROOT(2)
@@ -160,108 +157,105 @@
IRQ_Handler
EXPORT IRQ_Handler
- IMPORT IRQTable
- IMPORT IRQCount
- IMPORT osRtxIrqHandler
- IMPORT irqRtxGicBase
+ IMPORT osRtxInfo
+ IMPORT osRtxIrqGetId
+ IMPORT osRtxIrqGetHandler
+ IMPORT osRtxIrqSetEnd
SUB LR, LR, #4 ; Pre-adjust LR
SRSFD SP!, #MODE_IRQ ; Save LR_irq and SPRS_irq
PUSH {R0-R3, R12, LR} ; Save APCS corruptible registers
- ; Identify and acknowledge interrupt
- LDR R1, =irqRtxGicBase;
- LDR R1, [R1, #4]
- LDR R0, [R1, #ICCHPIR_OFFSET] ; Dummy Read GICI ICCHPIR to avoid GIC 390 errata 801120
- LDR R0, [R1, #ICCIAR_OFFSET] ; Read GICI ICCIAR
- DSB ; Ensure that interrupt acknowledge completes before re-enabling interrupts
+ MOV R3, SP ; Move SP into R3
+ AND R3, R3, #4 ; Get stack adjustment to ensure 8-byte alignment
+ SUB SP, SP, R3 ; Adjust stack
+ PUSH {R3, R4} ; Store stack adjustment(R3) and user data(R4)
- ; Workaround GIC 390 errata 733075 - see GIC-390_Errata_Notice_v6.pdf dated 09-Jul-2014
- ; The following workaround code is for a single-core system. It would be different in a multi-core system.
- ; If the ID is 0 or 0x3FE or 0x3FF, then the GIC CPU interface may be locked-up so unlock it, otherwise service the interrupt as normal
- ; Special IDs 1020=0x3FC and 1021=0x3FD are reserved values in GICv1 and GICv2 so will not occur here
- CMP R0, #0
- BEQ IRQ_Unlock
- MOV R2, #0x3FE
- CMP R0, R2
- BLT IRQ_Normal
-IRQ_Unlock
- ; Unlock the CPU interface with a dummy write to ICDIPR0
- LDR R2, =irqRtxGicBase
- LDR R2, [R2]
- LDR R3, [R2, #ICDIPR0_OFFSET]
- STR R3, [R2, #ICDIPR0_OFFSET]
- DSB ; Ensure the write completes before continuing
+ BLX osRtxIrqGetId ; Retrieve interrupt ID into R0
+ CMP R0, #-1 ; Check if interrupt valid
+ BEQ IRQ_Exit ; Spurious interrupt if -1, exit IRQ
+ MOV R4, R0 ; Move interrupt ID to R4
- ; If the ID is 0 and it is active and has not been seen before, then service it as normal,
- ; otherwise the interrupt should be treated as spurious and not serviced.
- CMP R0, #0
- BNE IRQ_Exit ; Not 0, so spurious
- LDR R3, [R2, #ICDABR0_OFFSET] ; Get the interrupt state
- TST R3, #1
- BEQ IRQ_Exit ; Not active, so spurious
- LDR R2, =ID0_Active
- LDRB R3, [R2]
- CMP R3, #1
- BEQ IRQ_Exit ; Seen it before, so spurious
+ LDR R1, =IRQ_NestLevel
+ LDR R3, [R1] ; Load IRQ nest level and increment it
+ ADD R3, R3, #1
+ STR R3, [R1]
- ; Record that ID0 has now been seen, then service it as normal
- MOV R3, #1
- STRB R3, [R2]
- ; End of Workaround GIC 390 errata 733075
-
-IRQ_Normal
- LDR R2, =IRQCount ; Read number of entries in IRQ handler table
- LDR R2, [R2]
- CMP R0, R2 ; Check if IRQ ID is within range
- MOV R2, #0
- BHS IRQ_End ; Out of range, return as normal
- LDR R2, =IRQTable ; Read IRQ handler address from IRQ table
- LDR R2, [R2, R0, LSL #2]
- CMP R2, #0 ; Check if handler address is 0
+ BLX osRtxIrqGetHandler ; Retrieve interrupt handler address for current ID
+ CMP R0, #0 ; Check if handler address is 0
BEQ IRQ_End ; If 0, end interrupt and return
- PUSH {R0, R1} ; Store IRQ ID and GIC CPU Interface base address
CPS #MODE_SVC ; Change to SVC mode
MOV R3, SP ; Move SP into R3
AND R3, R3, #4 ; Get stack adjustment to ensure 8-byte alignment
SUB SP, SP, R3 ; Adjust stack
- PUSH {R2, R3, R12, LR} ; Store handler address(R2), stack adjustment(R3) and user R12, LR
+ PUSH {R3, R4} ; Store stack adjustment(R3) and alignment dummy(R4)
CPSIE i ; Re-enable interrupts
- BLX R2 ; Call IRQ handler
+ BLX R0 ; Call IRQ handler
CPSID i ; Disable interrupts
- POP {R2, R3, R12, LR} ; Restore handler address(R2), stack adjustment(R3) and user R12, LR
+ POP {R3, R4}
ADD SP, SP, R3 ; Unadjust stack
CPS #MODE_IRQ ; Change to IRQ mode
- POP {R0, R1} ; Restore IRQ ID and GIC CPU Interface base address
- DSB ; Ensure that interrupt source is cleared before signalling End Of Interrupt
+
IRQ_End
- ; R0 =IRQ ID, R1 =GICI_BASE
- ; EOI does not need to be written for IDs 1020 to 1023 (0x3FC to 0x3FF)
- STR R0, [R1, #ICCEOIR_OFFSET] ; Normal end-of-interrupt write to EOIR (GIC CPU Interface register) to clear the active bit
+ MOV R0, R4 ; Move interrupt ID to R0
+ BLX osRtxIrqSetEnd
- ; If it was ID0, clear the seen flag, otherwise return as normal
+ LDR R2, =IRQ_NestLevel
+ LDR R1, [R2] ; Load IRQ nest level and
+ SUBS R1, R1, #1 ; decrement it
+ STR R1, [R2]
+ BNE IRQ_Exit ; Not zero, exit from IRQ handler
+
+ LDR R0, =SVC_Active
+ LDRB R0, [R0] ; Load SVC_Active flag
CMP R0, #0
- LDREQ R1, =ID0_Active
- STRBEQ R0, [R1] ; Clear the seen flag, using R0 (which is 0), to save loading another register
+ BNE IRQ_SwitchCheck ; Skip post processing when SVC active
- LDR R3, =osRtxIrqHandler ; Load osRtxIrqHandler function address
- CMP R2, R3 ; If is the same ass current IRQ handler
- BEQ osRtxContextSwitch ; Call context switcher
+ ; RTX IRQ post processing check
+ PUSH {R5, R6} ; Save user R5 and R6
+ MOV R6, #0
+ LDR R5, =IRQ_PendSV ; Load address of IRQ_PendSV flag
+ B IRQ_PendCheck
+IRQ_PendExec
+ STRB R6, [R5] ; Clear PendSV flag
+ CPSIE i ; Re-enable interrupts
+ BLX osRtxPendSV_Handler ; Post process pending objects
+ CPSID i ; Disable interrupts
+IRQ_PendCheck
+ LDRB R0, [R5] ; Load PendSV flag
+ CMP R0, #1 ; Compare PendSV value
+ BEQ IRQ_PendExec ; Branch to IRQ_PendExec if PendSV is set
+ POP {R5, R6} ; Restore user R5 and R6
+
+IRQ_SwitchCheck
+ ; RTX IRQ context switch check
+ LDR R12, =osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.run
+ LDM R12, {R0, R1} ; Load osRtxInfo.thread.run: curr & next
+ CMP R0, R1 ; Check if context switch is required
+ BEQ IRQ_Exit
+
+ POP {R3, R4} ; Restore stack adjustment(R3) and user data(R4)
+ ADD SP, SP, R3 ; Unadjust stack
+ B osRtxContextSwitch
IRQ_Exit
+ POP {R3, R4} ; Restore stack adjustment(R3) and user data(R4)
+ ADD SP, SP, R3 ; Unadjust stack
+
POP {R0-R3, R12, LR} ; Restore stacked APCS registers
RFEFD SP! ; Return from IRQ handler
-
+
SVC_Handler
EXPORT SVC_Handler
- IMPORT osRtxIrqLock
- IMPORT osRtxIrqUnlock
+ IMPORT osRtxIrqEnableTick
+ IMPORT osRtxIrqDisableTick
+ IMPORT osRtxPendSV_Handler
IMPORT osRtxUserSVC
IMPORT osRtxInfo
@@ -278,7 +272,10 @@
BNE SVC_User ; Branch if User SVC
PUSH {R0-R3}
- BLX osRtxIrqLock ; Disable RTX interrupt (timer, PendSV)
+ BLX osRtxIrqDisableTick ; Disable System Timer interrupt
+ LDR R0, =SVC_Active
+ MOV R1, #1
+ STRB R1, [R0] ; Set SVC_Active flag
POP {R0-R3}
LDR R12, [SP] ; Reload R12 from stack
@@ -294,7 +291,30 @@
LDMDB R12, {R2,R3} ; Load return values from SVC function
PUSH {R0-R3} ; Push return values to stack
- BLX osRtxIrqUnlock ; Enable RTX interrupt (timer, PendSV)
+ PUSH {R4, R5} ; Save R4 and R5
+ MOV R5, #0
+ LDR R4, =IRQ_PendSV ; Load address of IRQ_PendSV
+ B SVC_PendCheck
+SVC_PendExec
+ STRB R5, [R4] ; Clear IRQ_PendSV flag
+ CPSIE i ; Re-enable interrupts
+ BLX osRtxPendSV_Handler ; Post process pending objects
+ CPSID i ; Disable interrupts
+SVC_PendCheck
+ LDRB R0, [R4] ; Load IRQ_PendSV flag
+ CMP R0, #1 ; Compare IRQ_PendSV value
+ BEQ SVC_PendExec ; Branch to SVC_PendExec if IRQ_PendSV is set
+ POP {R4, R5} ; Restore R4 and R5
+
+ LDR R0, =SVC_Active
+ MOV R1, #0
+ STRB R1, [R0] ; Clear SVC_Active flag
+ BLX osRtxIrqEnableTick ; Enable System Timer interrupt
+
+ LDR R12, =osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.run
+ LDM R12, {R0, R1} ; Load osRtxInfo.thread.run: curr & next
+ CMP R0, R1 ; Check if context switch is required
+ BEQ osRtxContextExit ; Exit if curr and next are equal
B osRtxContextSwitch ; Continue in context switcher
SVC_User
@@ -315,10 +335,9 @@
osRtxContextSwitch
EXPORT osRtxContextSwitch
- LDR R12, =osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.run
- LDM R12, {R0, R1} ; Load osRtxInfo.thread.run: curr & next
- CMP R0, R1 ; Check if context switch is required
- BEQ osRtxContextExit ; Exit if curr and next are equal
+ ; R0 = osRtxInfo.thread.run.curr
+ ; R1 = osRtxInfo.thread.run.next
+ ; R12 = &osRtxInfo.thread.run
CMP R0, #0 ; Is osRtxInfo.thread.run.curr == 0
ADDEQ SP, SP, #32 ; Equal, curr deleted, adjust current SP
diff --git a/CMSIS/RTOS2/RTX/Source/IAR/irq_cm0.s b/CMSIS/RTOS2/RTX/Source/IAR/irq_cm0.s
index 023aae3..9d11699 100644
--- a/CMSIS/RTOS2/RTX/Source/IAR/irq_cm0.s
+++ b/CMSIS/RTOS2/RTX/Source/IAR/irq_cm0.s
@@ -27,7 +27,7 @@
NAME irq_cm0.s
-I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
+I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
diff --git a/CMSIS/RTOS2/RTX/Source/IAR/irq_cm3.s b/CMSIS/RTOS2/RTX/Source/IAR/irq_cm3.s
index bfc3b33..0bffcb3 100644
--- a/CMSIS/RTOS2/RTX/Source/IAR/irq_cm3.s
+++ b/CMSIS/RTOS2/RTX/Source/IAR/irq_cm3.s
@@ -27,7 +27,7 @@
NAME irq_cm3.s
-I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
+I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
diff --git a/CMSIS/RTOS2/RTX/Source/IAR/irq_cm4f.s b/CMSIS/RTOS2/RTX/Source/IAR/irq_cm4f.s
index 4af4386..0d84409 100644
--- a/CMSIS/RTOS2/RTX/Source/IAR/irq_cm4f.s
+++ b/CMSIS/RTOS2/RTX/Source/IAR/irq_cm4f.s
@@ -27,7 +27,7 @@
NAME irq_cm4f.s
-I_T_RUN_OFS EQU 28 ; osRtxInfo.thread.run offset
+I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
TCB_SP_OFS EQU 56 ; TCB.SP offset
TCB_SF_OFS EQU 34 ; TCB.stack_frame offset
diff --git a/CMSIS/RTOS2/RTX/Source/rtx_core_ca.h b/CMSIS/RTOS2/RTX/Source/rtx_core_ca.h
index 10731ae..1eaaaa0 100644
--- a/CMSIS/RTOS2/RTX/Source/rtx_core_ca.h
+++ b/CMSIS/RTOS2/RTX/Source/rtx_core_ca.h
@@ -32,10 +32,6 @@
#define __DOMAIN_NS 0U
#define __EXCLUSIVE_ACCESS 1U
-/* CPSR initial state */
-#define CPSR_INIT_USER 0x00000010U
-#define CPSR_INIT_SYSTEM 0x0000001FU
-
/* CPSR bit definitions */
#define CPSR_T_BIT 0x20U
#define CPSR_I_BIT 0x80U
@@ -50,10 +46,22 @@
#define IS_IRQ_MODE() ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM))
#define IS_IRQ_MASKED() (0U)
+#define xPSR_INIT(privileged, thumb) \
+ ((privileged) != 0U) ? (CPSR_MODE_SYSTEM | (((thumb) != 0U) ? CPSR_T_BIT : 0U)) : \
+ (CPSR_MODE_USER | (((thumb) != 0U) ? CPSR_T_BIT : 0U))
+
#define STACK_FRAME_INIT 0x00U
-#define IS_VFP_D32_STACK_FRAME(n) (((n) & 0x04U) != 0U)
-#define IS_VFP_D16_STACK_FRAME(n) (((n) & 0x02U) != 0U)
+// Stack Frame:
+// - VFP-D32: D16-31, D0-D15, FPSCR, Reserved, R4-R11, R0-R3, R12, LR, PC, CPSR
+// - VFP-D16: D0-D15, FPSCR, Reserved, R4-R11, R0-R3, R12, LR, PC, CPSR
+// - Basic: R4-R11, R0-R3, R12, LR, PC, CPSR
+#define STACK_OFFSET_R0(stack_frame) \
+ (((stack_frame) & 0x04U) != 0U) ? ((32U*8U) + (2U*4U) + (8U*4U)) : \
+ (((stack_frame) & 0x02U) != 0U) ? ((16U*8U) + (2U*4U) + (8U*4U)) : \
+ (8U*4U)
+
+#define OS_TICK_HANDLER osRtxTick_Handler
/* Emulate M profile get_PSP: SP_usr - (8*4) */
#if defined(__CC_ARM)
@@ -85,6 +93,9 @@
}
#endif
+__STATIC_INLINE void __set_CONTROL(uint32_t control) {
+}
+
// ==== Service Calls definitions ====
@@ -341,47 +352,27 @@
// ==== Core Peripherals functions ====
-extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock)
+extern uint8_t IRQ_PendSV;
/// Initialize SVC and PendSV System Service Calls (not needed on Cortex-A)
__STATIC_INLINE void SVC_Initialize (void) {
}
-/// Setup External Tick Timer Interrupt
-/// \param[in] irqn Interrupt number
-extern void ExtTick_SetupIRQ (int32_t irqn);
-
-/// Enable External Tick Timer Interrupt
-/// \param[in] irqn Interrupt number
-extern void ExtTick_EnableIRQ (int32_t irqn);
-
-/// Disable External Tick Timer Interrupt
-/// \param[in] irqn Interrupt number
-extern void ExtTick_DisableIRQ (int32_t irqn);
-
-/// Get Pending SV (Service Call) and ST (SysTick) Flags
-/// \return Pending SV&ST Flags
-__STATIC_INLINE uint8_t GetPendSV_ST (void) {
- return (0U);
-}
-
/// Get Pending SV (Service Call) Flag
/// \return Pending SV Flag
-extern uint8_t GetPendSV (void);
-
-/// Clear Pending SV (Service Call) and ST (SysTick) Flags
-__STATIC_INLINE void ClrPendSV_ST (void) {
+__STATIC_INLINE uint8_t GetPendSV (void) {
+ return (IRQ_PendSV);
}
/// Clear Pending SV (Service Call) Flag
-extern void ClrPendSV (void);
+__STATIC_INLINE void ClrPendSV (void) {
+ IRQ_PendSV = 0U;
+}
/// Set Pending SV (Service Call) Flag
-extern void SetPendSV (void);
-
-/// Set Pending Flags
-/// \param[in] flags Flags to set
-extern void SetPendFlags (uint8_t flags);
+__STATIC_INLINE void SetPendSV (void) {
+ IRQ_PendSV = 1U;
+}
// ==== Exclusive Access Operation ====
diff --git a/CMSIS/RTOS2/RTX/Source/rtx_core_cm.h b/CMSIS/RTOS2/RTX/Source/rtx_core_cm.h
index 759f90f..9b9d715 100644
--- a/CMSIS/RTOS2/RTX/Source/rtx_core_cm.h
+++ b/CMSIS/RTOS2/RTX/Source/rtx_core_cm.h
@@ -53,7 +53,6 @@
#endif
#endif
-
#define IS_PRIVILEGED() ((__get_CONTROL() & 1U) == 0U)
#define IS_IRQ_MODE() (__get_IPSR() != 0U)
@@ -66,7 +65,7 @@
#define IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
#endif
-#define XPSR_INITIAL_VALUE 0x01000000U
+#define xPSR_INIT(...) 0x01000000U
#if (__DOMAIN_NS == 1U)
#define STACK_FRAME_INIT 0xBCU
@@ -74,7 +73,18 @@
#define STACK_FRAME_INIT 0xFDU
#endif
-#define IS_EXTENDED_STACK_FRAME(n) (((n) & 0x10U) == 0U)
+// Stack Frame:
+// - Extended: S16-S31, R4-R11, R0-R3, R12, LR, PC, xPSR, S0-S15, FPSCR
+// - Basic: R4-R11, R0-R3, R12, LR, PC, xPSR
+#if (__FPU_USED == 1U)
+#define STACK_OFFSET_R0(stack_frame) \
+ (((stack_frame) & 0x10U) == 0U) ? ((16U+8U)*4U) : \
+ (8U *4U)
+#else
+#define STACK_OFFSET_R0(stack_frame) (8U *4U)
+#endif
+
+#define OS_TICK_HANDLER SysTick_Handler
// ==== Service Calls definitions ====
@@ -569,9 +579,6 @@
// ==== Core Peripherals functions ====
-extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock)
-
-
/// Initialize SVC and PendSV System Service Calls
__STATIC_INLINE void SVC_Initialize (void) {
#if ((__ARM_ARCH_8M_MAIN__ == 1U) || (defined(__CORTEX_M) && (__CORTEX_M == 7U)))
@@ -604,100 +611,12 @@
#endif
}
-/// Setup SysTick Timer
-/// \param[in] period Timer Load value
-__STATIC_INLINE void SysTick_Setup (uint32_t period) {
- SysTick->LOAD = period - 1U;
- SysTick->VAL = 0U;
-#if ((__ARM_ARCH_8M_MAIN__ == 1U) || (defined(__CORTEX_M) && (__CORTEX_M == 7U)))
- SCB->SHPR[11] = 0xFFU;
-#elif (__ARM_ARCH_8M_BASE__ == 1U)
- SCB->SHPR[1] |= 0xFF000000U;
-#elif ((__ARM_ARCH_7M__ == 1U) || \
- (__ARM_ARCH_7EM__ == 1U))
- SCB->SHP[11] = 0xFFU;
-#elif (__ARM_ARCH_6M__ == 1U)
- SCB->SHP[1] |= 0xFF000000U;
-#endif
-}
-
-/// Get SysTick Period
-/// \return SysTick Period
-__STATIC_INLINE uint32_t SysTick_GetPeriod (void) {
- return (SysTick->LOAD + 1U);
-}
-
-/// Get SysTick Value
-/// \return SysTick Value
-__STATIC_INLINE uint32_t SysTick_GetVal (void) {
- uint32_t load = SysTick->LOAD;
- return (load - SysTick->VAL);
-}
-
-/// Get SysTick Overflow (Auto Clear)
-/// \return SysTick Overflow flag
-__STATIC_INLINE uint32_t SysTick_GetOvf (void) {
- return ((SysTick->CTRL >> 16) & 1U);
-}
-
-/// Enable SysTick Timer
-__STATIC_INLINE void SysTick_Enable (void) {
- SysTick->CTRL = SysTick_CTRL_ENABLE_Msk |
- SysTick_CTRL_TICKINT_Msk |
- SysTick_CTRL_CLKSOURCE_Msk;
-}
-
-/// Disable SysTick Timer
-__STATIC_INLINE void SysTick_Disable (void) {
- SysTick->CTRL = 0U;
-}
-
-/// Setup External Tick Timer Interrupt
-/// \param[in] irqn Interrupt number
-__STATIC_INLINE void ExtTick_SetupIRQ (int32_t irqn) {
-#if (__ARM_ARCH_8M_MAIN__ == 1U)
- NVIC->IPR[irqn] = 0xFFU;
-#elif (__ARM_ARCH_8M_BASE__ == 1U)
- NVIC->IPR[irqn >> 2] = (NVIC->IPR[irqn >> 2] & ~(0xFFU << ((irqn & 3) << 3))) |
- (0xFFU << ((irqn & 3) << 3));
-#elif ((__ARM_ARCH_7M__ == 1U) || \
- (__ARM_ARCH_7EM__ == 1U))
- NVIC->IP[irqn] = 0xFFU;
-#elif (__ARM_ARCH_6M__ == 1U)
- NVIC->IP[irqn >> 2] = (NVIC->IP[irqn >> 2] & ~(0xFFU << ((irqn & 3) << 3))) |
- (0xFFU << ((irqn & 3) << 3));
-#endif
-}
-
-/// Enable External Tick Timer Interrupt
-/// \param[in] irqn Interrupt number
-__STATIC_INLINE void ExtTick_EnableIRQ (int32_t irqn) {
- NVIC->ISER[irqn >> 5] = 1U << (irqn & 0x1F);
-}
-
-/// Disable External Tick Timer Interrupt
-/// \param[in] irqn Interrupt number
-__STATIC_INLINE void ExtTick_DisableIRQ (int32_t irqn) {
- NVIC->ICER[irqn >> 5] = 1U << (irqn & 0x1F);
-}
-
-/// Get Pending SV (Service Call) and ST (SysTick) Flags
-/// \return Pending SV&ST Flags
-__STATIC_INLINE uint8_t GetPendSV_ST (void) {
- return ((uint8_t)((SCB->ICSR & (SCB_ICSR_PENDSVSET_Msk | SCB_ICSR_PENDSTSET_Msk)) >> 24));
-}
-
/// Get Pending SV (Service Call) Flag
/// \return Pending SV Flag
__STATIC_INLINE uint8_t GetPendSV (void) {
return ((uint8_t)((SCB->ICSR & (SCB_ICSR_PENDSVSET_Msk)) >> 24));
}
-/// Clear Pending SV (Service Call) and ST (SysTick) Flags
-__STATIC_INLINE void ClrPendSV_ST (void) {
- SCB->ICSR = SCB_ICSR_PENDSVCLR_Msk | SCB_ICSR_PENDSTCLR_Msk;
-}
-
/// Clear Pending SV (Service Call) Flag
__STATIC_INLINE void ClrPendSV (void) {
SCB->ICSR = SCB_ICSR_PENDSVCLR_Msk;
@@ -708,12 +627,6 @@
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
}
-/// Set Pending Flags
-/// \param[in] flags Flags to set
-__STATIC_INLINE void SetPendFlags (uint8_t flags) {
- SCB->ICSR = ((uint32_t)flags << 24);
-}
-
// ==== Exclusive Access Operation ====
diff --git a/CMSIS/RTOS2/RTX/Source/rtx_gic.c b/CMSIS/RTOS2/RTX/Source/rtx_gic.c
index 7246892..aac3184 100644
--- a/CMSIS/RTOS2/RTX/Source/rtx_gic.c
+++ b/CMSIS/RTOS2/RTX/Source/rtx_gic.c
@@ -26,121 +26,93 @@
#include "RTE_Components.h"
#include CMSIS_device_header
-#include "rtx_lib.h"
+#include "rtx_os.h"
+
#if ((__ARM_ARCH_7A__ == 1U) && (__GIC_PRESENT == 1U))
-extern const uint32_t irqRtxGicBase[];
- const uint32_t irqRtxGicBase[2] = {
- GIC_DISTRIBUTOR_BASE,
- GIC_INTERFACE_BASE
-};
+extern IRQHandler IRQTable[];
+extern uint32_t IRQCount;
+static uint32_t ID0_Active;
-static IRQn_Type PendSV_IRQn;
-static uint8_t PendSV_Flag = 0U;
-
-
-// Pending supervisor call interface
-// =================================
-
-/// Get Pending SV (Service Call) Flag
-/// \return Pending SV Flag
-uint8_t GetPendSV (void) {
- uint32_t pend;
-
- pend = GIC_GetIRQStatus(PendSV_IRQn);
-
- return ((uint8_t)(pend & 1U));
-}
-
-/// Clear Pending SV (Service Call) Flag
-void ClrPendSV (void) {
- GIC_ClearPendingIRQ(PendSV_IRQn);
- PendSV_Flag = 0U;
-}
-
-/// Set Pending SV (Service Call) Flag
-void SetPendSV (void) {
- PendSV_Flag = 1U;
- GIC_SetPendingIRQ(PendSV_IRQn);
-}
-
-/// Set Pending Flags
-/// \param[in] flags Flags to set
-void SetPendFlags (uint8_t flags) {
- if ((flags & 1U) != 0U) {
- PendSV_Flag = 1U;
- GIC_SetPendingIRQ(PendSV_IRQn);
- }
-}
-
-
-// External IRQ handling interface
-// =================================
-
-/// Enable RTX interrupts
-void osRtxIrqUnlock (void) {
- GIC_EnableIRQ(PendSV_IRQn);
-}
-
-/// Disable RTX interrupts
-void osRtxIrqLock (void) {
- GIC_DisableIRQ(PendSV_IRQn);
-}
-
-/// Timer/PendSV interrupt handler
-void osRtxIrqHandler (void) {
-
- if (PendSV_Flag == 0U) {
- osRtxTick_Handler();
- } else {
- ClrPendSV();
- osRtxPendSV_Handler();
- }
-}
-
-
-// External tick timer IRQ interface
-// =================================
-
-/// Setup External Tick Timer Interrupt
-/// \param[in] irqn Interrupt number
-void ExtTick_SetupIRQ (int32_t irqn) {
- IRQn_Type irq = (IRQn_Type)irqn;
+int32_t osRtxIrqGetId (void) {
+ IRQn_Type irq;
+ int32_t id;
uint32_t prio;
- PendSV_IRQn = irq;
+ /* Dummy read to avoid GIC 390 errata 801120 */
+ GIC_GetHighPendingIRQ();
- // Disable corresponding IRQ first
- GIC_DisableIRQ (irq);
- GIC_ClearPendingIRQ(irq);
+ irq = GIC_AcknowledgePending();
- // Write 0xFF to determine priority level
- GIC_SetPriority(irq, 0xFFU);
+ __DSB();
- // Read back the number of priority bits
- prio = GIC_GetPriority(irq);
+ /* Workaround GIC 390 errata 733075 (GIC-390_Errata_Notice_v6.pdf, 09-Jul-2014) */
+ /* The following workaround code is for a single-core system. It would be */
+ /* different in a multi-core system. */
+ /* If the ID is 0 or 0x3FE or 0x3FF, then the GIC CPU interface may be locked-up */
+ /* so unlock it, otherwise service the interrupt as normal. */
+ /* Special IDs 1020=0x3FC and 1021=0x3FD are reserved values in GICv1 and GICv2 */
+ /* so will not occur here. */
+ id = (int32_t)irq;
- // Set lowest possible priority
- GIC_SetPriority(irq, prio - 1);
+ if ((irq == 0U) || (irq >= 0x3FEU)) {
+ /* Unlock the CPU interface with a dummy write to Interrupt Priority Register */
+ prio = GIC_GetPriority((IRQn_Type)0);
+ GIC_SetPriority ((IRQn_Type)0, prio);
- // Set edge-triggered and 1-N model bits
- GIC_SetLevelModel(irq, 1, 1);
+ __DSB();
- InterruptHandlerRegister(irq, osRtxIrqHandler);
+ if (id != 0U) {
+ /* Not 0 (spurious interrupt) */
+ id = -1;
+ }
+ else if ((GIC_GetIRQStatus (irq) & 1U) == 0U) {
+ /* Not active (spurious interrupt) */
+ id = -1;
+ }
+ else if (ID0_Active == 1U) {
+ /* Already seen (spurious interrupt) */
+ id = -1;
+ }
+ else {
+ ID0_Active = 1U;
+ }
+ /* End of Workaround GIC 390 errata 733075 */
+ }
+
+ return (id);
}
-/// Enable External Tick Timer Interrupt
-/// \param[in] irqn Interrupt number
-void ExtTick_EnableIRQ (int32_t irqn) {
- GIC_EnableIRQ((IRQn_Type)irqn);
+uint32_t osRtxIrqGetHandler (int32_t id) {
+ IRQHandler h;
+
+ if (id < IRQCount) {
+ h = IRQTable[id];
+ } else {
+ h = NULL;
+ }
+
+ return ((uint32_t)h);
}
-/// Disable External Tick Timer Interrupt
-/// \param[in] irqn Interrupt number
-void ExtTick_DisableIRQ (int32_t irqn) {
- GIC_DisableIRQ((IRQn_Type)irqn);
+void osRtxIrqSetEnd (int32_t id) {
+
+ GIC_EndInterrupt ((IRQn_Type)id);
+
+ if (id == 0) {
+ ID0_Active = 0U;
+ }
+}
+
+void osRtxIrqEnableTick (void) {
+ GIC_EnableIRQ((IRQn_Type)osRtxInfo.tick_irqn);
+}
+
+void osRtxIrqDisableTick (void) {
+ GIC_DisableIRQ((IRQn_Type)osRtxInfo.tick_irqn);
}
#endif
+
diff --git a/CMSIS/RTOS2/RTX/Source/rtx_kernel.c b/CMSIS/RTOS2/RTX/Source/rtx_kernel.c
index 24883ad..fad3160 100644
--- a/CMSIS/RTOS2/RTX/Source/rtx_kernel.c
+++ b/CMSIS/RTOS2/RTX/Source/rtx_kernel.c
@@ -36,18 +36,14 @@
/// Block Kernel (disable: thread switching, time tick, post ISR processing).
static void KernelBlock (void) {
- if (osRtxInfo.tick_irqn >= 0) {
- ExtTick_DisableIRQ(osRtxInfo.tick_irqn);
- }
- osRtxSysTimerDisable();
+ OS_Tick_Disable();
+
osRtxInfo.kernel.blocked = 1U;
__DSB();
- if (osRtxInfo.tick_irqn < 0) {
- osRtxInfo.kernel.pendISR = GetPendSV_ST();
- ClrPendSV_ST();
- } else {
- osRtxInfo.kernel.pendISR = GetPendSV();
+
+ if (GetPendSV() != 0U) {
ClrPendSV();
+ osRtxInfo.kernel.pendSV = 1U;
}
}
@@ -56,17 +52,13 @@
osRtxInfo.kernel.blocked = 0U;
__DSB();
+
if (osRtxInfo.kernel.pendSV != 0U) {
osRtxInfo.kernel.pendSV = 0U;
SetPendSV();
}
- if (osRtxInfo.kernel.pendISR != 0U) {
- SetPendFlags(osRtxInfo.kernel.pendISR);
- }
- if (osRtxInfo.tick_irqn >= 0) {
- ExtTick_EnableIRQ(osRtxInfo.tick_irqn);
- }
- osRtxSysTimerEnable();
+
+ OS_Tick_Enable();
}
@@ -271,6 +263,17 @@
}
}
+ // Setup RTOS Tick
+ if (OS_Tick_Setup(osRtxConfig.tick_freq, OS_TICK_HANDLER) != 0U) {
+ return osError;
+ }
+ osRtxInfo.tick_irqn = OS_Tick_GetIRQn();
+
+ // Enable RTOS Tick
+ if (OS_Tick_Enable() != 0U) {
+ return osError;
+ }
+
// Switch to Ready Thread with highest Priority
thread = osRtxThreadListGet(&osRtxInfo.thread.ready);
if (thread == NULL) {
@@ -279,7 +282,6 @@
}
osRtxThreadSwitch(thread);
-#if (__ARM_ARCH_7A__ == 0U)
if ((osRtxConfig.flags & osRtxConfigPrivilegedMode) != 0U) {
// Privileged Thread mode & PSP
__set_CONTROL(0x02U);
@@ -287,17 +289,6 @@
// Unprivileged Thread mode & PSP
__set_CONTROL(0x03U);
}
-#endif
-
- osRtxInfo.kernel.sys_freq = SystemCoreClock;
-
- // Setup and Enable System Timer
- osRtxInfo.tick_irqn = osRtxSysTimerSetup();
- if (osRtxInfo.tick_irqn >= 0) {
- ExtTick_SetupIRQ (osRtxInfo.tick_irqn);
- ExtTick_EnableIRQ(osRtxInfo.tick_irqn);
- }
- osRtxSysTimerEnable();
osRtxInfo.kernel.state = osRtxKernelRunning;
@@ -483,7 +474,16 @@
/// Get the RTOS kernel system timer count.
/// \note API identical to osKernelGetSysTimerCount
uint32_t svcRtxKernelGetSysTimerCount (void) {
- uint32_t count = osRtxSysTimerGetCount();
+ uint32_t tick;
+ uint32_t count;
+
+ tick = (uint32_t)osRtxInfo.kernel.tick;
+ count = OS_Tick_GetCount();
+ if (OS_Tick_GetOverflow()) {
+ count = OS_Tick_GetCount();
+ tick++;
+ }
+ count += tick * OS_Tick_GetInterval();
EvrRtxKernelGetSysTimerCount(count);
return count;
}
@@ -491,7 +491,7 @@
/// Get the RTOS kernel system timer frequency.
/// \note API identical to osKernelGetSysTimerFreq
uint32_t svcRtxKernelGetSysTimerFreq (void) {
- uint32_t freq = osRtxSysTimerGetFreq();
+ uint32_t freq = OS_Tick_GetClock();
EvrRtxKernelGetSysTimerFreq(freq);
return freq;
}
diff --git a/CMSIS/RTOS2/RTX/Source/rtx_lib.h b/CMSIS/RTOS2/RTX/Source/rtx_lib.h
index 5c5f81b..17bfc00 100644
--- a/CMSIS/RTOS2/RTX/Source/rtx_lib.h
+++ b/CMSIS/RTOS2/RTX/Source/rtx_lib.h
@@ -32,6 +32,7 @@
#if ((__ARM_ARCH_8M_BASE__ != 0) || (__ARM_ARCH_8M_MAIN__ != 0))
#include "tz_context.h" // TrustZone Context API
#endif
+#include "os_tick.h"
#include "cmsis_os2.h" // CMSIS RTOS API
#include "rtx_os.h" // RTX OS definitions
#include "rtx_evr.h" // RTX Event Recorder definitions
diff --git a/CMSIS/RTOS2/RTX/Source/rtx_system.c b/CMSIS/RTOS2/RTX/Source/rtx_system.c
index f92b30b..fc64c93 100644
--- a/CMSIS/RTOS2/RTX/Source/rtx_system.c
+++ b/CMSIS/RTOS2/RTX/Source/rtx_system.c
@@ -120,7 +120,7 @@
void osRtxTick_Handler (void) {
os_thread_t *thread;
- osRtxSysTimerAckIRQ();
+ OS_Tick_AcknowledgeIRQ();
osRtxInfo.kernel.tick++;
// Process Timers
@@ -207,68 +207,3 @@
osRtxErrorNotify(osRtxErrorISRQueueOverflow, object);
}
}
-
-
-// ==== Public API ====
-
-/// Setup System Timer.
-__WEAK int32_t osRtxSysTimerSetup (void) {
-#ifdef SysTick
- // Setup SysTick Timer
- SysTick_Setup(osRtxInfo.kernel.sys_freq / osRtxConfig.tick_freq);
-
- return SysTick_IRQn; // Return IRQ number of SysTick
-#else
- return 0;
-#endif
-}
-
-/// Enable System Timer.
-__WEAK void osRtxSysTimerEnable (void) {
-#ifdef SysTick
- SysTick_Enable();
-#endif
-}
-
-/// Disable System Timer.
-__WEAK void osRtxSysTimerDisable (void) {
-#ifdef SysTick
- SysTick_Disable();
-#endif
-}
-
-/// Acknowledge System Timer IRQ.
-__WEAK void osRtxSysTimerAckIRQ (void) {
-#ifdef SysTick
- SysTick_GetOvf();
-#endif
-}
-
-/// Get System Timer count.
-__WEAK uint32_t osRtxSysTimerGetCount (void) {
-#ifdef SysTick
- uint32_t tick;
- uint32_t val;
-
- tick = osRtxInfo.kernel.tick;
- val = SysTick_GetVal();
- if (SysTick_GetOvf()) {
- val = SysTick_GetVal();
- tick++;
- }
- val += tick * SysTick_GetPeriod();
-
- return val;
-#else
- return 0U;
-#endif
-}
-
-/// Get System Timer frequency.
-__WEAK uint32_t osRtxSysTimerGetFreq (void) {
-#ifdef SysTick
- return osRtxInfo.kernel.sys_freq;
-#else
- return 0U;
-#endif
-}
diff --git a/CMSIS/RTOS2/RTX/Source/rtx_thread.c b/CMSIS/RTOS2/RTX/Source/rtx_thread.c
index 264e404..06d2d93 100644
--- a/CMSIS/RTOS2/RTX/Source/rtx_thread.c
+++ b/CMSIS/RTOS2/RTX/Source/rtx_thread.c
@@ -377,33 +377,7 @@
/// \param[in] thread thread object.
/// \return pointer to registers R0-R3.
uint32_t *osRtxThreadRegPtr (os_thread_t *thread) {
-#if (__ARM_ARCH_7A__ == 0U) /* Cortex-M */
-#if (__FPU_USED == 1U)
- if (IS_EXTENDED_STACK_FRAME(thread->stack_frame)) {
- // Extended Stack Frame: S16-S31, R4-R11, R0-R3, R12, LR, PC, xPSR, S0-S15, FPSCR
- return ((uint32_t *)(thread->sp + (16U+8U)*4U));
- } else {
- // Basic Stack Frame: R4-R11, R0-R3, R12, LR, PC, xPSR
- return ((uint32_t *)(thread->sp + 8U *4U));
- }
-#else
- // Stack Frame: R4-R11, R0-R3, R12, LR, PC, xPSR
- return ((uint32_t *)(thread->sp + 8U*4U));
-#endif
-#else /* Cortex-A */
- if (IS_VFP_D32_STACK_FRAME(thread->stack_frame)) {
- /* VFP-D32 Stack Frame: D16-31, D0-D15, FPSCR, Reserved, R4-R11, R0-R3, R12, LR, PC, CPSR */
- return (uint32_t *)(thread->sp + (8U*4U) + (2U*4U) + (32U*8U));
- }
- else if (IS_VFP_D16_STACK_FRAME(thread->stack_frame)) {
- /* VFP-D16 Stack Frame: D0-D15, FPSCR, Reserved, R4-R11, R0-R3, R12, LR, PC, CPSR */
- return (uint32_t *)(thread->sp + (8U*4U) + (2U*4U) + (16U*8U));
- }
- else {
- /* Basic Stack Frame: R4-R11, R0-R3, R12, LR, PC, CPSR */
- return (uint32_t *)(thread->sp + (8U*4U));
- }
-#endif
+ return ((uint32_t *)(thread->sp + STACK_OFFSET_R0(thread->stack_frame)));
}
/// Block running Thread execution and register it as Ready to Run.
@@ -775,19 +749,10 @@
}
*ptr++ = (uint32_t)osThreadExit; // LR
*ptr++ = (uint32_t)func; // PC
-#if (__ARM_ARCH_7A__ == 0U)
- *ptr++ = XPSR_INITIAL_VALUE; // xPSR
-#else
- if ((osRtxConfig.flags & osRtxConfigPrivilegedMode) != 0U) {
- *ptr = CPSR_INIT_SYSTEM; // CPSR (Mode=System))
- } else {
- *ptr = CPSR_INIT_USER; // CPSR (Mode=User)
- }
- if (((uint32_t)func & 1U) != 0U) {
- *ptr |= CPSR_T_BIT; // CPSR (Thumb=1)
- }
- ptr++;
-#endif
+ *ptr++ = xPSR_INIT(
+ (osRtxConfig.flags & osRtxConfigPrivilegedMode),
+ ((uint32_t)func & 1U)
+ ); // xPSR
*(ptr-8) = (uint32_t)argument; // R0
// Register post ISR processing function
diff --git a/CMSIS/RTOS2/Source/os_systick.c b/CMSIS/RTOS2/Source/os_systick.c
new file mode 100644
index 0000000..a560e96
--- /dev/null
+++ b/CMSIS/RTOS2/Source/os_systick.c
@@ -0,0 +1,121 @@
+/**************************************************************************//**
+ * @file os_systick.c
+ * @brief CMSIS OS Tick SysTick implementation
+ * @version V1.0.0
+ * @date 05. June 2017
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017-2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os_tick.h"
+
+#include "RTE_Components.h"
+#include CMSIS_device_header
+
+#ifdef SysTick
+
+#ifndef SYSTICK_IRQ_PRIORITY
+#define SYSTICK_IRQ_PRIORITY 0xFFU
+#endif
+
+static uint8_t PendST;
+
+// Setup OS Tick.
+__WEAK int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler) {
+ (void)handler;
+ uint32_t load;
+
+ if (freq == 0U) {
+ return (-1);
+ }
+
+ load = (SystemCoreClock / freq) - 1U;
+ if (load > 0x00FFFFFFU) {
+ return (-1);
+ }
+
+ NVIC_SetPriority(SysTick_IRQn, SYSTICK_IRQ_PRIORITY);
+
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk;
+ SysTick->LOAD = load;
+ SysTick->VAL = 0U;
+
+ PendST = 0U;
+
+ return (0);
+}
+
+/// Enable OS Tick.
+__WEAK int32_t OS_Tick_Enable (void) {
+
+ if (PendST != 0U) {
+ PendST = 0U;
+ SCB->ICSR = SCB_ICSR_PENDSTSET_Msk;
+ }
+
+ SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
+
+ return (0);
+}
+
+/// Disable OS Tick.
+__WEAK int32_t OS_Tick_Disable (void) {
+
+ SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
+
+ if ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) != 0U) {
+ SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk;
+ PendST = 1U;
+ }
+
+ return (0);
+}
+
+// Acknowledge OS Tick IRQ.
+__WEAK int32_t OS_Tick_AcknowledgeIRQ (void) {
+ (void)SysTick->CTRL;
+ return (0);
+}
+
+// Get OS Tick IRQ number.
+__WEAK int32_t OS_Tick_GetIRQn (void) {
+ return (SysTick_IRQn);
+}
+
+// Get OS Tick clock.
+__WEAK uint32_t OS_Tick_GetClock (void) {
+ return (SystemCoreClock);
+}
+
+// Get OS Tick interval.
+__WEAK uint32_t OS_Tick_GetInterval (void) {
+ return (SysTick->LOAD + 1U);
+}
+
+// Get OS Tick count value.
+__WEAK uint32_t OS_Tick_GetCount (void) {
+ uint32_t load = SysTick->LOAD;
+ return (load - SysTick->VAL);
+}
+
+// Get OS Tick overflow status.
+__WEAK uint32_t OS_Tick_GetOverflow (void) {
+ return ((SysTick->CTRL >> 16) & 1U);
+}
+
+#endif // SysTick