fixed bugs in QK/QXK ports to ARM Cortex-M
This commit is contained in:
MMS 2022-08-13 14:14:01 -04:00
parent ea41985bf1
commit d7225a6579
24 changed files with 543 additions and 482 deletions

View File

@ -297,7 +297,7 @@
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>3</nTsel>
<nTsel>4</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>
@ -491,7 +491,7 @@
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>3</nTsel>
<nTsel>4</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>

View File

@ -337,7 +337,7 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define>
<Define>QK_USE_IRQ_NUM=25 QK_USE_IRQ_HANDLER=CRYPTO_IRQHandler</Define>
<Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls>
@ -532,57 +532,6 @@
<FileName>qk_port.cpp</FileName>
<FileType>8</FileType>
<FilePath>..\..\..\..\..\ports\arm-cm\qk\armclang\qk_port.cpp</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>2</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>QK_USE_IRQ_NUM=25 QK_USE_IRQ_HANDLER=CRYPTO_IRQHandler</Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
</Files>
</Group>
@ -686,7 +635,7 @@
<TargetName>dpp-rel</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>5060183::V5.06 update 2 (build 183)::ARMCC</pCCUsed>
<pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6>
<TargetOption>
<TargetCommonOption>
@ -1013,7 +962,7 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>NDEBUG EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define>
<Define>NDEBUG</Define>
<Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls>
@ -1311,7 +1260,7 @@
<TargetName>dpp-spy</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6130001::V6.13.1::.\ARMCLANG</pCCUsed>
<pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6>
<TargetOption>
<TargetCommonOption>
@ -1638,7 +1587,7 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>Q_SPY EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define>
<Define>Q_SPY</Define>
<Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls>

View File

@ -138,8 +138,8 @@ LIBS :=
# defines
DEFINES := -DEFM32PG1B200F256GM48=1 \
-DQK_USE_IRQ_NUM=25 \
-DQK_USE_IRQ_HANDLER=CRYPTO_IRQHandler
-DQK_USE_IRQ_HANDLER=CRYPTO_IRQHandler \
-DQK_USE_IRQ_NUM=25
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]

View File

@ -215,6 +215,8 @@
<option>
<name>CCDefines</name>
<state>EFM32PG1B200F256GM48</state>
<state>QK_USE_IRQ_HANDLER=CRYPTO_IRQHandler</state>
<state>QK_USE_IRQ_NUM=25</state>
</option>
<option>
<name>CCPreprocFile</name>

View File

@ -337,7 +337,7 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define>
<Define>QXK_USE_IRQ_HANDLER=CRYPTO_IRQHandler QXK_USE_IRQ_NUM=25</Define>
<Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls>
@ -552,57 +552,6 @@
<FileName>qxk_port.cpp</FileName>
<FileType>8</FileType>
<FilePath>..\..\..\..\..\ports\arm-cm\qxk\armclang\qxk_port.cpp</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>2</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>QXK_USE_IRQ_NUM=25 QXK_USE_IRQ_HANDLER=CRYPTO_IRQHandler</Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
</Files>
</Group>
@ -1033,7 +982,7 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>NDEBUG EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define>
<Define>NDEBUG</Define>
<Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls>
@ -1678,7 +1627,7 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>Q_SPY EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define>
<Define>Q_SPY</Define>
<Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls>

View File

@ -143,8 +143,8 @@ LIBS :=
# defines
DEFINES := -DEFM32PG1B200F256GM48=1 \
-DQXK_USE_IRQ_NUM=25 \
-DQXK_USE_IRQ_HANDLER=CRYPTO_IRQHandler
-DQXK_USE_IRQ_HANDLER=CRYPTO_IRQHandler \
-DQXK_USE_IRQ_NUM=25
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]

View File

@ -215,6 +215,8 @@
<option>
<name>CCDefines</name>
<state>EFM32PG1B200F256GM48</state>
<state>QXK_USE_IRQ_HANDLER=CRYPTO_IRQHandler</state>
<state>QXK_USE_IRQ_NUM=25</state>
</option>
<option>
<name>CCPreprocFile</name>

View File

@ -299,7 +299,7 @@
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>5</nTsel>
<nTsel>6</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>
@ -495,7 +495,7 @@
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>5</nTsel>
<nTsel>6</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>

View File

@ -337,7 +337,7 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls>-fno-exceptions</MiscControls>
<Define></Define>
<Define>QK_USE_IRQ_HANDLER=LCD_IRQHandler QK_USE_IRQ_NUM=30</Define>
<Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\nucleo-l053r8</IncludePath>
</VariousControls>
@ -522,57 +522,6 @@
<FileName>qk_port.cpp</FileName>
<FileType>8</FileType>
<FilePath>..\..\..\..\..\ports\arm-cm\qk\armclang\qk_port.cpp</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>2</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>QK_USE_IRQ_NUM=30 QK_USE_IRQ_HANDLER=LCD_IRQHandler</Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
</Files>
</Group>
@ -1281,7 +1230,7 @@
<TargetName>dpp-spy</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6130001::V6.13.1::.\ARMCLANG</pCCUsed>
<pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6>
<TargetOption>
<TargetCommonOption>

View File

@ -134,8 +134,8 @@ LIBS :=
# defines
DEFINES := \
-DQK_USE_IRQ_NUM=30 \
-DQK_USE_IRQ_HANDLER=LCD_IRQHandler
-DQK_USE_IRQ_HANDLER=LCD_IRQHandler \
-DQK_USE_IRQ_NUM=30
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]

View File

@ -0,0 +1,72 @@
About this Example
==================
This example demonstrates how to use the IAR EWARM IDE to build
a QP application.
IAR Project File
----------------
The IAR EWARM project file provided with this example uses relative paths
to the QP/C framework location (includes, port, and libraries. These
relative paths must be modified when the project is moved to different
relative location.
Stack Size and Heap Size
------------------------
In this project, the size of the C stack and heap are determined in
the linker script dpp-qk.icf (see the next section).
Linker Script
-------------
The IAR linker script provides a template of the recommended linker script
for QP applications. This file needs to be customized to set the
application-specific sizes of the Stack and Heap. This file can be edited
from the IAR EWARM IDE via the Project Options/Linker settings.
Selecting QK Exception
======================
The QK kernel needs a dedicated exception to return to the thread
context after preemption. The default is to use the NMI exception
for that purpose. However, in case NMI is needed for some other
purpose, the QK port allows you to select a any, otherwise unused
IRQ for that purpose. To choose a given IRQ, you need to define
the macros QK_USE_IRQ_NUM and QK_USE_IRQ_HANDLER. These macros can
be provided on the command-line to the compiler.
For example, for the STM32L053 MCU, you might dedicate the IRQ
"CRYPTO_IRQHandler" (see the vector table), with IRQ number 25,
as follows:
QK_USE_IRQ_HANDLER=LCD_IRQHandler
QK_USE_IRQ_NUM=30
Startup Code
============
The startup code for the STM32L053 MCU used in this project is
located in the "3rd_party" folder in the following location:
3rd_party\nucleo-l053r8\iar\startup_stm32l053xx.s
The file startup_efm32pg1b.s provides a template of the recommended
startup for QP applications and should be easily customizable for other
ARM Cortex-M microcontrollers.
The startup file typically does not need to be modified or adapted for
applications. It provides only weak definitions of all exception and
interrupt handlers, as well as the assert_failed() function.
The weak function assert_failed() defined in this file might be re-defined
in the application to customize it for the application-specific error-
handling policy.
***
NOTE: The function assert_failed() typically should NOT use the stack,
because stack might be corrupted by the time this function is called.
Also, assert_failed() is intended to handle catastrophic errors and
should NOT return.
***

View File

@ -214,7 +214,8 @@
</option>
<option>
<name>CCDefines</name>
<state></state>
<state>QK_USE_IRQ_HANDLER=LCD_IRQHandler</state>
<state>QK_USE_IRQ_NUM=30</state>
</option>
<option>
<name>CCPreprocFile</name>

View File

@ -32,10 +32,27 @@ C++ programs seem not to tolerate heap size of 0. Therefore it is
recommended to set the Heap_Size symbol to a minimal value of 16.
***
Selecting QXK Exception
=======================
The QXK kernel needs a dedicated exception to return to the thread
context after preemption. The default is to use the NMI exception
for that purpose. However, in case NMI is needed for some other
purpose, the QXK port allows you to select a any, otherwise unused
IRQ for that purpose. To choose a given IRQ, you need to define
the macros QXK_USE_IRQ_NUM and QXK_USE_IRQ_HANDLER. These macros can
be provided on the command-line to the compiler.
For example, for the STM32L053 MCU, you might dedicate the IRQ
"CRYPTO_IRQHandler" (see the vector table), with IRQ number 25,
as follows:
QXK_USE_IRQ_HANDLER=LCD_IRQHandler
QXK_USE_IRQ_NUM=30
Startup Code
============
The startup code for the STM32L1xx MCU used in this project is
The startup code for the STM32L0xx MCU used in this project is
located in the "3rd_party" folder in the following location:
3rd_party\nucleo-l053r8\arm\startup_stm32l053xx.s
@ -74,4 +91,3 @@ on the solder bridge configuration. Please see Chapter 5.7 "OSC clock" in
the STM32 NUCLEO Boards User Manual (ST document UM1724) for more information.
***

View File

@ -495,7 +495,7 @@
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>5</nTsel>
<nTsel>6</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>

View File

@ -337,7 +337,7 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls>-fno-exceptions</MiscControls>
<Define></Define>
<Define>QXK_USE_IRQ_HANDLER=LCD_IRQHandler QXK_USE_IRQ_NUM=30</Define>
<Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\nucleo-l053r8</IncludePath>
</VariousControls>
@ -542,57 +542,6 @@
<FileName>qxk_port.cpp</FileName>
<FileType>8</FileType>
<FilePath>..\..\..\..\..\ports\arm-cm\qxk\armclang\qxk_port.cpp</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>2</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>QXK_USE_IRQ_NUM=30 QXK_USE_IRQ_HANDLER=LCD_IRQHandler</Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
</Files>
</Group>
@ -1321,7 +1270,7 @@
<TargetName>dpp-spy</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6130001::V6.13.1::.\ARMCLANG</pCCUsed>
<pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6>
<TargetOption>
<TargetCommonOption>

View File

@ -138,8 +138,8 @@ LIBS :=
# defines
DEFINES := -DQXK_ON_CONTEXT_SW \
-DQXK_USE_IRQ_NUM=30 \
-DQXK_USE_IRQ_HANDLER=LCD_IRQHandler
-DQXK_USE_IRQ_HANDLER=LCD_IRQHandler \
-DQXK_USE_IRQ_NUM=30
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]

View File

@ -0,0 +1,72 @@
About this Example
==================
This example demonstrates how to use the IAR EWARM IDE to build
a QP application.
IAR Project File
----------------
The IAR EWARM project file provided with this example uses relative paths
to the QP/C framework location (includes, port, and libraries. These
relative paths must be modified when the project is moved to different
relative location.
Stack Size and Heap Size
------------------------
In this project, the size of the C stack and heap are determined in
the linker script dpp-qxk.icf (see the next section).
Linker Script
-------------
The IAR linker script provides a template of the recommended linker script
for QP applications. This file needs to be customized to set the
application-specific sizes of the Stack and Heap. This file can be edited
from the IAR EWARM IDE via the Project Options/Linker settings.
Selecting QXK Exception
=======================
The QXK kernel needs a dedicated exception to return to the thread
context after preemption. The default is to use the NMI exception
for that purpose. However, in case NMI is needed for some other
purpose, the QXK port allows you to select a any, otherwise unused
IRQ for that purpose. To choose a given IRQ, you need to define
the macros QXK_USE_IRQ_NUM and QXK_USE_IRQ_HANDLER. These macros can
be provided on the command-line to the compiler.
For example, for the STM32L053 MCU, you might dedicate the IRQ
"CRYPTO_IRQHandler" (see the vector table), with IRQ number 25,
as follows:
QXK_USE_IRQ_HANDLER=LCD_IRQHandler
QXK_USE_IRQ_NUM=30
Startup Code
============
The startup code for the STM32L053 MCU used in this project is
located in the "3rd_party" folder in the following location:
3rd_party\nucleo-l053r8\iar\startup_stm32l053xx.s
The file startup_efm32pg1b.s provides a template of the recommended
startup for QP applications and should be easily customizable for other
ARM Cortex-M microcontrollers.
The startup file typically does not need to be modified or adapted for
applications. It provides only weak definitions of all exception and
interrupt handlers, as well as the assert_failed() function.
The weak function assert_failed() defined in this file might be re-defined
in the application to customize it for the application-specific error-
handling policy.
***
NOTE: The function assert_failed() typically should NOT use the stack,
because stack might be corrupted by the time this function is called.
Also, assert_failed() is intended to handle catastrophic errors and
should NOT return.
***

View File

@ -215,6 +215,8 @@
<option>
<name>CCDefines</name>
<state>QXK_ON_CONTEXT_SW</state>
<state>QXK_USE_IRQ_HANDLER=LCD_IRQHandler</state>
<state>QXK_USE_IRQ_NUM=30</state>
</option>
<option>
<name>CCPreprocFile</name>

View File

@ -1,5 +1,5 @@
/*============================================================================
* QK/C++ port to ARM Cortex-M, ARM-CLANG
* QP/C Real-Time Embedded Framework (RTEF)
* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
*
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com>
============================================================================*/
/*!
* @date Last updated on: 2022-05-13
* @version Last updated for: @ref qpcpp_7_0_1
* @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpc_7_0_2
*
* @file
* @brief QK/C++ port to ARM Cortex-M, ARM-CLANG toolset
@ -62,7 +62,7 @@ void NMI_Handler(void);
* BASEPRI register. However, this method cannot disable interrupt
* priority zero, which is the default for all interrupts out of reset.
* The following code changes the SysTick priority and all IRQ priorities
* to the safe value QF_BASEPRI, wich the QF critical section can disable.
* to the safe value QF_BASEPRI, which the QF critical section can disable.
* This avoids breaching of the QF critical sections in case the
* application programmer forgets to explicitly set priorities of all
* "kernel aware" interrupts.
@ -71,7 +71,7 @@ void NMI_Handler(void);
* changed by the application-level code.
*/
void QK_init(void) {
#if (__ARM_ARCH != 6) /* if ARMv7-M and higher... */
#if (__ARM_ARCH != 6) /*--------- if ARMv7-M and higher... */
/* set exception priorities to QF_BASEPRI...
* SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault
@ -92,25 +92,24 @@ void QK_init(void) {
NVIC_IP[n] = QF_BASEPRI;
}
#endif /* ARMv7-M or higher */
#endif /*--------- ARMv7-M or higher */
/* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */
SCB_SYSPRI[3] = (SCB_SYSPRI[3] | (0xFFU << 16U));
#ifdef QK_USE_IRQ_NUM
#ifdef QK_USE_IRQ_NUM /*--------- QK IRQ specified? */
/* The QK port is configured to use a given ARM Cortex-M IRQ #
* to return to thread mode (default is to use the NMI exception)
*/
NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */
NVIC_EN[QK_USE_IRQ_NUM / 32U] = (1U << (QK_USE_IRQ_NUM % 32U));
#endif
#endif /*--------- QK IRQ specified */
}
/*==========================================================================*/
/* The PendSV_Handler exception handler is used for handling context switch
* and asynchronous preemption in QK. The use of the PendSV exception is
* the recommended and most efficient method for performing context switches
* with ARM Cortex-M.
/* The PendSV_Handler exception is used for handling the asynchronous
* preemption in QK. The use of the PendSV exception is the recommended and
* the most efficient method for performing context switches with ARM Cortex-M.
*
* The PendSV exception should have the lowest priority in the whole system
* (0xFF, see QK_init). All other exceptions and interrupts should have higher
@ -138,17 +137,17 @@ __asm volatile (
" LSLS r1,r1,#27 \n" /* r0 := (1 << 27) (UNPENDSVSET bit) */
/*<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<<*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSID i \n" /* disable interrupts (set PRIMASK) */
#else /* ARMv7-M and higher */
#if (__ARM_FP != 0) /* if VFP available... */
#if (__ARM_FP != 0) /*--------- if VFP available... */
" PUSH {r0,lr} \n" /* ... push lr plus stack-aligner */
#endif /* VFP available */
#endif /*--------- VFP available */
" MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n"
" CPSID i \n" /* disable interrutps with BASEPRI */
" MSR BASEPRI,r0 \n" /* apply the Cortex-M7 erraturm */
" CPSIE i \n" /* 837070, see SDEN-1068427. */
#endif /* ARMv7-M and higher */
#endif /*--------- ARMv7-M and higher */
/* The PendSV exception handler can be preempted by an interrupt,
* which might pend PendSV exception again. The following write to
@ -168,7 +167,7 @@ __asm volatile (
" LSRS r3,r1,#3 \n" /* r3 := (r1 >> 3), set the T bit (new xpsr) */
" LDR r2,=QK_activate_ \n" /* address of QK_activate_ */
" SUBS r2,r2,#1 \n" /* align Thumb-address at halfword (new pc) */
" LDR r1,=QK_thread_ret \n" /* return address after the call (new lr) */
" LDR r1,=QK_thread_ret \n" /* return address after the call (new lr) */
" SUB sp,sp,#8*4 \n" /* reserve space for exception stack frame */
" ADD r0,sp,#5*4 \n" /* r0 := 5 registers below the SP */
@ -176,9 +175,9 @@ __asm volatile (
" MOVS r0,#6 \n"
" MVNS r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */
#if (__ARM_ARCH != 6) /* if ARMv7-M and higher... */
#if (__ARM_ARCH != 6) /*--------- if ARMv7-M and higher... */
" DSB \n" /* ARM Erratum 838869 */
#endif /* ARMv7-M and higher */
#endif /*--------- ARMv7-M and higher */
" BX r0 \n" /* exception-return to the QK activator */
);
}
@ -196,61 +195,77 @@ __asm volatile (
/* After the QK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the exception
* contex is accomplished by triggering the SVC or NMI exception.
* context is accomplished by triggering the NMI exception or the selected
* IRQ (if macro #QK_USE_IRQ_NUM is defined).
*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /* ARMv7-M and higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* before triggering the NMI/IRQ, make sure that the VFP stack frame
* will NOT be used...
*/
#if (__ARM_FP != 0) /*--------- if VFP available... */
/* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */
#endif /* ARMv7-M and higher */
#ifdef QK_USE_IRQ_NUM /* if use IRQ... */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QK_USE_IRQ_NUM / 32)) "\n"
" MOVS r1,#1 \n"
" LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */
" STR r1,[r0] \n" /* pend the IRQ */
" B . \n" /* wait for preemption by the IRQ */
#else /* use the NMI */
#ifndef QK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOVS r1,#1 \n"
" LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */
" B . \n" /* wait for preemption by NMI */
#endif /* use NMI */
/* NOTE! interrupts are still disabled when NMI is used */
#else /*--------- use the selected IRQ */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QK_USE_IRQ_NUM / 32)) "\n"
" MOVS r1,#1 \n"
" LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */
" STR r1,[r0] \n" /* pend the IRQ */
/* now enable interrupts so that pended IRQ can be entered */
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /* ARMv7-M and higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
#endif /*--------- use IRQ */
" B . \n" /* wait for preemption by NMI/IRQ */
);
}
/*==========================================================================*/
/* This exception handler is used for returning back to the interrupted task.
/* This exception handler is used for returning back to the preempted thread.
* The exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack.
*/
__attribute__ ((naked))
#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */
void QK_USE_IRQ_HANDLER(void)
#else /* use NMI */
void NMI_Handler(void)
#endif /* use NMI */
{
#ifndef QK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
void NMI_Handler(void) {
__asm volatile (
/* enable interrupts */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /*--------- ARMv7-M and higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
);
#else /* use the selected IRQ */
void QK_USE_IRQ_HANDLER(void) {
#endif /*--------- use IRQ */
__asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */
#if (__ARM_ARCH != 6) /* if ARMv7-M or higher... */
#if (__ARM_FP != 0) /* if VFP available... */
#if (__ARM_FP != 0) /*--------- if VFP available... */
" POP {r0,lr} \n" /* pop stack aligner and EXC_RETURN to LR */
" DSB \n" /* ARM Erratum 838869 */
#endif /* VFP available */
#endif /* ARMv7-M or higher */
#endif /*--------- VFP available */
" BX lr \n" /* return to the preempted task */
);
}

View File

@ -1,5 +1,5 @@
/*============================================================================
* QK/C++ port to ARM Cortex-M, GNU-ARM
* QP/C Real-Time Embedded Framework (RTEF)
* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
*
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com>
============================================================================*/
/*!
* @date Last updated on: 2022-05-13
* @version Last updated for: @ref qpcpp_7_0_1
* @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpc_7_0_2
*
* @file
* @brief QK/C++ port to ARM Cortex-M, GNU-ARM toolset
@ -62,7 +62,7 @@ void NMI_Handler(void);
* BASEPRI register. However, this method cannot disable interrupt
* priority zero, which is the default for all interrupts out of reset.
* The following code changes the SysTick priority and all IRQ priorities
* to the safe value QF_BASEPRI, wich the QF critical section can disable.
* to the safe value QF_BASEPRI, which the QF critical section can disable.
* This avoids breaching of the QF critical sections in case the
* application programmer forgets to explicitly set priorities of all
* "kernel aware" interrupts.
@ -71,7 +71,7 @@ void NMI_Handler(void);
* changed by the application-level code.
*/
void QK_init(void) {
#if (__ARM_ARCH != 6) /* if ARMv7-M or higher... */
#if (__ARM_ARCH != 6) /*--------- if ARMv7-M and higher... */
/* set exception priorities to QF_BASEPRI...
* SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault
@ -92,25 +92,24 @@ void QK_init(void) {
NVIC_IP[n] = QF_BASEPRI;
}
#endif /* ARMv7-M or higher */
#endif /*--------- ARMv7-M or higher */
/* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */
SCB_SYSPRI[3] = (SCB_SYSPRI[3] | (0xFFU << 16U));
#ifdef QK_USE_IRQ_NUM
#ifdef QK_USE_IRQ_NUM /*--------- QK IRQ specified? */
/* The QK port is configured to use a given ARM Cortex-M IRQ #
* to return to thread mode (default is to use the NMI exception)
*/
NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */
NVIC_EN[QK_USE_IRQ_NUM / 32U] = (1U << (QK_USE_IRQ_NUM % 32U));
#endif
#endif /*--------- QK IRQ specified */
}
/*==========================================================================*/
/* The PendSV_Handler exception handler is used for handling context switch
* and asynchronous preemption in QK. The use of the PendSV exception is
* the recommended and most efficient method for performing context switches
* with ARM Cortex-M.
/* The PendSV_Handler exception is used for handling the asynchronous
* preemption in QK. The use of the PendSV exception is the recommended and
* the most efficient method for performing context switches with ARM Cortex-M.
*
* The PendSV exception should have the lowest priority in the whole system
* (0xFF, see QK_init). All other exceptions and interrupts should have higher
@ -143,17 +142,17 @@ __asm volatile (
" LSL r1,r1,#27 \n" /* r0 := (1 << 27) (UNPENDSVSET bit) */
/*<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<<*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSID i \n" /* disable interrupts (set PRIMASK) */
#else /* ARMv7-M and higher */
#if (__ARM_FP != 0) /* if VFP available... */
#if (__ARM_FP != 0) /*--------- if VFP available... */
" PUSH {r0,lr} \n" /* ... push lr plus stack-aligner */
#endif /* VFP available */
#endif /*--------- VFP available */
" MOV r0,#" STRINGIFY(QF_BASEPRI) "\n"
" CPSID i \n" /* disable interrutps with BASEPRI */
" MSR BASEPRI,r0 \n" /* apply the Cortex-M7 erraturm */
" CPSIE i \n" /* 837070, see SDEN-1068427. */
#endif /* ARMv7-M and higher */
#endif /*--------- ARMv7-M and higher */
/* The PendSV exception handler can be preempted by an interrupt,
* which might pend PendSV exception again. The following write to
@ -173,7 +172,7 @@ __asm volatile (
" LSR r3,r1,#3 \n" /* r3 := (r1 >> 3), set the T bit (new xpsr) */
" LDR r2,=QK_activate_ \n" /* address of QK_activate_ */
" SUB r2,r2,#1 \n" /* align Thumb-address at halfword (new pc) */
" LDR r1,=QK_thread_ret \n" /* return address after the call (new lr) */
" LDR r1,=QK_thread_ret \n" /* return address after the call (new lr) */
" SUB sp,sp,#8*4 \n" /* reserve space for exception stack frame */
" ADD r0,sp,#5*4 \n" /* r0 := 5 registers below the SP */
@ -181,9 +180,9 @@ __asm volatile (
" MOV r0,#6 \n"
" MVN r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */
#if (__ARM_ARCH != 6) /* if ARMv7-M and higher... */
#if (__ARM_ARCH != 6) /*--------- if ARMv7-M and higher... */
" DSB \n" /* ARM Erratum 838869 */
#endif /* ARMv7-M and higher */
#endif /*--------- ARMv7-M and higher */
" BX r0 \n" /* exception-return to the QK activator */
);
}
@ -201,61 +200,77 @@ __asm volatile (
/* After the QK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the exception
* contex is accomplished by triggering the SVC or NMI exception.
* context is accomplished by triggering the NMI exception or the selected
* IRQ (if macro #QK_USE_IRQ_NUM is defined).
*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /* ARMv7-M and higher */
" MOV r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* before triggering the NMI/IRQ, make sure that the VFP stack frame
* will NOT be used...
*/
#if (__ARM_FP != 0) /*--------- if VFP available... */
/* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */
#endif /* ARMv7-M and higher */
#ifdef QK_USE_IRQ_NUM /* if use IRQ... */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QK_USE_IRQ_NUM / 32)) "\n"
" MOV r1,#1 \n"
" LSL r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */
" STR r1,[r0] \n" /* pend the IRQ */
" B . \n" /* wait for preemption by the IRQ */
#else /* use the NMI */
#ifndef QK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOV r1,#1 \n"
" LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */
" B . \n" /* wait for preemption by NMI */
#endif /* use NMI */
/* NOTE! interrupts are still disabled when NMI is used */
#else /*--------- use the selected IRQ */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QK_USE_IRQ_NUM / 32)) "\n"
" MOV r1,#1 \n"
" LSL r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */
" STR r1,[r0] \n" /* pend the IRQ */
/* now enable interrupts so that pended IRQ can be entered */
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /* ARMv7-M and higher */
" MOV r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
#endif /*--------- use IRQ */
" B . \n" /* wait for preemption by NMI/IRQ */
);
}
/*==========================================================================*/
/* This exception handler is used for returning back to the interrupted task.
/* This exception handler is used for returning back to the preempted thread.
* The exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack.
*/
__attribute__ ((naked, optimize("-fno-stack-protector")))
#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */
void QK_USE_IRQ_HANDLER(void)
#else /* use NMI */
void NMI_Handler(void)
#endif /* use NMI */
{
__attribute__ ((naked))
#ifndef QK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
void NMI_Handler(void) {
__asm volatile (
/* enable interrupts */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /*--------- ARMv7-M and higher */
" MOV r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
);
#else /* use the selected IRQ */
void QK_USE_IRQ_HANDLER(void) {
#endif /*--------- use IRQ */
__asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */
#if (__ARM_ARCH != 6) /* if ARMv7-M and higher... */
#if (__ARM_FP != 0) /* if VFP available... */
#if (__ARM_FP != 0) /*--------- if VFP available... */
" POP {r0,lr} \n" /* pop stack aligner and EXC_RETURN to LR */
" DSB \n" /* ARM Erratum 838869 */
#endif /* VFP available */
#endif /* ARMv7-M and higher */
#endif /*--------- VFP available */
" BX lr \n" /* return to the preempted task */
);
}

View File

@ -1,5 +1,5 @@
/*============================================================================
* QK/C++ port to ARM Cortex-M, IAR
* QP/C Real-Time Embedded Framework (RTEF)
* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
*
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com>
============================================================================*/
/*!
* @date Last updated on: 2022-05-13
* @version Last updated for: @ref qpcpp_7_0_1
* @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpc_7_0_2
*
* @file
* @brief QK/C++ port to ARM Cortex-M, IAR-ARM toolset
@ -62,7 +62,7 @@ void NMI_Handler(void);
* BASEPRI register. However, this method cannot disable interrupt
* priority zero, which is the default for all interrupts out of reset.
* The following code changes the SysTick priority and all IRQ priorities
* to the safe value QF_BASEPRI, wich the QF critical section can disable.
* to the safe value QF_BASEPRI, which the QF critical section can disable.
* This avoids breaching of the QF critical sections in case the
* application programmer forgets to explicitly set priorities of all
* "kernel aware" interrupts.
@ -71,7 +71,7 @@ void NMI_Handler(void);
* changed by the application-level code.
*/
void QK_init(void) {
#if (__ARM_ARCH != 6) /* if ARMv7-M or higher... */
#if (__ARM_ARCH != 6) /*--------- if ARMv7-M and higher... */
/* set exception priorities to QF_BASEPRI...
* SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault
@ -92,25 +92,24 @@ void QK_init(void) {
NVIC_IP[n] = QF_BASEPRI;
}
#endif /* ARMv7-M or higher */
#endif /*--------- ARMv7-M or higher */
/* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */
SCB_SYSPRI[3] = (SCB_SYSPRI[3] | (0xFFU << 16U));
#ifdef QK_USE_IRQ_NUM
#ifdef QK_USE_IRQ_NUM /*--------- QK IRQ specified? */
/* The QK port is configured to use a given ARM Cortex-M IRQ #
* to return to thread mode (default is to use the NMI exception)
*/
NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */
NVIC_EN[QK_USE_IRQ_NUM / 32U] = (1U << (QK_USE_IRQ_NUM % 32U));
#endif
#endif /*--------- QK IRQ specified */
}
/*==========================================================================*/
/* The PendSV_Handler exception handler is used for handling context switch
* and asynchronous preemption in QK. The use of the PendSV exception is
* the recommended and most efficient method for performing context switches
* with ARM Cortex-M.
/* The PendSV_Handler exception is used for handling the asynchronous
* preemption in QK. The use of the PendSV exception is the recommended and
* the most efficient method for performing context switches with ARM Cortex-M.
*
* The PendSV exception should have the lowest priority in the whole system
* (0xFF, see QK_init). All other exceptions and interrupts should have higher
@ -138,17 +137,17 @@ __asm volatile (
" LSLS r1,r1,#27 \n" /* r0 := (1 << 27) (UNPENDSVSET bit) */
/*<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<<*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSID i \n" /* disable interrupts (set PRIMASK) */
#else /* ARMv7-M and higher */
#if (__ARM_FP != 0) /* if VFP available... */
#if (__ARM_FP != 0) /*--------- if VFP available... */
" PUSH {r0,lr} \n" /* ... push lr plus stack-aligner */
#endif /* VFP available */
#endif /*--------- VFP available */
" MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n"
" CPSID i \n" /* disable interrutps with BASEPRI */
" MSR BASEPRI,r0 \n" /* apply the Cortex-M7 erraturm */
" CPSIE i \n" /* 837070, see SDEN-1068427. */
#endif /* ARMv7-M and higher */
#endif /*--------- ARMv7-M and higher */
/* The PendSV exception handler can be preempted by an interrupt,
* which might pend PendSV exception again. The following write to
@ -176,9 +175,9 @@ __asm volatile (
" MOVS r0,#6 \n"
" MVNS r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */
#if (__ARM_ARCH != 6) /* if ARMv7-M and higher... */
#if (__ARM_ARCH != 6) /*--------- if ARMv7-M and higher... */
" DSB \n" /* ARM Erratum 838869 */
#endif /* ARMv7-M and higher */
#endif /*--------- ARMv7-M and higher */
" BX r0 \n" /* exception-return to the QK activator */
);
}
@ -189,7 +188,6 @@ __asm volatile (
* NOTE: QK_thread_ret does not execute in the PendSV context!
* NOTE: QK_thread_ret is entered with interrupts DISABLED.
*/
__stackless
void QK_thread_ret(void) {
__asm volatile (
@ -197,24 +195,30 @@ __asm volatile (
/* After the QK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the exception
* contex is accomplished by triggering the SVC or NMI exception.
* context is accomplished by triggering the NMI exception or the selected
* IRQ (if macro #QK_USE_IRQ_NUM is defined).
*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /* ARMv7-M or higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* before triggering the NMI/IRQ, make sure that the VFP stack frame
* will NOT be used...
*/
#if (__ARM_FP != 0) /*--------- if VFP available... */
/* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */
#endif /* ARMv7-M or higher */
#ifdef QK_USE_IRQ_NUM /* if use IRQ... */
#ifndef QK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOVS r1,#1 \n"
" LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */
/* NOTE! interrupts are still disabled when NMI is used */
#else /*--------- use the selected IRQ */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QK_USE_IRQ_NUM / 32)) "\n"
" MOVS r1,#1 \n"
/* NOTE: the following IRQ bit calculation should be done simply as
@ -223,39 +227,49 @@ __asm volatile (
*/
" LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM - (QK_USE_IRQ_NUM/32)*32) "\n"
" STR r1,[r0] \n" /* pend the IRQ */
" B . \n" /* wait for preemption by the IRQ */
#else /* use the NMI */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOVS r1,#1 \n"
" LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */
" B . \n" /* wait for preemption by NMI */
#endif /* use NMI */
/* now enable interrupts so that pended IRQ can be entered */
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /* ARMv7-M and higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
#endif /*--------- use IRQ */
" B . \n" /* wait for preemption by NMI/IRQ */
);
}
/*==========================================================================*/
/* This exception handler is used for returning back to the interrupted task.
/* This exception handler is used for returning back to the preempted thread.
* The exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack.
*/
__stackless
#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */
void QK_USE_IRQ_HANDLER(void)
#else /* use NMI */
void NMI_Handler(void)
#endif /* use NMI */
{
#ifndef QK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
void NMI_Handler(void) {
__asm volatile (
/* enable interrupts */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /*--------- ARMv7-M and higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
);
#else /* use the selected IRQ */
void QK_USE_IRQ_HANDLER(void) {
#endif /*--------- use IRQ */
__asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */
#if (__ARM_ARCH != 6) /* if ARMv7-M and higher... */
#if (__ARM_FP != 0) /* if VFP available... */
#if (__ARM_FP != 0) /*--------- if VFP available... */
" POP {r0,lr} \n" /* pop stack aligner and EXC_RETURN to LR */
" DSB \n" /* ARM Erratum 838869 */
#endif /* VFP available */
#endif /* ARMv7-M and higher */
#endif /*--------- VFP available */
" BX lr \n" /* return to the preempted task */
);
}

View File

@ -1,5 +1,5 @@
/*============================================================================
* QXK/C++ port to ARM Cortex-M, ARM-CLANG
* QXK/C++ Real-Time to ARM Cortex-M, ARM-CLANG
* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
*
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com>
============================================================================*/
/*!
* @date Last updated on: 2022-06-30
* @version Last updated for: @ref qpcpp_7_0_1
* @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpc_7_0_2
*
* @file
* @brief QXK/C++ port to ARM Cortex-M, ARM-CLANG toolset
@ -220,7 +220,7 @@ __asm volatile (
#else /* ARMv7-M or higher */
" MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n"
" CPSID i \n" /* selectively disable interrutps with BASEPRI */
" MSR BASEPRI,r0 \n" /* apply the workaround the Cortex-M7 erraturm */
" MSR BASEPRI,r0 \n" /* apply the workaround the Cortex-M7 erratum */
" CPSIE i \n" /* 837070, see SDEN-1068427. */
#endif /* ARMv7-M or higher */
@ -256,7 +256,7 @@ __asm volatile (
" PUSH {r0,lr} \n" /* save the "aligner" and the EXC_RETURN value */
#endif /* VFP available */
/* The QXK activator must be called in a thread context, while this code
* executes in the handler contex of the PendSV exception. The switch
* executes in the handler context of the PendSV exception. The switch
* to the Thread mode is accomplished by returning from PendSV using
* a fabricated exception stack frame, where the return address is
* QXK_activate_().
@ -524,64 +524,82 @@ __asm volatile (
/* After the QXK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the exception
* contex is accomplished by triggering the SVC or NMI exception.
* context is accomplished by triggering the NMI exception or the selected
* IRQ (if macro #QXK_USE_IRQ_NUM is defined).
*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /* ARMv7-M and higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* before triggering the NMI/IRQ, make sure that the VFP stack frame
* will NOT be used...
*/
#if (__ARM_FP != 0) /*--------- if VFP available... */
/* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */
#endif /* ARMv7-M or higher */
#endif /*--------- VFP available */
#ifdef QXK_USE_IRQ_NUM /* if use IRQ... */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QXK_USE_IRQ_NUM / 32)) "\n"
" MOVS r1,#1 \n"
" LSLS r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */
" STR r1,[r0] \n" /* pend the IRQ */
" B . \n" /* wait for preemption by the IRQ */
#else /* use the NMI */
#ifndef QXK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOVS r1,#1 \n"
" LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */
" B . \n" /* wait for preemption by NMI */
#endif /* use NMI */
/* NOTE! interrupts are still disabled when NMI is used */
#else /*--------- use the selected IRQ */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QXK_USE_IRQ_NUM / 32)) "\n"
" MOVS r1,#1 \n"
" LSLS r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */
" STR r1,[r0] \n" /* pend the IRQ */
/* now enable interrupts so that pended IRQ can be entered */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /*--------- ARMv7-M and higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
#endif /*--------- use IRQ */
" B . \n" /* wait for preemption by NMI/IRQ */
);
}
/*==========================================================================*/
/* This exception handler is used for returning back to the interrupted task.
/* This exception handler is used for returning back to the preempted thread.
* The exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack.
*/
__attribute__ ((naked))
#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */
void QXK_USE_IRQ_HANDLER(void)
#else /* use NMI */
void NMI_Handler(void)
#endif /* use NMI */
{
#ifndef QXK_USE_IRQ_NUM /* IRQ NOT defined, used NMI by default */
void NMI_Handler(void) {
__asm volatile (
/* enable interrupts */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /*--------- ARMv7-M and higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
);
#else /*--------- use the selected IRQ */
void QXK_USE_IRQ_HANDLER(void) {
#endif /*--------- use IRQ */
__asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */
#if (__ARM_ARCH != 6) /* if ARMv7-M or higher... */
#if (__ARM_FP != 0) /* if VFP available... */
#if (__ARM_ARCH != 6) /*--------- if ARMv7-M or higher... */
#if (__ARM_FP != 0) /*--------- if VFP available... */
" POP {r0,lr} \n" /* restore alighner and EXC_RETURN into lr */
" DSB \n" /* ARM Erratum 838869 */
" TST lr,#(1 << 4) \n" /* is it return to the VFP exception frame? */
" IT EQ \n" /* if EXC_RETURN[4] is zero... */
" VLDMIAEQ sp!,{s16-s31} \n" /* ... restore VFP registers s16..s31 */
#endif /* VFP available */
#endif /* ARMv7-M or higher */
#endif /*--------- VFP available */
#endif /*--------- ARMv7-M or higher */
" BX lr \n" /* return to the preempted task */
);
}

View File

@ -1,5 +1,5 @@
/*============================================================================
* QXK/C++ port to ARM Cortex-M, GNU-ARM
* QP/C Real-Time Embedded Framework (RTEF)
* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
*
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com>
============================================================================*/
/*!
* @date Last updated on: 2022-06-30
* @version Last updated for: @ref qpcpp_7_0_1
* @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpc_7_0_2
*
* @file
* @brief QXK/C++ port to ARM Cortex-M, GNU-ARM toolset
@ -261,7 +261,7 @@ __asm volatile (
" PUSH {r0,lr} \n" /* save the "aligner" and the EXC_RETURN value */
#endif /* VFP available */
/* The QXK activator must be called in a thread context, while this code
* executes in the handler contex of the PendSV exception. The switch
* executes in the handler context of the PendSV exception. The switch
* to the Thread mode is accomplished by returning from PendSV using
* a fabricated exception stack frame, where the return address is
* QXK_activate_().
@ -529,64 +529,82 @@ __asm volatile (
/* After the QXK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the exception
* contex is accomplished by triggering the SVC or NMI exception.
* context is accomplished by triggering the NMI exception or the selected
* IRQ (if macro #QXK_USE_IRQ_NUM is defined).
*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /* ARMv7-M and higher */
" MOV r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* before triggering the NMI/IRQ, make sure that the VFP stack frame
* will NOT be used...
*/
#if (__ARM_FP != 0) /*--------- if VFP available... */
/* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" BIC r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */
#endif /* ARMv7-M or higher */
#endif /*--------- VFP available */
#ifdef QXK_USE_IRQ_NUM /* if use IRQ... */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QXK_USE_IRQ_NUM / 32)) "\n"
" MOV r1,#1 \n"
" LSL r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */
" STR r1,[r0] \n" /* pend the IRQ */
" B . \n" /* wait for preemption by the IRQ */
#else /* use the NMI */
#ifndef QXK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOV r1,#1 \n"
" LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */
" B . \n" /* wait for preemption by NMI */
#endif /* use NMI */
/* NOTE! interrupts are still disabled when NMI is used */
#else /*--------- use the selected IRQ */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QXK_USE_IRQ_NUM / 32)) "\n"
" MOV r1,#1 \n"
" LSL r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */
" STR r1,[r0] \n" /* pend the IRQ */
/* now enable interrupts so that pended IRQ can be entered */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /*--------- ARMv7-M and higher */
" MOV r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
#endif /*--------- use IRQ */
" B . \n" /* wait for preemption by NMI/IRQ */
);
}
/*==========================================================================*/
/* This exception handler is used for returning back to the interrupted task.
/* This exception handler is used for returning back to the preempted thread.
* The exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack.
*/
__attribute__ ((naked, optimize("-fno-stack-protector")))
#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */
void QXK_USE_IRQ_HANDLER(void)
#else /* use NMI */
void NMI_Handler(void)
#endif /* use NMI */
{
#ifndef QXK_USE_IRQ_NUM /* IRQ NOT defined, used NMI by default */
void NMI_Handler(void) {
__asm volatile (
/* enable interrupts */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /*--------- ARMv7-M and higher */
" MOV r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
);
#else /*--------- use the selected IRQ */
void QXK_USE_IRQ_HANDLER(void) {
#endif /*--------- use IRQ */
__asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */
#if (__ARM_ARCH != 6) /* if ARMv7-M or higher... */
#if (__ARM_FP != 0) /* if VFP available... */
#if (__ARM_ARCH != 6) /*--------- if ARMv7-M or higher... */
#if (__ARM_FP != 0) /*--------- if VFP available... */
" POP {r0,lr} \n" /* restore alighner and EXC_RETURN into lr */
" DSB \n" /* ARM Erratum 838869 */
" TST lr,#(1 << 4) \n" /* is it return to the VFP exception frame? */
" IT EQ \n" /* if EXC_RETURN[4] is zero... */
" VLDMIAEQ sp!,{s16-s31} \n" /* ... restore VFP registers s16..s31 */
#endif /* VFP available */
#endif /* ARMv7-M or higher */
#endif /*--------- VFP available */
#endif /*--------- ARMv7-M or higher */
" BX lr \n" /* return to the preempted task */
);
}

View File

@ -1,5 +1,5 @@
/*============================================================================
* QXK/C++ port to ARM Cortex-M, IAR
* QP/C Real-Time Embedded Framework (RTEF)
* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
*
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com>
============================================================================*/
/*!
* @date Last updated on: 2022-06-30
* @version Last updated for: @ref qpcpp_7_0_1
* @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpc_7_0_2
*
* @file
* @brief QXK/C++ port to ARM Cortex-M, IAR-ARM toolset
@ -206,7 +206,7 @@ void QXK_stackInit_(void *thr, QP::QXThreadHandler const handler,
*/
__stackless
void PendSV_Handler(void) {
__asm (
__asm volatile (
/* Prepare some constants before entering a critical section... */
" LDR r3,=QXK_attr_ \n"
@ -220,7 +220,7 @@ __asm (
#else /* ARMv7-M or higher */
" MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n"
" CPSID i \n" /* selectively disable interrutps with BASEPRI */
" MSR BASEPRI,r0 \n" /* apply the workaround the Cortex-M7 erraturm */
" MSR BASEPRI,r0 \n" /* apply the workaround the Cortex-M7 erratum */
" CPSIE i \n" /* 837070, see SDEN-1068427. */
#endif /* ARMv7-M or higher */
@ -256,7 +256,7 @@ __asm (
" PUSH {r0,lr} \n" /* save the "aligner" and the EXC_RETURN value */
#endif /* VFP available */
/* The QXK activator must be called in a thread context, while this code
* executes in the handler contex of the PendSV exception. The switch
* executes in the handler context of the PendSV exception. The switch
* to the Thread mode is accomplished by returning from PendSV using
* a fabricated exception stack frame, where the return address is
* QXK_activate_().
@ -519,73 +519,91 @@ __asm (
*/
__stackless
void QXK_thread_ret(void) {
__asm (
__asm volatile (
/* After the QXK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the exception
* contex is accomplished by triggering the SVC or NMI exception.
* context is accomplished by triggering the NMI exception or the selected
* IRQ (if macro #QXK_USE_IRQ_NUM is defined).
*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /* ARMv7-M or higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* before triggering the NMI/IRQ, make sure that the VFP stack frame
* will NOT be used...
*/
#if (__ARM_FP != 0) /*--------- if VFP available... */
/* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */
#endif /* ARMv7-M or higher */
#endif /*--------- VFP available */
#ifdef QXK_USE_IRQ_NUM /* if use IRQ... */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QXK_USE_IRQ_NUM / 32)) "\n"
" MOVS r1,#1 \n"
/* NOTE: the following IRQ bit calculation should be done simply as
* (QK_USE_IRQ_NUM % 32), but the IAR assembler does not accept it.
* As a workaround the modulo (%) operation is replaced with the following:
*/
" LSLS r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM - (QXK_USE_IRQ_NUM/32)*32) "\n"
" STR r1,[r0] \n" /* pend the IRQ */
" B . \n" /* wait for preemption by the IRQ */
#else /* use the NMI */
#ifndef QXK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOVS r1,#1 \n"
" LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */
" B . \n" /* wait for preemption by NMI */
#endif /* use NMI */
/* NOTE! interrupts are still disabled when NMI is used */
#else /*--------- use the selected IRQ */
" LDR r0,=" STRINGIFY(NVIC_PEND + (QXK_USE_IRQ_NUM / 32)) "\n"
" MOVS r1,#1 \n"
/* NOTE: the following IRQ bit calculation should be done simply as
* (QXK_USE_IRQ_NUM % 32), but the IAR assembler does not accept it.
* As a workaround the modulo (%) operation is replaced with the following:
*/
" LSLS r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM - (QXK_USE_IRQ_NUM/32)*32) "\n"
" STR r1,[r0] \n" /* pend the IRQ */
/* now enable interrupts so that pended IRQ can be entered */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /*--------- ARMv7-M and higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
#endif /*--------- use IRQ */
" B . \n" /* wait for preemption by NMI/IRQ */
);
}
/*==========================================================================*/
/* This exception handler is used for returning back to the interrupted task.
/* This exception handler is used for returning back to the preempted thread.
* The exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack.
*/
__stackless
#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */
void QXK_USE_IRQ_HANDLER(void)
#else /* use NMI */
void NMI_Handler(void)
#endif /* use NMI */
{
#ifndef QXK_USE_IRQ_NUM /* IRQ NOT defined, used NMI by default */
void NMI_Handler(void) {
__asm volatile (
/* enable interrupts */
#if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */
#else /*--------- ARMv7-M and higher */
" MOVS r0,#0 \n"
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /*--------- ARMv7-M and higher */
);
#else /*--------- use the selected IRQ */
void QXK_USE_IRQ_HANDLER(void) {
#endif /*--------- use IRQ */
__asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */
#if (__ARM_ARCH != 6) /* if ARMv7-M or higher... */
#if (__ARM_FP != 0) /* if VFP available... */
#if (__ARM_ARCH != 6) /*--------- if ARMv7-M or higher... */
#if (__ARM_FP != 0) /*--------- if VFP available... */
" POP {r0,lr} \n" /* restore alighner and EXC_RETURN into lr */
" DSB \n" /* ARM Erratum 838869 */
" TST lr,#(1 << 4) \n" /* is it return to the VFP exception frame? */
" IT EQ \n" /* if EXC_RETURN[4] is zero... */
" VLDMIAEQ sp!,{s16-s31} \n" /* ... restore VFP registers s16..s31 */
#endif /* VFP available */
#endif /* ARMv7-M or higher */
#endif /*--------- VFP available */
#endif /*--------- ARMv7-M or higher */
" BX lr \n" /* return to the preempted task */
);
}