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

View File

@ -337,7 +337,7 @@
<v6Rtti>0</v6Rtti> <v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define> <Define>QK_USE_IRQ_NUM=25 QK_USE_IRQ_HANDLER=CRYPTO_IRQHandler</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath> <IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls> </VariousControls>
@ -532,57 +532,6 @@
<FileName>qk_port.cpp</FileName> <FileName>qk_port.cpp</FileName>
<FileType>8</FileType> <FileType>8</FileType>
<FilePath>..\..\..\..\..\ports\arm-cm\qk\armclang\qk_port.cpp</FilePath> <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> </File>
</Files> </Files>
</Group> </Group>
@ -686,7 +635,7 @@
<TargetName>dpp-rel</TargetName> <TargetName>dpp-rel</TargetName>
<ToolsetNumber>0x4</ToolsetNumber> <ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName> <ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>5060183::V5.06 update 2 (build 183)::ARMCC</pCCUsed> <pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6> <uAC6>1</uAC6>
<TargetOption> <TargetOption>
<TargetCommonOption> <TargetCommonOption>
@ -1013,7 +962,7 @@
<v6Rtti>0</v6Rtti> <v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>NDEBUG EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define> <Define>NDEBUG</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath> <IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls> </VariousControls>
@ -1311,7 +1260,7 @@
<TargetName>dpp-spy</TargetName> <TargetName>dpp-spy</TargetName>
<ToolsetNumber>0x4</ToolsetNumber> <ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName> <ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6130001::V6.13.1::.\ARMCLANG</pCCUsed> <pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6> <uAC6>1</uAC6>
<TargetOption> <TargetOption>
<TargetCommonOption> <TargetCommonOption>
@ -1638,7 +1587,7 @@
<v6Rtti>0</v6Rtti> <v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>Q_SPY EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define> <Define>Q_SPY</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath> <IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls> </VariousControls>

View File

@ -138,8 +138,8 @@ LIBS :=
# defines # defines
DEFINES := -DEFM32PG1B200F256GM48=1 \ 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, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] # ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]

View File

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

View File

@ -337,7 +337,7 @@
<v6Rtti>0</v6Rtti> <v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define> <Define>QXK_USE_IRQ_HANDLER=CRYPTO_IRQHandler QXK_USE_IRQ_NUM=25</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath> <IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls> </VariousControls>
@ -552,57 +552,6 @@
<FileName>qxk_port.cpp</FileName> <FileName>qxk_port.cpp</FileName>
<FileType>8</FileType> <FileType>8</FileType>
<FilePath>..\..\..\..\..\ports\arm-cm\qxk\armclang\qxk_port.cpp</FilePath> <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> </File>
</Files> </Files>
</Group> </Group>
@ -1033,7 +982,7 @@
<v6Rtti>0</v6Rtti> <v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>NDEBUG EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define> <Define>NDEBUG</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath> <IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls> </VariousControls>
@ -1678,7 +1627,7 @@
<v6Rtti>0</v6Rtti> <v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>Q_SPY EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define> <Define>Q_SPY</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath> <IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls> </VariousControls>

View File

@ -143,8 +143,8 @@ LIBS :=
# defines # defines
DEFINES := -DEFM32PG1B200F256GM48=1 \ 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, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] # ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]

View File

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

View File

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

View File

@ -337,7 +337,7 @@
<v6Rtti>0</v6Rtti> <v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls>-fno-exceptions</MiscControls> <MiscControls>-fno-exceptions</MiscControls>
<Define></Define> <Define>QK_USE_IRQ_HANDLER=LCD_IRQHandler QK_USE_IRQ_NUM=30</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\nucleo-l053r8</IncludePath> <IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\nucleo-l053r8</IncludePath>
</VariousControls> </VariousControls>
@ -522,57 +522,6 @@
<FileName>qk_port.cpp</FileName> <FileName>qk_port.cpp</FileName>
<FileType>8</FileType> <FileType>8</FileType>
<FilePath>..\..\..\..\..\ports\arm-cm\qk\armclang\qk_port.cpp</FilePath> <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> </File>
</Files> </Files>
</Group> </Group>
@ -1281,7 +1230,7 @@
<TargetName>dpp-spy</TargetName> <TargetName>dpp-spy</TargetName>
<ToolsetNumber>0x4</ToolsetNumber> <ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName> <ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6130001::V6.13.1::.\ARMCLANG</pCCUsed> <pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6> <uAC6>1</uAC6>
<TargetOption> <TargetOption>
<TargetCommonOption> <TargetCommonOption>

View File

@ -134,8 +134,8 @@ LIBS :=
# defines # defines
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, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] # 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>
<option> <option>
<name>CCDefines</name> <name>CCDefines</name>
<state></state> <state>QK_USE_IRQ_HANDLER=LCD_IRQHandler</state>
<state>QK_USE_IRQ_NUM=30</state>
</option> </option>
<option> <option>
<name>CCPreprocFile</name> <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. 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 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: located in the "3rd_party" folder in the following location:
3rd_party\nucleo-l053r8\arm\startup_stm32l053xx.s 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. the STM32 NUCLEO Boards User Manual (ST document UM1724) for more information.
*** ***

View File

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

View File

@ -337,7 +337,7 @@
<v6Rtti>0</v6Rtti> <v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls>-fno-exceptions</MiscControls> <MiscControls>-fno-exceptions</MiscControls>
<Define></Define> <Define>QXK_USE_IRQ_HANDLER=LCD_IRQHandler QXK_USE_IRQ_NUM=30</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\nucleo-l053r8</IncludePath> <IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\nucleo-l053r8</IncludePath>
</VariousControls> </VariousControls>
@ -542,57 +542,6 @@
<FileName>qxk_port.cpp</FileName> <FileName>qxk_port.cpp</FileName>
<FileType>8</FileType> <FileType>8</FileType>
<FilePath>..\..\..\..\..\ports\arm-cm\qxk\armclang\qxk_port.cpp</FilePath> <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> </File>
</Files> </Files>
</Group> </Group>
@ -1321,7 +1270,7 @@
<TargetName>dpp-spy</TargetName> <TargetName>dpp-spy</TargetName>
<ToolsetNumber>0x4</ToolsetNumber> <ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName> <ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6130001::V6.13.1::.\ARMCLANG</pCCUsed> <pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6> <uAC6>1</uAC6>
<TargetOption> <TargetOption>
<TargetCommonOption> <TargetCommonOption>

View File

@ -138,8 +138,8 @@ LIBS :=
# defines # defines
DEFINES := -DQXK_ON_CONTEXT_SW \ 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, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] # 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> <option>
<name>CCDefines</name> <name>CCDefines</name>
<state>QXK_ON_CONTEXT_SW</state> <state>QXK_ON_CONTEXT_SW</state>
<state>QXK_USE_IRQ_HANDLER=LCD_IRQHandler</state>
<state>QXK_USE_IRQ_NUM=30</state>
</option> </option>
<option> <option>
<name>CCPreprocFile</name> <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. * Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
* *
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial * SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com> * <info@state-machine.com>
============================================================================*/ ============================================================================*/
/*! /*!
* @date Last updated on: 2022-05-13 * @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpcpp_7_0_1 * @version Last updated for: @ref qpc_7_0_2
* *
* @file * @file
* @brief QK/C++ port to ARM Cortex-M, ARM-CLANG toolset * @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 * BASEPRI register. However, this method cannot disable interrupt
* priority zero, which is the default for all interrupts out of reset. * priority zero, which is the default for all interrupts out of reset.
* The following code changes the SysTick priority and all IRQ priorities * 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 * This avoids breaching of the QF critical sections in case the
* application programmer forgets to explicitly set priorities of all * application programmer forgets to explicitly set priorities of all
* "kernel aware" interrupts. * "kernel aware" interrupts.
@ -71,7 +71,7 @@ void NMI_Handler(void);
* changed by the application-level code. * changed by the application-level code.
*/ */
void QK_init(void) { 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... /* set exception priorities to QF_BASEPRI...
* SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault * SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault
@ -92,25 +92,24 @@ void QK_init(void) {
NVIC_IP[n] = QF_BASEPRI; NVIC_IP[n] = QF_BASEPRI;
} }
#endif /* ARMv7-M or higher */ #endif /*--------- ARMv7-M or higher */
/* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */ /* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */
SCB_SYSPRI[3] = (SCB_SYSPRI[3] | (0xFFU << 16U)); 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 # /* 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) * to return to thread mode (default is to use the NMI exception)
*/ */
NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */ NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */
NVIC_EN[QK_USE_IRQ_NUM / 32U] = (1U << (QK_USE_IRQ_NUM % 32U)); 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 /* The PendSV_Handler exception is used for handling the asynchronous
* and asynchronous preemption in QK. The use of the PendSV exception is * preemption in QK. The use of the PendSV exception is the recommended and
* the recommended and most efficient method for performing context switches * the most efficient method for performing context switches with ARM Cortex-M.
* with ARM Cortex-M.
* *
* The PendSV exception should have the lowest priority in the whole system * The PendSV exception should have the lowest priority in the whole system
* (0xFF, see QK_init). All other exceptions and interrupts should have higher * (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) */ " LSLS r1,r1,#27 \n" /* r0 := (1 << 27) (UNPENDSVSET bit) */
/*<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<<*/ /*<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<<*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */ #if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSID i \n" /* disable interrupts (set PRIMASK) */ " CPSID i \n" /* disable interrupts (set PRIMASK) */
#else /* ARMv7-M and higher */ #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 */ " PUSH {r0,lr} \n" /* ... push lr plus stack-aligner */
#endif /* VFP available */ #endif /*--------- VFP available */
" MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n" " MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n"
" CPSID i \n" /* disable interrutps with BASEPRI */ " CPSID i \n" /* disable interrutps with BASEPRI */
" MSR BASEPRI,r0 \n" /* apply the Cortex-M7 erraturm */ " MSR BASEPRI,r0 \n" /* apply the Cortex-M7 erraturm */
" CPSIE i \n" /* 837070, see SDEN-1068427. */ " 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, /* The PendSV exception handler can be preempted by an interrupt,
* which might pend PendSV exception again. The following write to * 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) */ " LSRS r3,r1,#3 \n" /* r3 := (r1 >> 3), set the T bit (new xpsr) */
" LDR r2,=QK_activate_ \n" /* address of QK_activate_ */ " LDR r2,=QK_activate_ \n" /* address of QK_activate_ */
" SUBS r2,r2,#1 \n" /* align Thumb-address at halfword (new pc) */ " 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 */ " SUB sp,sp,#8*4 \n" /* reserve space for exception stack frame */
" ADD r0,sp,#5*4 \n" /* r0 := 5 registers below the SP */ " ADD r0,sp,#5*4 \n" /* r0 := 5 registers below the SP */
@ -176,9 +175,9 @@ __asm volatile (
" MOVS r0,#6 \n" " MOVS r0,#6 \n"
" MVNS r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */ " 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 */ " DSB \n" /* ARM Erratum 838869 */
#endif /* ARMv7-M and higher */ #endif /*--------- ARMv7-M and higher */
" BX r0 \n" /* exception-return to the QK activator */ " 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 /* After the QK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception, * thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the 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... */ /* before triggering the NMI/IRQ, make sure that the VFP stack frame
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */ * will NOT be used...
#else /* ARMv7-M and higher */ */
" MOVS r0,#0 \n" #if (__ARM_FP != 0) /*--------- if VFP available... */
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* make sure that the VFP stack frame will NOT be used */ /* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */ " MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */ " BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */ " MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */ " ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */ #endif /* VFP available */
#endif /* ARMv7-M and 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_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 */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOVS r1,#1 \n" " MOVS r1,#1 \n"
" LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ " LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */ " 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 exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt * the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack. * stack frame that must be at the top of the stack.
*/ */
__attribute__ ((naked)) __attribute__ ((naked))
#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */ #ifndef QK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
void QK_USE_IRQ_HANDLER(void) void NMI_Handler(void) {
#else /* use NMI */ __asm volatile (
void NMI_Handler(void) /* enable interrupts */
#endif /* use NMI */ #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 ( __asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */ " 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 */ " POP {r0,lr} \n" /* pop stack aligner and EXC_RETURN to LR */
" DSB \n" /* ARM Erratum 838869 */ " DSB \n" /* ARM Erratum 838869 */
#endif /* VFP available */ #endif /*--------- VFP available */
#endif /* ARMv7-M or higher */
" BX lr \n" /* return to the preempted task */ " 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. * Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
* *
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial * SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com> * <info@state-machine.com>
============================================================================*/ ============================================================================*/
/*! /*!
* @date Last updated on: 2022-05-13 * @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpcpp_7_0_1 * @version Last updated for: @ref qpc_7_0_2
* *
* @file * @file
* @brief QK/C++ port to ARM Cortex-M, GNU-ARM toolset * @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 * BASEPRI register. However, this method cannot disable interrupt
* priority zero, which is the default for all interrupts out of reset. * priority zero, which is the default for all interrupts out of reset.
* The following code changes the SysTick priority and all IRQ priorities * 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 * This avoids breaching of the QF critical sections in case the
* application programmer forgets to explicitly set priorities of all * application programmer forgets to explicitly set priorities of all
* "kernel aware" interrupts. * "kernel aware" interrupts.
@ -71,7 +71,7 @@ void NMI_Handler(void);
* changed by the application-level code. * changed by the application-level code.
*/ */
void QK_init(void) { 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... /* set exception priorities to QF_BASEPRI...
* SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault * SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault
@ -92,25 +92,24 @@ void QK_init(void) {
NVIC_IP[n] = QF_BASEPRI; NVIC_IP[n] = QF_BASEPRI;
} }
#endif /* ARMv7-M or higher */ #endif /*--------- ARMv7-M or higher */
/* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */ /* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */
SCB_SYSPRI[3] = (SCB_SYSPRI[3] | (0xFFU << 16U)); 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 # /* 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) * to return to thread mode (default is to use the NMI exception)
*/ */
NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */ NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */
NVIC_EN[QK_USE_IRQ_NUM / 32U] = (1U << (QK_USE_IRQ_NUM % 32U)); 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 /* The PendSV_Handler exception is used for handling the asynchronous
* and asynchronous preemption in QK. The use of the PendSV exception is * preemption in QK. The use of the PendSV exception is the recommended and
* the recommended and most efficient method for performing context switches * the most efficient method for performing context switches with ARM Cortex-M.
* with ARM Cortex-M.
* *
* The PendSV exception should have the lowest priority in the whole system * The PendSV exception should have the lowest priority in the whole system
* (0xFF, see QK_init). All other exceptions and interrupts should have higher * (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) */ " LSL r1,r1,#27 \n" /* r0 := (1 << 27) (UNPENDSVSET bit) */
/*<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<<*/ /*<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<<*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */ #if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSID i \n" /* disable interrupts (set PRIMASK) */ " CPSID i \n" /* disable interrupts (set PRIMASK) */
#else /* ARMv7-M and higher */ #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 */ " PUSH {r0,lr} \n" /* ... push lr plus stack-aligner */
#endif /* VFP available */ #endif /*--------- VFP available */
" MOV r0,#" STRINGIFY(QF_BASEPRI) "\n" " MOV r0,#" STRINGIFY(QF_BASEPRI) "\n"
" CPSID i \n" /* disable interrutps with BASEPRI */ " CPSID i \n" /* disable interrutps with BASEPRI */
" MSR BASEPRI,r0 \n" /* apply the Cortex-M7 erraturm */ " MSR BASEPRI,r0 \n" /* apply the Cortex-M7 erraturm */
" CPSIE i \n" /* 837070, see SDEN-1068427. */ " 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, /* The PendSV exception handler can be preempted by an interrupt,
* which might pend PendSV exception again. The following write to * 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) */ " LSR r3,r1,#3 \n" /* r3 := (r1 >> 3), set the T bit (new xpsr) */
" LDR r2,=QK_activate_ \n" /* address of QK_activate_ */ " LDR r2,=QK_activate_ \n" /* address of QK_activate_ */
" SUB r2,r2,#1 \n" /* align Thumb-address at halfword (new pc) */ " 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 */ " SUB sp,sp,#8*4 \n" /* reserve space for exception stack frame */
" ADD r0,sp,#5*4 \n" /* r0 := 5 registers below the SP */ " ADD r0,sp,#5*4 \n" /* r0 := 5 registers below the SP */
@ -181,9 +180,9 @@ __asm volatile (
" MOV r0,#6 \n" " MOV r0,#6 \n"
" MVN r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */ " 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 */ " DSB \n" /* ARM Erratum 838869 */
#endif /* ARMv7-M and higher */ #endif /*--------- ARMv7-M and higher */
" BX r0 \n" /* exception-return to the QK activator */ " 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 /* After the QK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception, * thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the 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... */ /* before triggering the NMI/IRQ, make sure that the VFP stack frame
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */ * will NOT be used...
#else /* ARMv7-M and higher */ */
" MOV r0,#0 \n" #if (__ARM_FP != 0) /*--------- if VFP available... */
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* make sure that the VFP stack frame will NOT be used */ /* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */ " MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */ " BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */ " MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */ " ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */ #endif /* VFP available */
#endif /* ARMv7-M and 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_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 */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOV r1,#1 \n" " MOV r1,#1 \n"
" LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ " LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */ " 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 exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt * the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack. * stack frame that must be at the top of the stack.
*/ */
__attribute__ ((naked, optimize("-fno-stack-protector"))) __attribute__ ((naked))
#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */ #ifndef QK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
void QK_USE_IRQ_HANDLER(void) void NMI_Handler(void) {
#else /* use NMI */ __asm volatile (
void NMI_Handler(void) /* enable interrupts */
#endif /* use NMI */ #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 ( __asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */ " 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 */ " POP {r0,lr} \n" /* pop stack aligner and EXC_RETURN to LR */
" DSB \n" /* ARM Erratum 838869 */ " DSB \n" /* ARM Erratum 838869 */
#endif /* VFP available */ #endif /*--------- VFP available */
#endif /* ARMv7-M and higher */
" BX lr \n" /* return to the preempted task */ " 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. * Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
* *
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial * SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com> * <info@state-machine.com>
============================================================================*/ ============================================================================*/
/*! /*!
* @date Last updated on: 2022-05-13 * @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpcpp_7_0_1 * @version Last updated for: @ref qpc_7_0_2
* *
* @file * @file
* @brief QK/C++ port to ARM Cortex-M, IAR-ARM toolset * @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 * BASEPRI register. However, this method cannot disable interrupt
* priority zero, which is the default for all interrupts out of reset. * priority zero, which is the default for all interrupts out of reset.
* The following code changes the SysTick priority and all IRQ priorities * 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 * This avoids breaching of the QF critical sections in case the
* application programmer forgets to explicitly set priorities of all * application programmer forgets to explicitly set priorities of all
* "kernel aware" interrupts. * "kernel aware" interrupts.
@ -71,7 +71,7 @@ void NMI_Handler(void);
* changed by the application-level code. * changed by the application-level code.
*/ */
void QK_init(void) { 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... /* set exception priorities to QF_BASEPRI...
* SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault * SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault
@ -92,25 +92,24 @@ void QK_init(void) {
NVIC_IP[n] = QF_BASEPRI; NVIC_IP[n] = QF_BASEPRI;
} }
#endif /* ARMv7-M or higher */ #endif /*--------- ARMv7-M or higher */
/* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */ /* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */
SCB_SYSPRI[3] = (SCB_SYSPRI[3] | (0xFFU << 16U)); 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 # /* 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) * to return to thread mode (default is to use the NMI exception)
*/ */
NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */ NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */
NVIC_EN[QK_USE_IRQ_NUM / 32U] = (1U << (QK_USE_IRQ_NUM % 32U)); 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 /* The PendSV_Handler exception is used for handling the asynchronous
* and asynchronous preemption in QK. The use of the PendSV exception is * preemption in QK. The use of the PendSV exception is the recommended and
* the recommended and most efficient method for performing context switches * the most efficient method for performing context switches with ARM Cortex-M.
* with ARM Cortex-M.
* *
* The PendSV exception should have the lowest priority in the whole system * The PendSV exception should have the lowest priority in the whole system
* (0xFF, see QK_init). All other exceptions and interrupts should have higher * (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) */ " LSLS r1,r1,#27 \n" /* r0 := (1 << 27) (UNPENDSVSET bit) */
/*<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<<*/ /*<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<<*/
#if (__ARM_ARCH == 6) /* if ARMv6-M... */ #if (__ARM_ARCH == 6) /*--------- if ARMv6-M... */
" CPSID i \n" /* disable interrupts (set PRIMASK) */ " CPSID i \n" /* disable interrupts (set PRIMASK) */
#else /* ARMv7-M and higher */ #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 */ " PUSH {r0,lr} \n" /* ... push lr plus stack-aligner */
#endif /* VFP available */ #endif /*--------- VFP available */
" MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n" " MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n"
" CPSID i \n" /* disable interrutps with BASEPRI */ " CPSID i \n" /* disable interrutps with BASEPRI */
" MSR BASEPRI,r0 \n" /* apply the Cortex-M7 erraturm */ " MSR BASEPRI,r0 \n" /* apply the Cortex-M7 erraturm */
" CPSIE i \n" /* 837070, see SDEN-1068427. */ " 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, /* The PendSV exception handler can be preempted by an interrupt,
* which might pend PendSV exception again. The following write to * which might pend PendSV exception again. The following write to
@ -176,9 +175,9 @@ __asm volatile (
" MOVS r0,#6 \n" " MOVS r0,#6 \n"
" MVNS r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */ " 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 */ " DSB \n" /* ARM Erratum 838869 */
#endif /* ARMv7-M and higher */ #endif /*--------- ARMv7-M and higher */
" BX r0 \n" /* exception-return to the QK activator */ " 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 does not execute in the PendSV context!
* NOTE: QK_thread_ret is entered with interrupts DISABLED. * NOTE: QK_thread_ret is entered with interrupts DISABLED.
*/ */
__stackless __stackless
void QK_thread_ret(void) { void QK_thread_ret(void) {
__asm volatile ( __asm volatile (
@ -197,24 +195,30 @@ __asm volatile (
/* After the QK activator returns, we need to resume the preempted /* After the QK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception, * thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the 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... */ /* before triggering the NMI/IRQ, make sure that the VFP stack frame
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */ * will NOT be used...
#else /* ARMv7-M or higher */ */
" MOVS r0,#0 \n" #if (__ARM_FP != 0) /*--------- if VFP available... */
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* make sure that the VFP stack frame will NOT be used */ /* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */ " MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */ " BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */ " MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */ " ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */ #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" " LDR r0,=" STRINGIFY(NVIC_PEND + (QK_USE_IRQ_NUM / 32)) "\n"
" MOVS r1,#1 \n" " MOVS r1,#1 \n"
/* NOTE: the following IRQ bit calculation should be done simply as /* 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" " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM - (QK_USE_IRQ_NUM/32)*32) "\n"
" STR r1,[r0] \n" /* pend the IRQ */ " STR r1,[r0] \n" /* pend the IRQ */
" B . \n" /* wait for preemption by the IRQ */
#else /* use the NMI */ /* now enable interrupts so that pended IRQ can be entered */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ #if (__ARM_ARCH == 6) /* if ARMv6-M... */
" MOVS r1,#1 \n" " CPSIE i \n" /* enable interrupts (clear PRIMASK) */
" LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ #else /* ARMv7-M and higher */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */ " MOVS r0,#0 \n"
" B . \n" /* wait for preemption by NMI */ " MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#endif /* use NMI */ #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 exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt * the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack. * stack frame that must be at the top of the stack.
*/ */
__stackless __stackless
#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */ #ifndef QK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
void QK_USE_IRQ_HANDLER(void) void NMI_Handler(void) {
#else /* use NMI */ __asm volatile (
void NMI_Handler(void) /* enable interrupts */
#endif /* use NMI */ #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 ( __asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */ " 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 */ " POP {r0,lr} \n" /* pop stack aligner and EXC_RETURN to LR */
" DSB \n" /* ARM Erratum 838869 */ " DSB \n" /* ARM Erratum 838869 */
#endif /* VFP available */ #endif /*--------- VFP available */
#endif /* ARMv7-M and higher */
" BX lr \n" /* return to the preempted task */ " 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. * Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
* *
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial * SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com> * <info@state-machine.com>
============================================================================*/ ============================================================================*/
/*! /*!
* @date Last updated on: 2022-06-30 * @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpcpp_7_0_1 * @version Last updated for: @ref qpc_7_0_2
* *
* @file * @file
* @brief QXK/C++ port to ARM Cortex-M, ARM-CLANG toolset * @brief QXK/C++ port to ARM Cortex-M, ARM-CLANG toolset
@ -220,7 +220,7 @@ __asm volatile (
#else /* ARMv7-M or higher */ #else /* ARMv7-M or higher */
" MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n" " MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n"
" CPSID i \n" /* selectively disable interrutps with BASEPRI */ " 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. */ " CPSIE i \n" /* 837070, see SDEN-1068427. */
#endif /* ARMv7-M or higher */ #endif /* ARMv7-M or higher */
@ -256,7 +256,7 @@ __asm volatile (
" PUSH {r0,lr} \n" /* save the "aligner" and the EXC_RETURN value */ " PUSH {r0,lr} \n" /* save the "aligner" and the EXC_RETURN value */
#endif /* VFP available */ #endif /* VFP available */
/* The QXK activator must be called in a thread context, while this code /* 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 * to the Thread mode is accomplished by returning from PendSV using
* a fabricated exception stack frame, where the return address is * a fabricated exception stack frame, where the return address is
* QXK_activate_(). * QXK_activate_().
@ -524,64 +524,82 @@ __asm volatile (
/* After the QXK activator returns, we need to resume the preempted /* After the QXK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception, * thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the 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... */ /* before triggering the NMI/IRQ, make sure that the VFP stack frame
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */ * will NOT be used...
#else /* ARMv7-M and higher */ */
" MOVS r0,#0 \n" #if (__ARM_FP != 0) /*--------- if VFP available... */
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* make sure that the VFP stack frame will NOT be used */ /* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */ " MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */ " BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */ " MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */ " ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */ #endif /*--------- VFP available */
#endif /* ARMv7-M or higher */
#ifdef QXK_USE_IRQ_NUM /* if use IRQ... */ #ifndef QXK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
" 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 */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOVS r1,#1 \n" " MOVS r1,#1 \n"
" LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ " LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */ " 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 exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt * the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack. * stack frame that must be at the top of the stack.
*/ */
__attribute__ ((naked)) __attribute__ ((naked))
#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */ #ifndef QXK_USE_IRQ_NUM /* IRQ NOT defined, used NMI by default */
void QXK_USE_IRQ_HANDLER(void) void NMI_Handler(void) {
#else /* use NMI */ __asm volatile (
void NMI_Handler(void) /* enable interrupts */
#endif /* use NMI */ #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 ( __asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */ " ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */
#if (__ARM_ARCH != 6) /* if ARMv7-M or higher... */ #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" /* restore alighner and EXC_RETURN into lr */ " POP {r0,lr} \n" /* restore alighner and EXC_RETURN into lr */
" DSB \n" /* ARM Erratum 838869 */ " DSB \n" /* ARM Erratum 838869 */
" TST lr,#(1 << 4) \n" /* is it return to the VFP exception frame? */ " TST lr,#(1 << 4) \n" /* is it return to the VFP exception frame? */
" IT EQ \n" /* if EXC_RETURN[4] is zero... */ " IT EQ \n" /* if EXC_RETURN[4] is zero... */
" VLDMIAEQ sp!,{s16-s31} \n" /* ... restore VFP registers s16..s31 */ " VLDMIAEQ sp!,{s16-s31} \n" /* ... restore VFP registers s16..s31 */
#endif /* VFP available */ #endif /*--------- VFP available */
#endif /* ARMv7-M or higher */ #endif /*--------- ARMv7-M or higher */
" BX lr \n" /* return to the preempted task */ " 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. * Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
* *
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial * SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com> * <info@state-machine.com>
============================================================================*/ ============================================================================*/
/*! /*!
* @date Last updated on: 2022-06-30 * @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpcpp_7_0_1 * @version Last updated for: @ref qpc_7_0_2
* *
* @file * @file
* @brief QXK/C++ port to ARM Cortex-M, GNU-ARM toolset * @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 */ " PUSH {r0,lr} \n" /* save the "aligner" and the EXC_RETURN value */
#endif /* VFP available */ #endif /* VFP available */
/* The QXK activator must be called in a thread context, while this code /* 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 * to the Thread mode is accomplished by returning from PendSV using
* a fabricated exception stack frame, where the return address is * a fabricated exception stack frame, where the return address is
* QXK_activate_(). * QXK_activate_().
@ -529,64 +529,82 @@ __asm volatile (
/* After the QXK activator returns, we need to resume the preempted /* After the QXK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception, * thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the 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... */ /* before triggering the NMI/IRQ, make sure that the VFP stack frame
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */ * will NOT be used...
#else /* ARMv7-M and higher */ */
" MOV r0,#0 \n" #if (__ARM_FP != 0) /*--------- if VFP available... */
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* make sure that the VFP stack frame will NOT be used */ /* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */ " 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) */ " MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */ " ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */ #endif /*--------- VFP available */
#endif /* ARMv7-M or higher */
#ifdef QXK_USE_IRQ_NUM /* if use IRQ... */ #ifndef QXK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
" 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 */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOV r1,#1 \n" " MOV r1,#1 \n"
" LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ " LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */ " 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 exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt * the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack. * stack frame that must be at the top of the stack.
*/ */
__attribute__ ((naked, optimize("-fno-stack-protector"))) __attribute__ ((naked, optimize("-fno-stack-protector")))
#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */ #ifndef QXK_USE_IRQ_NUM /* IRQ NOT defined, used NMI by default */
void QXK_USE_IRQ_HANDLER(void) void NMI_Handler(void) {
#else /* use NMI */ __asm volatile (
void NMI_Handler(void) /* enable interrupts */
#endif /* use NMI */ #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 ( __asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */ " ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */
#if (__ARM_ARCH != 6) /* if ARMv7-M or higher... */ #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" /* restore alighner and EXC_RETURN into lr */ " POP {r0,lr} \n" /* restore alighner and EXC_RETURN into lr */
" DSB \n" /* ARM Erratum 838869 */ " DSB \n" /* ARM Erratum 838869 */
" TST lr,#(1 << 4) \n" /* is it return to the VFP exception frame? */ " TST lr,#(1 << 4) \n" /* is it return to the VFP exception frame? */
" IT EQ \n" /* if EXC_RETURN[4] is zero... */ " IT EQ \n" /* if EXC_RETURN[4] is zero... */
" VLDMIAEQ sp!,{s16-s31} \n" /* ... restore VFP registers s16..s31 */ " VLDMIAEQ sp!,{s16-s31} \n" /* ... restore VFP registers s16..s31 */
#endif /* VFP available */ #endif /*--------- VFP available */
#endif /* ARMv7-M or higher */ #endif /*--------- ARMv7-M or higher */
" BX lr \n" /* return to the preempted task */ " 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. * Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
* *
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial * SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
@ -23,8 +23,8 @@
* <info@state-machine.com> * <info@state-machine.com>
============================================================================*/ ============================================================================*/
/*! /*!
* @date Last updated on: 2022-06-30 * @date Last updated on: 2022-08-13
* @version Last updated for: @ref qpcpp_7_0_1 * @version Last updated for: @ref qpc_7_0_2
* *
* @file * @file
* @brief QXK/C++ port to ARM Cortex-M, IAR-ARM toolset * @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 __stackless
void PendSV_Handler(void) { void PendSV_Handler(void) {
__asm ( __asm volatile (
/* Prepare some constants before entering a critical section... */ /* Prepare some constants before entering a critical section... */
" LDR r3,=QXK_attr_ \n" " LDR r3,=QXK_attr_ \n"
@ -220,7 +220,7 @@ __asm (
#else /* ARMv7-M or higher */ #else /* ARMv7-M or higher */
" MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n" " MOVS r0,#" STRINGIFY(QF_BASEPRI) "\n"
" CPSID i \n" /* selectively disable interrutps with BASEPRI */ " 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. */ " CPSIE i \n" /* 837070, see SDEN-1068427. */
#endif /* ARMv7-M or higher */ #endif /* ARMv7-M or higher */
@ -256,7 +256,7 @@ __asm (
" PUSH {r0,lr} \n" /* save the "aligner" and the EXC_RETURN value */ " PUSH {r0,lr} \n" /* save the "aligner" and the EXC_RETURN value */
#endif /* VFP available */ #endif /* VFP available */
/* The QXK activator must be called in a thread context, while this code /* 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 * to the Thread mode is accomplished by returning from PendSV using
* a fabricated exception stack frame, where the return address is * a fabricated exception stack frame, where the return address is
* QXK_activate_(). * QXK_activate_().
@ -519,73 +519,91 @@ __asm (
*/ */
__stackless __stackless
void QXK_thread_ret(void) { void QXK_thread_ret(void) {
__asm ( __asm volatile (
/* After the QXK activator returns, we need to resume the preempted /* After the QXK activator returns, we need to resume the preempted
* thread. However, this must be accomplished by a return-from-exception, * thread. However, this must be accomplished by a return-from-exception,
* while we are still in the thread context. The switch to the 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... */ /* before triggering the NMI/IRQ, make sure that the VFP stack frame
" CPSIE i \n" /* enable interrupts (clear PRIMASK) */ * will NOT be used...
#else /* ARMv7-M or higher */ */
" MOVS r0,#0 \n" #if (__ARM_FP != 0) /*--------- if VFP available... */
" MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */
#if (__ARM_FP != 0) /* if VFP available... */
/* make sure that the VFP stack frame will NOT be used */ /* make sure that the VFP stack frame will NOT be used */
" MRS r0,CONTROL \n" /* r0 := CONTROL */ " MRS r0,CONTROL \n" /* r0 := CONTROL */
" BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */ " BICS r0,r0,#4 \n" /* r0 := r0 & ~4 (FPCA bit) */
" MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */ " MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */ " ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /* VFP available */ #endif /*--------- VFP available */
#endif /* ARMv7-M or higher */
#ifdef QXK_USE_IRQ_NUM /* if use IRQ... */ #ifndef QXK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
" 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 */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOVS r1,#1 \n" " MOVS r1,#1 \n"
" LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ " LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
" STR r1,[r0] \n" /* ICSR[31] := 1 (pend NMI) */ " 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 exception handler simply removes its own interrupt stack frame from
* the stack (MSP) and returns to the preempted task using the interrupt * the stack (MSP) and returns to the preempted task using the interrupt
* stack frame that must be at the top of the stack. * stack frame that must be at the top of the stack.
*/ */
__stackless __stackless
#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */ #ifndef QXK_USE_IRQ_NUM /* IRQ NOT defined, used NMI by default */
void QXK_USE_IRQ_HANDLER(void) void NMI_Handler(void) {
#else /* use NMI */ __asm volatile (
void NMI_Handler(void) /* enable interrupts */
#endif /* use NMI */ #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 ( __asm volatile (
" ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */ " ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */
#if (__ARM_ARCH != 6) /* if ARMv7-M or higher... */ #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" /* restore alighner and EXC_RETURN into lr */ " POP {r0,lr} \n" /* restore alighner and EXC_RETURN into lr */
" DSB \n" /* ARM Erratum 838869 */ " DSB \n" /* ARM Erratum 838869 */
" TST lr,#(1 << 4) \n" /* is it return to the VFP exception frame? */ " TST lr,#(1 << 4) \n" /* is it return to the VFP exception frame? */
" IT EQ \n" /* if EXC_RETURN[4] is zero... */ " IT EQ \n" /* if EXC_RETURN[4] is zero... */
" VLDMIAEQ sp!,{s16-s31} \n" /* ... restore VFP registers s16..s31 */ " VLDMIAEQ sp!,{s16-s31} \n" /* ... restore VFP registers s16..s31 */
#endif /* VFP available */ #endif /*--------- VFP available */
#endif /* ARMv7-M or higher */ #endif /*--------- ARMv7-M or higher */
" BX lr \n" /* return to the preempted task */ " BX lr \n" /* return to the preempted task */
); );
} }