mirror of
https://github.com/QuantumLeaps/qpcpp.git
synced 2025-01-14 05:42:57 +08:00
5.6.4
This commit is contained in:
parent
7febc1a01b
commit
bdc74240aa
4
.gitignore
vendored
4
.gitignore
vendored
@ -21,6 +21,7 @@
|
||||
*.log
|
||||
*.chm
|
||||
*.zip
|
||||
*.pdb
|
||||
*.ncb
|
||||
*.suo
|
||||
*.chw
|
||||
@ -29,7 +30,7 @@
|
||||
*.avrsuo
|
||||
*.Debug
|
||||
*.Release
|
||||
lint*.out
|
||||
lint*.txt
|
||||
*.Miro
|
||||
*.bak
|
||||
|
||||
@ -40,6 +41,7 @@ dbg/
|
||||
rel/
|
||||
spy/
|
||||
settings/
|
||||
.settings/
|
||||
|
||||
Debug/
|
||||
Release/
|
||||
|
@ -2,7 +2,7 @@
|
||||
; * @file startup_TM4C123GH6PM.s for IAR ARM assembler
|
||||
; * @brief CMSIS Cortex-M4F Core Device Startup File for TM4C123GH6PM
|
||||
; * @version CMSIS 4.3.0
|
||||
; * @date 20 August 2015
|
||||
; * @date 24 April 2016
|
||||
; *
|
||||
; * @description
|
||||
; * Created from the CMSIS template for the specified device
|
||||
@ -521,11 +521,10 @@ PWM1Gen2_IRQHandler
|
||||
PWM1Gen3_IRQHandler
|
||||
PWM1Fault_IRQHandler
|
||||
MOVS r0,#0
|
||||
MOVS r1,#-1 ; 0xFFFFFFF
|
||||
MOVS r1,#0xFF
|
||||
B assert_failed
|
||||
|
||||
;******************************************************************************
|
||||
;
|
||||
;*****************************************************************************
|
||||
; The function assert_failed defines the error/assertion handling policy
|
||||
; for the application. After making sure that the stack is OK, this function
|
||||
; calls Q_onAssert, which should NOT return (typically reset the CPU).
|
||||
@ -535,11 +534,12 @@ PWM1Fault_IRQHandler
|
||||
; The C proptotype of the assert_failed() and Q_onAssert() functions are:
|
||||
; void assert_failed(char const *file, int line);
|
||||
; void Q_onAssert (char const *file, int line);
|
||||
;******************************************************************************
|
||||
;*****************************************************************************
|
||||
PUBLIC assert_failed
|
||||
EXTERN Q_onAssert
|
||||
assert_failed
|
||||
LDR sp,=sfe(CSTACK) ; re-set the SP in case of stack overflow
|
||||
LDR r2,=sfe(CSTACK) ; load the original top of stack
|
||||
MOV sp,r2 ; re-set the SP in case of stack overflow
|
||||
BL Q_onAssert ; call the application-specific handler
|
||||
|
||||
B . ; should not be reached, but just in case...
|
||||
|
@ -5,7 +5,7 @@
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "QP/C++"
|
||||
PROJECT_NUMBER = "5.6.3"
|
||||
PROJECT_NUMBER = "5.6.4"
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO = images/header_logo_ql.png
|
||||
OUTPUT_DIRECTORY =
|
||||
|
@ -5,7 +5,7 @@
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "QP/C++"
|
||||
PROJECT_NUMBER = "5.6.3"
|
||||
PROJECT_NUMBER = "5.6.4"
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO = images/header_logo_ql.png
|
||||
OUTPUT_DIRECTORY =
|
||||
|
@ -1,8 +1,12 @@
|
||||
namespace QP {
|
||||
|
||||
/** @page history Revision History
|
||||
|
||||
|
||||
@section qpcpp_5_6_4 Version 5.6.4, 2016-04-25
|
||||
This release fixes a serious Bug #128 (https://sourceforge.net/p/qpc/bugs/128 ) in the QK port to ARM Cortex-M introduced back in QP 5.6.1
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@section qpcpp_5_6_3 Version 5.6.3, 2016-04-12
|
||||
This release fixes a serious Bug #127 (https://sourceforge.net/p/qpc/bugs/127 ) in the QK preemptive scheduler introduced in QP 5.6.2.
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
@echo off
|
||||
:: ==========================================================================
|
||||
:: Product: QP/C++ script for generating Doxygen documentation
|
||||
:: Last Updated for Version: 5.6.3
|
||||
:: Date of the Last Update: 2016-04-12
|
||||
:: Last Updated for Version: 5.6.4
|
||||
:: Date of the Last Update: 2016-04-24
|
||||
::
|
||||
:: Q u a n t u m L e a P s
|
||||
:: ---------------------------
|
||||
@ -38,7 +38,7 @@ echo usage:
|
||||
echo make
|
||||
echo make -CHM
|
||||
|
||||
set VERSION=5.6.3
|
||||
set VERSION=5.6.4
|
||||
|
||||
:: Generate Resource Standard Metrics for QP/C++ .............................
|
||||
set DOXHOME="C:\tools\doxygen\bin"
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @page metrics Code Metrics
|
||||
|
||||
@code
|
||||
Standard Code Metrics for QP/C++ 5.6.3
|
||||
Standard Code Metrics for QP/C++ 5.6.4
|
||||
|
||||
Resource Standard Metrics (TM) for C, C++, C# and Java
|
||||
Version 7.75 - mSquaredTechnologies.com
|
||||
@ -9,7 +9,7 @@
|
||||
License Type: Windows Single User License
|
||||
Licensed To : Quantum Leaps, LLC
|
||||
License No. : WS2975 License Date: Dec 15, 2013
|
||||
Build Date : Sep 2 2009 Run Date: Apr 12, 2016
|
||||
Build Date : Sep 2 2009 Run Date: Apr 24, 2016
|
||||
(C)1996-2009 M Squared Technologies LLC
|
||||
________________________________________________________________________
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
"C:\qp\qpcpp\ports\arm-cm\qk\gnu\qk_port.h" 48 19 Warning 530: Symbol 'regIPSR' (line 46) not initialized [MISRA C++ Rule 8-5-1]
|
||||
"C:\qp\qpcpp\ports\arm-cm\qk\gnu\qk_port.h" 46 1 Info 830: Location cited in prior message
|
||||
"C:\qp\qpcpp\ports\arm-cm\qk\gnu\qk_port.h" 52 32 Note 1923: macro 'QK_ISR_ENTRY' could become const variable [MISRA C++ Rule 16-2-2]
|
||||
"C:\qp\qpcpp\ports\arm-cm\qk\gnu\qk_port.h" 65 33 Note 1960: Violates MISRA C++ 2008 Required Rule 7-3-1, Global declaration of symbol 'QK_nextPrio_'
|
||||
"C:\qp\qpcpp\include\qpset.h" 128 58 Note 1960: Violates MISRA C++ 2008 Required Rule 5-0-8, Cast of integer cvalue expression to larger type
|
||||
"C:\qp\qpcpp\include\qpset.h" 221 21 Note 1960: Violates MISRA C++ 2008 Required Rule 5-0-8, Cast of integer cvalue expression to larger type
|
||||
"C:\qp\qpcpp\include\qpset.h" 224 21 Note 1960: Violates MISRA C++ 2008 Required Rule 5-0-8, Cast of integer cvalue expression to larger type
|
||||
@ -57,7 +56,6 @@
|
||||
"C:\qp\qpcpp\ports\arm-cm\qk\gnu\qk_port.h" 48 19 Warning 530: Symbol 'regIPSR' (line 46) not initialized [MISRA C++ Rule 8-5-1]
|
||||
"C:\qp\qpcpp\ports\arm-cm\qk\gnu\qk_port.h" 46 1 Info 830: Location cited in prior message
|
||||
"C:\qp\qpcpp\ports\arm-cm\qk\gnu\qk_port.h" 52 32 Note 1923: macro 'QK_ISR_ENTRY' could become const variable [MISRA C++ Rule 16-2-2]
|
||||
"C:\qp\qpcpp\ports\arm-cm\qk\gnu\qk_port.h" 65 33 Note 1960: Violates MISRA C++ 2008 Required Rule 7-3-1, Global declaration of symbol 'QK_nextPrio_'
|
||||
"C:\qp\qpcpp\ports\arm-cm\qk\gnu\qs_port.h" 51 10 Warning 537: Repeated include file 'C:\qp\qpcpp\ports\arm-cm\qk\gnu\qf_port.h'
|
||||
"C:\qp\qpcpp\include\qs.h" 61 9 Note 1960: Violates MISRA C++ 2008 Required Rule 16-0-4, Function-like macro defined: 'QS_PTR_AT_'
|
||||
"C:\qp\qpcpp\include\qs.h" 61 37 Note 1960: Violates MISRA C++ 2008 Required Rule 16-0-6, unparenthesized macro parameter in definition of macro: 'QS_PTR_AT_'
|
||||
@ -476,4 +474,4 @@ Count Type Number Text
|
||||
2 Note 963 Qualifier const or volatile ___ a type; use ___ to reverse the test
|
||||
1 Note 1914 Default constructor '___' (___) not referenced
|
||||
2 Note 1923 macro '___' could become const variable
|
||||
27 Note 1960 Violates MISRA C++ 2008 Required Rule ___, ___
|
||||
25 Note 1960 Violates MISRA C++ 2008 Required Rule ___, ___
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Purpose: startup file for TM4C123GH6PM Cortex-M4 device.
|
||||
* Should be used with TI CCS-ARM Compiler
|
||||
* Version: CMSIS 4.3.0
|
||||
* Date: 2015-Nov-10
|
||||
* Date: 2016-Apr-22
|
||||
*
|
||||
* Created from the CMSIS template for the specified device
|
||||
* Quantum Leaps, www.state-machine.com
|
||||
@ -373,6 +373,7 @@ void Default_Handler(void) {
|
||||
);
|
||||
}
|
||||
/*..........................................................................*/
|
||||
/* defined in QK port
|
||||
void NMI_Handler(void) {
|
||||
__asm(
|
||||
" .global assert_failed\n\r"
|
||||
@ -381,6 +382,7 @@ void NMI_Handler(void) {
|
||||
" b.w assert_failed\n\r"
|
||||
);
|
||||
}
|
||||
*/
|
||||
/*..........................................................................*/
|
||||
void MemManage_Handler(void) {
|
||||
__asm(
|
||||
|
@ -1,45 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Default Linker Command file for the Texas Instruments TM4C123GH6PM
|
||||
*
|
||||
* This is derived from revision 14351 of the TivaWare Library.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
--retain=g_pfnVectors
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (RX) : origin = 0x00000000, length = 0x00040000
|
||||
SRAM (RWX) : origin = 0x20000000, length = 0x00008000
|
||||
}
|
||||
|
||||
/* The following command line options are set as part of the CCS project. */
|
||||
/* If you are building using the command line, or for some reason want to */
|
||||
/* define them here, you can uncomment and modify these lines as needed. */
|
||||
/* If you are using CCS for building, it is probably better to make any such */
|
||||
/* modifications in your CCS project and leave this file alone. */
|
||||
/* */
|
||||
/* --heap_size=0 */
|
||||
/* --stack_size=256 */
|
||||
/* --library=rtsv7M4_T_le_eabi.lib */
|
||||
|
||||
/* Section allocation in memory */
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.intvecs: > 0x00000000
|
||||
.text : > FLASH
|
||||
.const : > FLASH
|
||||
.cinit : > FLASH
|
||||
.pinit : > FLASH
|
||||
.init_array : > FLASH
|
||||
|
||||
.vtable : > 0x20000000
|
||||
.data : > SRAM
|
||||
.bss : > SRAM
|
||||
.sysmem : > SRAM
|
||||
.stack : > SRAM
|
||||
}
|
||||
|
||||
__STACK_TOP = __stack + 512;
|
@ -1,45 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Default Linker Command file for the Texas Instruments TM4C123GH6PM
|
||||
*
|
||||
* This is derived from revision 14351 of the TivaWare Library.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
--retain=g_pfnVectors
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (RX) : origin = 0x00000000, length = 0x00040000
|
||||
SRAM (RWX) : origin = 0x20000000, length = 0x00008000
|
||||
}
|
||||
|
||||
/* The following command line options are set as part of the CCS project. */
|
||||
/* If you are building using the command line, or for some reason want to */
|
||||
/* define them here, you can uncomment and modify these lines as needed. */
|
||||
/* If you are using CCS for building, it is probably better to make any such */
|
||||
/* modifications in your CCS project and leave this file alone. */
|
||||
/* */
|
||||
/* --heap_size=0 */
|
||||
/* --stack_size=256 */
|
||||
/* --library=rtsv7M4_T_le_eabi.lib */
|
||||
|
||||
/* Section allocation in memory */
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.intvecs: > 0x00000000
|
||||
.text : > FLASH
|
||||
.const : > FLASH
|
||||
.cinit : > FLASH
|
||||
.pinit : > FLASH
|
||||
.init_array : > FLASH
|
||||
|
||||
.vtable : > 0x20000000
|
||||
.data : > SRAM
|
||||
.bss : > SRAM
|
||||
.sysmem : > SRAM
|
||||
.stack : > SRAM
|
||||
}
|
||||
|
||||
__STACK_TOP = __stack + 512;
|
@ -1,45 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Default Linker Command file for the Texas Instruments TM4C123GH6PM
|
||||
*
|
||||
* This is derived from revision 14351 of the TivaWare Library.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
--retain=g_pfnVectors
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (RX) : origin = 0x00000000, length = 0x00040000
|
||||
SRAM (RWX) : origin = 0x20000000, length = 0x00008000
|
||||
}
|
||||
|
||||
/* The following command line options are set as part of the CCS project. */
|
||||
/* If you are building using the command line, or for some reason want to */
|
||||
/* define them here, you can uncomment and modify these lines as needed. */
|
||||
/* If you are using CCS for building, it is probably better to make any such */
|
||||
/* modifications in your CCS project and leave this file alone. */
|
||||
/* */
|
||||
/* --heap_size=0 */
|
||||
/* --stack_size=256 */
|
||||
/* --library=rtsv7M4_T_le_eabi.lib */
|
||||
|
||||
/* Section allocation in memory */
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.intvecs: > 0x00000000
|
||||
.text : > FLASH
|
||||
.const : > FLASH
|
||||
.cinit : > FLASH
|
||||
.pinit : > FLASH
|
||||
.init_array : > FLASH
|
||||
|
||||
.vtable : > 0x20000000
|
||||
.data : > SRAM
|
||||
.bss : > SRAM
|
||||
.sysmem : > SRAM
|
||||
.stack : > SRAM
|
||||
}
|
||||
|
||||
__STACK_TOP = __stack + 512;
|
@ -2,14 +2,14 @@
|
||||
/// @brief QK/C++ port to ARM Cortex-M, ARM-KEIL toolset
|
||||
/// @cond
|
||||
///***************************************************************************
|
||||
/// Last updated for version 5.5.2
|
||||
/// Last updated on 2015-11-11
|
||||
/// Last updated for version 5.6.4
|
||||
/// Last updated on 2016-04-25
|
||||
///
|
||||
/// Q u a n t u m L e a P s
|
||||
/// ---------------------------
|
||||
/// innovating embedded systems
|
||||
///
|
||||
/// Copyright (C) Quantum Leaps, www.state-machine.com.
|
||||
/// Copyright (C) Quantum Leaps, LLC. All rights reserved.
|
||||
///
|
||||
/// This program is open source software: you can redistribute it and/or
|
||||
/// modify it under the terms of the GNU General Public License as published
|
||||
@ -30,7 +30,7 @@
|
||||
/// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
///
|
||||
/// Contact information:
|
||||
/// http:// www.state-machine.com
|
||||
/// http://www.state-machine.com
|
||||
/// mailto:info@state-machine.com
|
||||
///***************************************************************************
|
||||
/// @endcond
|
||||
@ -49,19 +49,9 @@ static __inline uint32_t QK_get_IPSR(void) {
|
||||
|
||||
// QK interrupt entry and exit
|
||||
#define QK_ISR_ENTRY() ((void)0)
|
||||
|
||||
#define QK_ISR_EXIT() do { \
|
||||
QF_INT_DISABLE(); \
|
||||
uint_fast8_t nextPrio_ = QK_schedPrio_(); \
|
||||
if (nextPrio_ != static_cast<uint_fast8_t>(0)) { \
|
||||
QK_nextPrio_ = nextPrio_; \
|
||||
(*Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) \
|
||||
= static_cast<uint32_t>(1U << 28)); \
|
||||
} \
|
||||
QF_INT_ENABLE(); \
|
||||
} while (false)
|
||||
|
||||
extern uint_fast8_t QK_nextPrio_; // priority of the next task to execute
|
||||
#define QK_ISR_EXIT() \
|
||||
((*Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = \
|
||||
static_cast<uint32_t>(1U << 28)))
|
||||
|
||||
#include "qk.h" // QK platform-independent public interface
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
;*****************************************************************************
|
||||
; Product: QK port to ARM Cortex-M (M0,M0+,M1,M3,M4,M7), ARM-Keil assembler
|
||||
; Last Updated for Version: 5.6.0
|
||||
; Date of the Last Update: 2015-12-14
|
||||
; Last Updated for Version: 5.6.4
|
||||
; Date of the Last Update: 2016-04-21
|
||||
;
|
||||
; Q u a n t u m L e a P s
|
||||
; ---------------------------
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
EXPORT QK_init
|
||||
EXPORT PendSV_Handler ; CMSIS-compliant PendSV exception name
|
||||
EXPORT QK_nextPrio_ ; priority of the next task to execute
|
||||
EXPORT NMI_Handler ; CMSIS-compliant NMI exception name
|
||||
|
||||
IMPORT QK_schedPrio_ ; external reference
|
||||
IMPORT QK_sched_ ; external reference
|
||||
@ -42,14 +42,6 @@
|
||||
; NOTE: keep in synch with QF_BASEPRI value defined in "qf_port.h" !!!
|
||||
QF_BASEPRI EQU (0xFF:SHR:2)
|
||||
|
||||
AREA |.data|, DATA, READWRITE
|
||||
;*****************************************************************************
|
||||
; Global priority of the next task to execute or zero to indicate return
|
||||
; to the preempted task
|
||||
;*****************************************************************************
|
||||
QK_nextPrio_
|
||||
DCD 0
|
||||
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
THUMB
|
||||
@ -105,14 +97,15 @@ PendSV_Handler
|
||||
ENDIF ; M3/M4/M7
|
||||
ISB ; reset the instruction pipeline
|
||||
|
||||
LDR r0,=QK_nextPrio_
|
||||
LDR r0,[r0]
|
||||
CMP r0,#0
|
||||
BNE.N PendSV_sched ; if QK_nextPrio_ != 0, branch to scheduler
|
||||
IF {TARGET_FPU_VFP} == {TRUE} ; if VFP available...
|
||||
PUSH {r0,lr} ; push lr (EXC_RETURN) plus stack "aligner"
|
||||
ENDIF ; VFP available
|
||||
|
||||
; QK_nextPrio_ == 0: return to the preempted task...
|
||||
ADD sp,sp,#(8*4) ; remove one 8-register exception frame
|
||||
BL QK_schedPrio_ ; call QK_schedPrio_()
|
||||
CMP r0,#0 ; is the returned next prio 0?
|
||||
BNE.N PendSV_sched ; if next prio != 0, branch to scheduler
|
||||
|
||||
PendSV_ret
|
||||
IF {TARGET_ARCH_THUMB} == 3 ; Cortex-M0/M0+/M1 (v6-M, v6S-M)?
|
||||
CPSIE i ; enable interrupts (clear PRIMASK)
|
||||
MOVS r0,#6
|
||||
@ -130,18 +123,20 @@ PendSV_Handler
|
||||
ENDIF ; no VFP
|
||||
ENDIF ; M3/M4/M7
|
||||
|
||||
PendSV_sched
|
||||
IF {TARGET_FPU_VFP} == {TRUE} ; if VFP available...
|
||||
PUSH {r0,lr} ; push lr (EXC_RETURN) plus stack "aligner"
|
||||
ENDIF ; VFP available
|
||||
|
||||
PendSV_sched ; call the QK scheduler...
|
||||
; NOTE: The QK scheduler must be called in a task context, while
|
||||
; we are still in the PendSV exception context. The switch to the
|
||||
; task context is accomplished by returning from PendSV using a
|
||||
; fabricated exception stack frame, where the return address is
|
||||
; the QK scheduler.
|
||||
; NOTE: the QK scheduler is called with interrupts DISABLED.
|
||||
MOVS r3,#1
|
||||
LSLS r3,r3,#24 ; r3:=(1 << 24), set the T bit (new xpsr)
|
||||
LDR r2,=QK_sched_ ; address of the QK scheduler (new pc)
|
||||
LDR r1,=PendSV_sched_ret ; return address after the call (new lr)
|
||||
|
||||
SUB sp,sp,#8*4 ; reserve space for exception stack frame
|
||||
STR r0,[sp] ; save the prio argument (new r0)
|
||||
STR r0,[sp] ; save the prio argument (new r0)
|
||||
ADD r0,sp,#5*4 ; r0 := 5 registers below the top of stack
|
||||
STM r0!,{r1-r3} ; save xpsr,pc,lr
|
||||
|
||||
@ -150,28 +145,53 @@ PendSV_sched
|
||||
BX r0 ; exception-return to the QK scheduler
|
||||
|
||||
PendSV_sched_ret
|
||||
LDR r0,=QK_nextPrio_
|
||||
MOVS r1,#0
|
||||
STR r1,[r0] ; QK_nextPrio_ = 0;
|
||||
; NOTE: After the QK scheduler returns, we need to resume the preempted
|
||||
; task. However, this must be accomplished by a return-from-exception,
|
||||
; while we are still in the task context. The switch to the exception
|
||||
; contex is accomplished by triggering the NMI exception.
|
||||
; NOTE: The NMI exception is triggered with nterrupts DISABLED,
|
||||
; because QK scheduler disables interrutps before return.
|
||||
|
||||
IF {TARGET_ARCH_THUMB} == 3 ; Cortex-M0/M0+/M1 (v6-M, v6S-M)?
|
||||
CPSIE i ; enable interrupts (clear PRIMASK)
|
||||
ELSE ; M3/M4/M7
|
||||
; before triggering the NMI exception, make sure that the
|
||||
; VFP stack frame will NOT be used...
|
||||
IF {TARGET_FPU_VFP} == {TRUE} ; if VFP available...
|
||||
MRS r0,CONTROL ; r0 := CONTROL
|
||||
BICS r0,r0,#4 ; r0 := r0 & ~4 (FPCA bit)
|
||||
MSR CONTROL,r0 ; CONTROL := r0 (clear CONTROL[2] FPCA bit)
|
||||
ENDIF ; VFP available
|
||||
MOVS r0,#0
|
||||
MSR BASEPRI,r0 ; enable interrupts (clear BASEPRI)
|
||||
ENDIF ; M3/M4/M7
|
||||
|
||||
; trigger PendSV to return to preempted task...
|
||||
; trigger NMI to return to preempted task...
|
||||
LDR r0,=0xE000ED04 ; Interrupt Control and State Register
|
||||
MOVS r1,#1
|
||||
LSLS r1,r1,#28 ; r0 := (1 << 28) (PENDSVSET bit)
|
||||
STR r1,[r0] ; ICSR[28] := 1 (pend PendSV)
|
||||
B . ; wait for preemption by PendSV
|
||||
LSLS r1,r1,#31 ; r0 := (1 << 31) (NMI bit)
|
||||
STR r1,[r0] ; ICSR[31] := 1 (pend NMI)
|
||||
B . ; wait for preemption by NMI
|
||||
|
||||
|
||||
;*****************************************************************************
|
||||
; The NMI_Handler exception handler is used for returning back to the
|
||||
; interrupted task. The NMI exception simply removes its own interrupt
|
||||
; stack frame from the stack and returns to the preempted task using the
|
||||
; interrupt stack frame that must be at the top of the stack.
|
||||
;
|
||||
; NOTE: The NMI exception is entered with interrupts DISABLED, so it needs
|
||||
; to re-enable interrupts before it returns to the preempted task.
|
||||
;*****************************************************************************
|
||||
NMI_Handler
|
||||
ADD sp,sp,#(8*4) ; remove one 8-register exception frame
|
||||
|
||||
IF {TARGET_ARCH_THUMB} == 3 ; Cortex-M0/M0+/M1 (v6-M, v6S-M)?
|
||||
CPSIE i ; enable interrupts (clear PRIMASK)
|
||||
BX lr ; return to the preempted task
|
||||
ELSE ; M3/M4/M7
|
||||
MOVS r0,#0
|
||||
MSR BASEPRI,r0 ; enable interrupts (clear BASEPRI)
|
||||
IF {TARGET_FPU_VFP} == {TRUE} ; if VFP available...
|
||||
POP {r0,pc} ; pop stack "aligner" and EXC_RETURN to PC
|
||||
ELSE ; no VFP
|
||||
BX lr ; return to the preempted task
|
||||
ENDIF ; no VFP
|
||||
ENDIF ; M3/M4/M7
|
||||
|
||||
ALIGN ; make sure the END is properly aligned
|
||||
|
||||
|
@ -2,14 +2,14 @@
|
||||
/// @brief QK/C++ port to ARM Cortex-M, preemptive QK kernel, GNU-ARM toolset
|
||||
/// @cond
|
||||
///***************************************************************************
|
||||
/// Last updated for version 5.5.2
|
||||
/// Last updated on 2015-11-11
|
||||
/// Last updated for version 5.6.4
|
||||
/// Last updated on 2016-04-25
|
||||
///
|
||||
/// Q u a n t u m L e a P s
|
||||
/// ---------------------------
|
||||
/// innovating embedded systems
|
||||
///
|
||||
/// Copyright (C) Quantum Leaps, www.state-machine.com.
|
||||
/// Copyright (C) Quantum Leaps, LLC. All rights reserved.
|
||||
///
|
||||
/// This program is open source software: you can redistribute it and/or
|
||||
/// modify it under the terms of the GNU General Public License as published
|
||||
@ -50,19 +50,9 @@ static inline uint32_t QK_get_IPSR(void) {
|
||||
|
||||
// QK interrupt entry and exit
|
||||
#define QK_ISR_ENTRY() ((void)0)
|
||||
|
||||
#define QK_ISR_EXIT() do { \
|
||||
QF_INT_DISABLE(); \
|
||||
uint_fast8_t nextPrio_ = QK_schedPrio_(); \
|
||||
if (nextPrio_ != static_cast<uint_fast8_t>(0)) { \
|
||||
QK_nextPrio_ = nextPrio_; \
|
||||
(*Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) \
|
||||
= static_cast<uint32_t>(1U << 28)); \
|
||||
} \
|
||||
QF_INT_ENABLE(); \
|
||||
} while (false)
|
||||
|
||||
extern uint_fast8_t QK_nextPrio_; // priority of the next task to execute
|
||||
#define QK_ISR_EXIT() \
|
||||
((*Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = \
|
||||
static_cast<uint32_t>(1U << 28)))
|
||||
|
||||
#include "qk.h" // QK platform-independent public interface
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
* Product: QK port to ARM Cortex-M (M0,M0+,M1,M3,M4,M7), GNU-ARM assembler
|
||||
* Last Updated for Version: 5.6.0
|
||||
* Date of the Last Update: 2015-12-14
|
||||
* Last Updated for Version: 5.6.4
|
||||
* Date of the Last Update: 2016-04-22
|
||||
*
|
||||
* Q u a n t u m L e a P s
|
||||
* ---------------------------
|
||||
@ -33,21 +33,12 @@
|
||||
*****************************************************************************/
|
||||
|
||||
.syntax unified
|
||||
.thumb
|
||||
|
||||
/* NOTE: keep in synch with QF_BASEPRI value defined in "qf_port.h" !!! */
|
||||
.equ QF_BASEPRI,(0xFF >> 2)
|
||||
|
||||
|
||||
.section .data
|
||||
/*****************************************************************************
|
||||
* Global priority of the next task to execute or zero to indicate return
|
||||
* to the preempted task
|
||||
*****************************************************************************/
|
||||
QK_nextPrio_:
|
||||
.global QK_nextPrio_
|
||||
.word 0
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* The QK_init function sets the priorities of PendSV to 0xFF (lowest).
|
||||
* The priority is set within a critical section.
|
||||
@ -55,7 +46,6 @@ QK_nextPrio_:
|
||||
.section .text.QK_init
|
||||
.global QK_init
|
||||
.type QK_init, %function
|
||||
.thumb
|
||||
|
||||
QK_init:
|
||||
MRS r0,PRIMASK /* store the state of the PRIMASK in r0 */
|
||||
@ -103,20 +93,20 @@ PendSV_Handler:
|
||||
.if __ARM_ARCH == 6 /* Cortex-M0/M0+/M1 (v6-M, v6S-M)? */
|
||||
CPSID i /* disable interrupts at processor level */
|
||||
.else /* M3/M4/M7 */
|
||||
|
||||
MOVS r0,#QF_BASEPRI
|
||||
MSR BASEPRI,r0 /* selectively disable interrupts */
|
||||
.endif /* M3/M4/M7 */
|
||||
ISB /* reset the instruction pipeline */
|
||||
|
||||
LDR r0,=QK_nextPrio_
|
||||
LDR r0,[r0]
|
||||
CMP r0,#0
|
||||
BNE.N PendSV_sched /* if QK_nextPrio_ != 0, branch to scheduler */
|
||||
.ifdef __FPU_PRESENT /* if VFP available... */
|
||||
PUSH {r0,lr} /* push lr (EXC_RETURN) plus stack "aligner" */
|
||||
.endif /* VFP available */
|
||||
|
||||
/* QK_nextPrio_ == 0: return to the preempted task... */
|
||||
ADD sp,sp,#(8*4) /* remove one 8-register exception frame */
|
||||
BL QK_schedPrio_ /* call QK_schedPrio_() */
|
||||
CMP r0,#0 /* is the returned next prio 0? */
|
||||
BNE.N PendSV_sched /* if next prio != 0, branch to scheduler */
|
||||
|
||||
PendSV_ret:
|
||||
.if __ARM_ARCH == 6 /* Cortex-M0/M0+/M1 (v6-M, v6S-M)? */
|
||||
CPSIE i /* enable interrupts (clear PRIMASK) */
|
||||
MOVS r0,#6
|
||||
@ -134,10 +124,14 @@ PendSV_Handler:
|
||||
.endif /* VFP available */
|
||||
.endif /* M3/M4/M7 */
|
||||
|
||||
PendSV_sched:
|
||||
.ifdef __FPU_PRESENT /* if VFP available... */
|
||||
PUSH {r0,lr} /* push lr (EXC_RETURN) plus stack "aligner" */
|
||||
.endif /* VFP available */
|
||||
PendSV_sched: /* call the QK scheduler... */
|
||||
/* NOTE: The QK scheduler must be called in a task context, while
|
||||
* we are still in the PendSV exception context. The switch to the
|
||||
* task context is accomplished by returning from PendSV using a
|
||||
* fabricated exception stack frame, where the return address is
|
||||
* the QK scheduler.
|
||||
* NOTE: the QK scheduler is called with interrupts DISABLED.
|
||||
*/
|
||||
MOVS r3,#1
|
||||
LSLS r3,r3,#24 /* r3:=(1 << 24), set the T bit (new xpsr) */
|
||||
LDR r2,=QK_sched_ /* address of the QK scheduler (new pc) */
|
||||
@ -153,28 +147,59 @@ PendSV_sched:
|
||||
BX r0 /* exception-return to the QK scheduler */
|
||||
|
||||
PendSV_sched_ret:
|
||||
LDR r0,=QK_nextPrio_
|
||||
MOVS r1,#0
|
||||
STR r1,[r0] /* QK_nextPrio_ = 0; */
|
||||
|
||||
.if __ARM_ARCH == 6 /* Cortex-M0/M0+/M1 (v6-M, v6S-M)? */
|
||||
CPSIE i /* enable interrupts (clear PRIMASK) */
|
||||
.else /* M3/M4/M7 */
|
||||
/* NOTE: After the QK scheduler returns, we need to resume the preempted
|
||||
* task. However, this must be accomplished by a return-from-exception,
|
||||
* while we are still in the task context. The switch to the exception
|
||||
* contex is accomplished by triggering the NMI exception.
|
||||
* NOTE: The NMI exception is triggered with nterrupts DISABLED,
|
||||
* because QK scheduler disables interrutps before return.
|
||||
*/
|
||||
/* before triggering the NMI exception, make sure that the
|
||||
* VFP stack frame will NOT be used...
|
||||
*/
|
||||
.ifdef __FPU_PRESENT /* if VFP available... */
|
||||
MRS r0,CONTROL /* r0 := CONTROL */
|
||||
BICS r0,r0,#4 /* r0 := r0 & ~4 (FPCA bit) */
|
||||
MSR CONTROL,r0 /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */
|
||||
.endif /* VFP available */
|
||||
MOVS r0,#0
|
||||
MSR BASEPRI,r0 /* enable interrupts (clear BASEPRI) */
|
||||
.endif /* M3/M4/M7 */
|
||||
|
||||
/* trigger PendSV to return to preempted task... */
|
||||
/* trigger NMI to return to preempted task... */
|
||||
LDR r0,=0xE000ED04 /* Interrupt Control and State Register */
|
||||
MOVS r1,#1
|
||||
LSLS r1,r1,#28 /* r0 := (1 << 28) (PENDSVSET bit) */
|
||||
STR r1,[r0] /* ICSR[28] := 1 (pend PendSV) */
|
||||
B . /* wait for preemption by PendSV */
|
||||
LSLS r1,r1,#31 /* r0 := (1 << 31) (NMI bit) */
|
||||
STR r1,[r0] /* ICSR[31] := 1 (pend NMI) */
|
||||
B . /* wait for preemption by NMI */
|
||||
.size PendSV_Handler, . - PendSV_Handler
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* The NMI_Handler exception handler is used for returning back to the
|
||||
* interrupted task. The NMI exception simply removes its own interrupt
|
||||
* stack frame from the stack and returns to the preempted task using the
|
||||
* interrupt stack frame that must be at the top of the stack.
|
||||
*
|
||||
* NOTE: The NMI exception is entered with interrupts DISABLED, so it needs
|
||||
* to re-enable interrupts before it returns to the preempted task.
|
||||
*****************************************************************************/
|
||||
.section .text.NMI_Handler
|
||||
.global NMI_Handler /* CMSIS-compliant exception name */
|
||||
.type NMI_Handler, %function
|
||||
|
||||
NMI_Handler:
|
||||
ADD sp,sp,#(8*4) /* remove one 8-register exception frame */
|
||||
|
||||
.if __ARM_ARCH == 6 /* Cortex-M0/M0+/M1 (v6-M, v6S-M)? */
|
||||
CPSIE i /* enable interrupts (clear PRIMASK) */
|
||||
BX lr /* return to the preempted task */
|
||||
.else /* M3/M4/M7 */
|
||||
MOVS r0,#0
|
||||
MSR BASEPRI,r0 /* enable interrupts (clear BASEPRI) */
|
||||
.ifdef __FPU_PRESENT /* if VFP available... */
|
||||
POP {r0,pc} /* pop stack "aligner" and EXC_RETURN to PC */
|
||||
.else /* no VFP */
|
||||
BX lr /* return to the preempted task */
|
||||
.endif /* VFP available */
|
||||
.endif /* M3/M4/M7 */
|
||||
.size NMI_Handler, . - NMI_Handler
|
||||
|
||||
.end
|
||||
|
@ -2,8 +2,8 @@
|
||||
/// @brief QK/C++ port to ARM Cortex-M, preemptive QK kernel, IAR-ARM toolset
|
||||
/// @cond
|
||||
///***************************************************************************
|
||||
/// Last updated for version 5.6.0
|
||||
/// Last updated on 2015-12-28
|
||||
/// Last updated for version 5.6.4
|
||||
/// Last updated on 2016-04-25
|
||||
///
|
||||
/// Q u a n t u m L e a P s
|
||||
/// ---------------------------
|
||||
@ -43,19 +43,9 @@
|
||||
|
||||
/* QK interrupt entry and exit */
|
||||
#define QK_ISR_ENTRY() ((void)0)
|
||||
|
||||
#define QK_ISR_EXIT() do { \
|
||||
QF_INT_DISABLE(); \
|
||||
uint_fast8_t nextPrio_ = QK_schedPrio_(); \
|
||||
if (nextPrio_ != static_cast<uint_fast8_t>(0)) { \
|
||||
QK_nextPrio_ = nextPrio_; \
|
||||
(*Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) \
|
||||
= static_cast<uint32_t>(1U << 28)); \
|
||||
} \
|
||||
QF_INT_ENABLE(); \
|
||||
} while (false)
|
||||
|
||||
extern uint_fast8_t QK_nextPrio_; // priority of the next task to execute
|
||||
#define QK_ISR_EXIT() \
|
||||
((*Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = \
|
||||
static_cast<uint32_t>(1U << 28)))
|
||||
|
||||
#include "qk.h" // QK platform-independent public interface
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
;*****************************************************************************
|
||||
; Product: QK port to ARM Cortex-M (M0,M0+,M1,M3,M4,M7), IAR ARM assembler
|
||||
; Last Updated for Version: 5.6.0
|
||||
; Date of the Last Update: 2015-12-11
|
||||
; Last Updated for Version: 5.6.4
|
||||
; Date of the Last Update: 2016-04-21
|
||||
;
|
||||
; Q u a n t u m L e a P s
|
||||
; ---------------------------
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
PUBLIC QK_init
|
||||
PUBLIC PendSV_Handler ; CMSIS-compliant PendSV exception name
|
||||
PUBLIC QK_nextPrio_ ; priority of the next task to execute
|
||||
PUBLIC NMI_Handler ; CMSIS-compliant NMI exception name
|
||||
|
||||
EXTERN QK_schedPrio_ ; external reference
|
||||
EXTERN QK_sched_ ; external reference
|
||||
@ -42,21 +42,13 @@
|
||||
; NOTE: keep in synch with QF_BASEPRI value defined in "qf_port.h" !!!
|
||||
QF_BASEPRI EQU (0xFF >> 2)
|
||||
|
||||
RSEG .data:DATA:NOROOT(2)
|
||||
;*****************************************************************************
|
||||
; Global priority of the next task to execute or zero to indicate return
|
||||
; to the preempted task
|
||||
;*****************************************************************************
|
||||
QK_nextPrio_:
|
||||
DC32 0
|
||||
|
||||
|
||||
RSEG CODE:CODE:NOROOT(2)
|
||||
;*****************************************************************************
|
||||
; The QK_init function sets the priorities of PendSV to 0xFF (lowest).
|
||||
; The priority is set within a critical section.
|
||||
;*****************************************************************************
|
||||
QK_init
|
||||
QK_init:
|
||||
MRS r0,PRIMASK ; store the state of the PRIMASK in r0
|
||||
CPSID i ; disable interrupts (set PRIMASK)
|
||||
|
||||
@ -92,7 +84,6 @@ QK_init
|
||||
; check for the asynchronous preemption.
|
||||
;*****************************************************************************
|
||||
PendSV_Handler:
|
||||
|
||||
#if (__CORE__ == __ARM6M__) ; Cortex-M0/M0+/M1 ?
|
||||
CPSID i ; disable interrupts (set PRIMASK)
|
||||
#else ; M3/M4/M7
|
||||
@ -101,14 +92,15 @@ PendSV_Handler:
|
||||
#endif ; M3/M4/M7
|
||||
ISB ; reset the instruction pipeline
|
||||
|
||||
LDR r0,=QK_nextPrio_
|
||||
LDR r0,[r0]
|
||||
CMP r0,#0
|
||||
BNE.N PendSV_sched ; if QK_nextPrio_ != 0, branch to scheduler
|
||||
#ifdef __ARMVFP__ ; if VFP available...
|
||||
PUSH {r0,lr} ; push lr (EXC_RETURN) plus stack "aligner"
|
||||
#endif ; VFP available
|
||||
|
||||
; QK_nextPrio_ == 0: return to the preempted task...
|
||||
ADD sp,sp,#(8*4) ; remove one 8-register exception frame
|
||||
BL QK_schedPrio_ ; call QK_schedPrio_()
|
||||
CMP r0,#0 ; is the returned next prio 0?
|
||||
BNE.N PendSV_sched ; if next prio != 0, branch to scheduler
|
||||
|
||||
PendSV_ret:
|
||||
#if (__CORE__ == __ARM6M__) ; Cortex-M0/M0+/M1 ?
|
||||
CPSIE i ; enable interrupts (clear PRIMASK)
|
||||
MOVS r0,#6
|
||||
@ -126,18 +118,20 @@ PendSV_Handler:
|
||||
#endif ; no VFP
|
||||
#endif ; M3/M4/M7
|
||||
|
||||
PendSV_sched:
|
||||
#ifdef __ARMVFP__ ; if VFP available...
|
||||
PUSH {r0,lr} ; push lr (EXC_RETURN) plus stack "aligner"
|
||||
#endif ; VFP available
|
||||
|
||||
PendSV_sched: ; call the QK scheduler...
|
||||
; NOTE: The QK scheduler must be called in a task context, while
|
||||
; we are still in the PendSV exception context. The switch to the
|
||||
; task context is accomplished by returning from PendSV using a
|
||||
; fabricated exception stack frame, where the return address is
|
||||
; the QK scheduler.
|
||||
; NOTE: the QK scheduler is called with interrupts DISABLED.
|
||||
MOVS r3,#1
|
||||
LSLS r3,r3,#24 ; r3:=(1 << 24), set the T bit (new xpsr)
|
||||
LDR r2,=QK_sched_ ; address of the QK scheduler (new pc)
|
||||
LDR r1,=PendSV_sched_ret ; return address after the call (new lr)
|
||||
|
||||
SUB sp,sp,#8*4 ; reserve space for exception stack frame
|
||||
STR r0,[sp] ; save the prio argument (new r0)
|
||||
STR r0,[sp] ; save the prio argument (new r0)
|
||||
ADD r0,sp,#5*4 ; r0 := 5 registers below the top of stack
|
||||
STM r0!,{r1-r3} ; save xpsr,pc,lr
|
||||
|
||||
@ -146,28 +140,53 @@ PendSV_sched:
|
||||
BX r0 ; exception-return to the QK scheduler
|
||||
|
||||
PendSV_sched_ret:
|
||||
LDR r0,=QK_nextPrio_
|
||||
MOVS r1,#0
|
||||
STR r1,[r0] ; QK_nextPrio_ = 0;
|
||||
; NOTE: After the QK scheduler returns, we need to resume the preempted
|
||||
; task. However, this must be accomplished by a return-from-exception,
|
||||
; while we are still in the task context. The switch to the exception
|
||||
; contex is accomplished by triggering the NMI exception.
|
||||
; NOTE: The NMI exception is triggered with nterrupts DISABLED,
|
||||
; because QK scheduler disables interrutps before return.
|
||||
|
||||
#if (__CORE__ == __ARM6M__) ; Cortex-M0/M0+/M1 ?
|
||||
CPSIE i ; enable interrupts (clear PRIMASK)
|
||||
#else ; M3/M4/M7
|
||||
; before triggering the NMI exception, make sure that the
|
||||
; VFP stack frame will NOT be used...
|
||||
#ifdef __ARMVFP__ ; if VFP available...
|
||||
MRS r0,CONTROL ; r0 := CONTROL
|
||||
BICS r0,r0,#4 ; r0 := r0 & ~4 (FPCA bit)
|
||||
MSR CONTROL,r0 ; CONTROL := r0 (clear CONTROL[2] FPCA bit)
|
||||
#endif ; VFP available
|
||||
MOVS r0,#0
|
||||
MSR BASEPRI,r0 ; enable interrupts (clear BASEPRI)
|
||||
#endif ; M3/M4/M7
|
||||
|
||||
; trigger PendSV to return to preempted task...
|
||||
; trigger NMI to return to preempted task...
|
||||
LDR r0,=0xE000ED04 ; Interrupt Control and State Register
|
||||
MOVS r1,#1
|
||||
LSLS r1,r1,#28 ; r0 := (1 << 28) (PENDSVSET bit)
|
||||
STR r1,[r0] ; ICSR[28] := 1 (pend PendSV)
|
||||
B . ; wait for preemption by PendSV
|
||||
LSLS r1,r1,#31 ; r0 := (1 << 31) (NMI bit)
|
||||
STR r1,[r0] ; ICSR[31] := 1 (pend NMI)
|
||||
B . ; wait for preemption by NMI
|
||||
|
||||
|
||||
;*****************************************************************************
|
||||
; The NMI_Handler exception handler is used for returning back to the
|
||||
; interrupted task. The NMI exception simply removes its own interrupt
|
||||
; stack frame from the stack and returns to the preempted task using the
|
||||
; interrupt stack frame that must be at the top of the stack.
|
||||
;
|
||||
; NOTE: The NMI exception is entered with interrupts DISABLED, so it needs
|
||||
; to re-enable interrupts before it returns to the preempted task.
|
||||
;*****************************************************************************
|
||||
NMI_Handler:
|
||||
ADD sp,sp,#(8*4) ; remove one 8-register exception frame
|
||||
|
||||
#if (__CORE__ == __ARM6M__) ; Cortex-M0/M0+/M1 ?
|
||||
CPSIE i ; enable interrupts (clear PRIMASK)
|
||||
BX lr ; return to the preempted task
|
||||
#else ; M3/M4/M7
|
||||
MOVS r0,#0
|
||||
MSR BASEPRI,r0 ; enable interrupts (clear BASEPRI)
|
||||
#ifdef __ARMVFP__ ; if VFP available...
|
||||
POP {r0,pc} ; pop stack "aligner" and EXC_RETURN to PC
|
||||
#else ; no VFP
|
||||
BX lr ; return to the preempted task
|
||||
#endif ; no VFP
|
||||
#endif ; M3/M4/M7
|
||||
|
||||
ALIGNROM 2,0xFF ; make sure the END is properly aligned
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
/// @brief QK/C++ port to ARM Cortex-M, preemptive QK kernel, TI-ARM toolset
|
||||
/// @cond
|
||||
///***************************************************************************
|
||||
/// Last updated for version 5.6.0
|
||||
/// Last updated on 2015-12-30
|
||||
/// Last updated for version 5.6.4
|
||||
/// Last updated on 2016-04-25
|
||||
///
|
||||
/// Q u a n t u m L e a P s
|
||||
/// ---------------------------
|
||||
@ -38,11 +38,19 @@
|
||||
#ifndef qk_port_h
|
||||
#define qk_port_h
|
||||
|
||||
// QK interrupt entry and exit (defined in assembly)
|
||||
// determination if the code executes in the ISR context
|
||||
#define QK_ISR_CONTEXT_() (QK_get_IPSR() != static_cast<uint32_t>(0))
|
||||
|
||||
// QK interrupt entry and exit
|
||||
#define QK_ISR_ENTRY() ((void)0)
|
||||
#define QK_ISR_EXIT() \
|
||||
((*Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = \
|
||||
static_cast<uint32_t>(1U << 28)))
|
||||
|
||||
extern "C" {
|
||||
void QK_ISR_ENTRY(void);
|
||||
void QK_ISR_EXIT(void);
|
||||
} // extern "C"
|
||||
// get the IPSR defined in assembly
|
||||
uint32_t QK_get_IPSR(void);
|
||||
}
|
||||
|
||||
#include "qk.h" // QK platform-independent public interface
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
;*****************************************************************************
|
||||
; Product: QK port to ARM Cortex-M (M0,M0+,M1,M3,M4,M7), TI-ARM assembler
|
||||
; Last Updated for Version: 5.6.1
|
||||
; Date of the Last Update: 2015-12-30
|
||||
; Last Updated for Version: 5.6.4
|
||||
; Date of the Last Update: 2016-04-21
|
||||
;
|
||||
; Q u a n t u m L e a P s
|
||||
; ---------------------------
|
||||
@ -34,10 +34,10 @@
|
||||
|
||||
.global QK_init
|
||||
.global PendSV_Handler ; CMSIS-compliant PendSV exception name
|
||||
.global NMI_Handler ; CMSIS-compliant NMI exception name
|
||||
|
||||
.global QF_set_BASEPRI ; set BASEPRI register
|
||||
.global QK_ISR_ENTRY ; inform QK about interrupt entry
|
||||
.global QK_ISR_EXIT ; inform QK about interrupt exit
|
||||
.global QK_get_IPSR ; get the IPSR
|
||||
.global assert_failed ; low-level assert handler
|
||||
|
||||
.ref QK_schedPrio_ ; external reference
|
||||
@ -48,16 +48,9 @@
|
||||
; NOTE: keep in synch with QF_BASEPRI value defined in "qf_port.h" !!!
|
||||
QF_BASEPRI: .equ (0xFF >> 2)
|
||||
|
||||
.data
|
||||
;*****************************************************************************
|
||||
; Priority of the next task to execute or zero to indicate return
|
||||
; to the preempted task
|
||||
;*****************************************************************************
|
||||
QK_nextPrio_: .word 0
|
||||
|
||||
|
||||
.text
|
||||
.thumb
|
||||
|
||||
;*****************************************************************************
|
||||
; The QK_init function sets the priorities of PendSV to 0xFF (lowest).
|
||||
; The priority is set within a critical section.
|
||||
@ -107,14 +100,15 @@ PendSV_Handler: .asmfunc
|
||||
.endif ; M0/M0+/M1
|
||||
ISB ; reset the instruction pipeline
|
||||
|
||||
LDR r0,QK_nextPrio_addr
|
||||
LDR r0,[r0]
|
||||
CMP r0,#0
|
||||
BNE.N PendSV_sched ; if QK_nextPrio_ != 0, branch to scheduler
|
||||
.if __TI_VFP_SUPPORT__ ; if VFP available...
|
||||
PUSH {r0,lr} ; push lr (EXC_RETURN) plus stack "aligner"
|
||||
.endif ; VFP available
|
||||
|
||||
; QK_nextPrio_ == 0: return to the preempted task...
|
||||
ADD sp,sp,#(8*4) ; remove one 8-register exception frame
|
||||
BL QK_schedPrio_ ; call QK_schedPrio_()
|
||||
CMP r0,#0 ; is the returned next prio 0?
|
||||
BNE.N PendSV_sched ; if next prio != 0, branch to scheduler
|
||||
|
||||
PendSV_ret:
|
||||
.if __TI_TMS470_V7M3__ | __TI_TMS470_V7M4__ ; | __TI_TMS470_V7M7__
|
||||
; NOTE: r0 == 0 at this point
|
||||
MSR BASEPRI,r0 ; enable interrupts (clear BASEPRI)
|
||||
@ -132,18 +126,20 @@ PendSV_Handler: .asmfunc
|
||||
BX r0 ; exception-return to the task
|
||||
.endif ; M0/M0+/M1
|
||||
|
||||
PendSV_sched:
|
||||
.if __TI_VFP_SUPPORT__ ; if VFP available...
|
||||
PUSH {r0,lr} ; push lr (EXC_RETURN) plus stack "aligner"
|
||||
.endif ; VFP available
|
||||
|
||||
PendSV_sched: ; call the QK scheduler...
|
||||
; NOTE: The QK scheduler must be called in a task context, while
|
||||
; we are still in the PendSV exception context. The switch to the
|
||||
; task context is accomplished by returning from PendSV using a
|
||||
; fabricated exception stack frame, where the return address is
|
||||
; the QK scheduler.
|
||||
; NOTE: the QK scheduler is called with interrupts DISABLED.
|
||||
MOVS r3,#1
|
||||
LSLS r3,r3,#24 ; r3:=(1 << 24), set the T bit (new xpsr)
|
||||
LDR r2,QK_sched_addr ; address of the QK scheduler (new pc)
|
||||
LDR r1,PendSV_sched_ret_addr ; ret address after the call (new lr)
|
||||
|
||||
SUB sp,sp,#8*4 ; reserve space for exception stack frame
|
||||
STR r0,[sp] ; save the prio argument (new r0)
|
||||
STR r0,[sp] ; save the prio argument (new r0)
|
||||
ADD r0,sp,#5*4 ; r0 := 5 registers below the top of stack
|
||||
STM r0!,{r1-r3} ; save xpsr,pc,lr
|
||||
|
||||
@ -153,32 +149,59 @@ PendSV_sched:
|
||||
.endasmfunc
|
||||
|
||||
PendSV_sched_ret: .asmfunc ; to ensure that the label is THUMB
|
||||
LDR r0,QK_nextPrio_addr
|
||||
MOVS r1,#0
|
||||
STR r1,[r0] ; QK_nextPrio_ = 0;
|
||||
; NOTE: After the QK scheduler returns, we need to resume the preempted
|
||||
; task. However, this must be accomplished by a return-from-exception,
|
||||
; while we are still in the task context. The switch to the exception
|
||||
; contex is accomplished by triggering the NMI exception.
|
||||
; NOTE: The NMI exception is triggered with nterrupts DISABLED,
|
||||
; because QK scheduler disables interrutps before return.
|
||||
|
||||
.if __TI_TMS470_V7M3__ | __TI_TMS470_V7M4__ ; | __TI_TMS470_V7M7__
|
||||
; before triggering the NMI exception, make sure that the
|
||||
; VFP stack frame will NOT be used...
|
||||
.if __TI_VFP_SUPPORT__ ; if VFP available...
|
||||
MRS r0,CONTROL ; r0 := CONTROL
|
||||
BICS r0,r0,#4 ; r0 := r0 & ~4 (FPCA bit)
|
||||
MSR CONTROL,r0 ; CONTROL := r0 (clear CONTROL[2] FPCA bit)
|
||||
.endif ; VFP available
|
||||
MOVS r0,#0
|
||||
MSR BASEPRI,r0 ; enable interrupts (clear BASEPRI)
|
||||
.else ; M0/M0+/M1
|
||||
CPSIE i ; enable interrupts (clear BASEPRI)
|
||||
.endif ; M0/M0+/M1
|
||||
|
||||
; trigger PendSV to return to preempted task...
|
||||
; trigger NMI to return to preempted task...
|
||||
LDR r0,ICSR_addr ; Interrupt Control and State Register
|
||||
MOVS r1,#1
|
||||
LSLS r1,r1,#28 ; r0 := (1 << 28) (PENDSVSET bit)
|
||||
STR r1,[r0] ; ICSR[28] := 1 (pend PendSV)
|
||||
LSLS r1,r1,#31 ; r0 := (1 << 31) (NMI bit)
|
||||
STR r1,[r0] ; ICSR[31] := 1 (pend NMI)
|
||||
PendSV_sched_wait:
|
||||
B PendSV_sched_wait ; wait for preemption by PendSV
|
||||
B PendSV_sched_wait ; wait for preemption by NMI
|
||||
.endasmfunc
|
||||
|
||||
|
||||
;*****************************************************************************
|
||||
; The NMI_Handler exception handler is used for returning back to the
|
||||
; interrupted task. The NMI exception simply removes its own interrupt
|
||||
; stack frame from the stack and returns to the preempted task using the
|
||||
; interrupt stack frame that must be at the top of the stack.
|
||||
;
|
||||
; NOTE: The NMI exception is entered with interrupts DISABLED, so it needs
|
||||
; to re-enable interrupts before it returns to the preempted task.
|
||||
;*****************************************************************************
|
||||
NMI_Handler: .asmfunc
|
||||
ADD sp,sp,#(8*4) ; remove one 8-register exception frame
|
||||
|
||||
.if __TI_TMS470_V7M3__ | __TI_TMS470_V7M4__ ; | __TI_TMS470_V7M7__
|
||||
|
||||
MOVS r0,#0
|
||||
MSR BASEPRI,r0 ; enable interrupts (clear BASEPRI)
|
||||
.if __TI_VFP_SUPPORT__ ; if VFP available...
|
||||
POP {r0,pc} ; pop stack "aligner" and EXC_RETURN to PC
|
||||
.else ; no VFP
|
||||
BX lr ; return to the preempted task
|
||||
.endif ; VFP available
|
||||
.else ; M0/M0+/M1
|
||||
CPSIE i ; enable interrupts (clear PRIMASK)
|
||||
BX lr ; return to the preempted task
|
||||
.endif ; M0/M0+/M1
|
||||
.endasmfunc
|
||||
|
||||
|
||||
;*****************************************************************************
|
||||
; The QF_set_BASEPRI function sets the BASEPRI register to the value
|
||||
; passed in r0.
|
||||
@ -191,80 +214,14 @@ QF_set_BASEPRI: .asmfunc
|
||||
|
||||
|
||||
;*****************************************************************************
|
||||
; Inform QK about interrupt entry.
|
||||
; C prototype: void QK_ISR_ENTRY(void);
|
||||
; The QK_get_IPSR function gets the IPSR register and returns it in r0.
|
||||
; C prototype: uint32_t QK_get_IPSR(void);
|
||||
;*****************************************************************************
|
||||
QK_ISR_ENTRY: .asmfunc
|
||||
.if __TI_TMS470_V7M3__ | __TI_TMS470_V7M4__ ; | __TI_TMS470_V7M7__
|
||||
MOVS r0,#QF_BASEPRI
|
||||
MSR BASEPRI,r0 ; selectively disable interrupts
|
||||
.else ; M0/M0+/M1
|
||||
CPSID i ; disable interrupts (set PRIMASK)
|
||||
.endif ; M0/M0+/M1
|
||||
|
||||
; ++QK_intNest_
|
||||
LDR r1,QK_intNest_addr ; address of the QK_intNest_
|
||||
LDR r0,[r1]
|
||||
ADDS r0,r0,#1
|
||||
STR r0,[r1]
|
||||
|
||||
.if __TI_TMS470_V7M3__ | __TI_TMS470_V7M4__ ; | __TI_TMS470_V7M7__
|
||||
MOVS r0,#0
|
||||
MSR BASEPRI,r0 ; set BASEPRI (disable interrupts)
|
||||
.else ; M0/M0+/M1
|
||||
CPSIE i ; enable interrupts (set PRIMASK)
|
||||
.endif ; M0/M0+/M1
|
||||
|
||||
QK_get_IPSR: .asmfunc
|
||||
MRS r0,ipsr ; r0 := IPSR
|
||||
BX lr ; return to the caller
|
||||
.endasmfunc
|
||||
|
||||
|
||||
;*****************************************************************************
|
||||
; Inform QK about interrupt exit.
|
||||
; C prototype: void QK_ISR_EXIT(void);
|
||||
;*****************************************************************************
|
||||
QK_ISR_EXIT: .asmfunc
|
||||
PUSH {r0,lr} ; push lr (return address) plus stack "aligner"
|
||||
; NOTE: because of the call to QK_schedPrio_()
|
||||
|
||||
.if __TI_TMS470_V7M3__ | __TI_TMS470_V7M4__ ; | __TI_TMS470_V7M7__
|
||||
MOVS r0,#QF_BASEPRI
|
||||
MSR BASEPRI,r0 ; selectively disable interrupts
|
||||
.else ; M0/M0+/M1
|
||||
CPSID i ; disable interrupts (set PRIMASK)
|
||||
.endif ; M0/M0+/M1
|
||||
|
||||
; --QK_intNest_
|
||||
LDR r1,QK_intNest_addr ; address of the QK_intNest_
|
||||
LDR r0,[r1]
|
||||
SUBS r0,r0,#1
|
||||
STR r0,[r1]
|
||||
|
||||
BL QK_schedPrio_ ; check if we have preemption
|
||||
CMP r0,#0 ; is prio == 0 ?
|
||||
BEQ.N no_preemption ; if prio == 0, branch to no_preemption
|
||||
|
||||
LDR r1,QK_nextPrio_addr ; address of the QK_nextPrio_
|
||||
STR r0,[r1] ; QK_nextPrio_ = prio
|
||||
|
||||
; trigger PendSV to return to preempted task...
|
||||
LDR r0,ICSR_addr ; Interrupt Control and State Register
|
||||
MOVS r1,#1
|
||||
LSLS r1,r1,#28 ; r0 := (1 << 28) (PENDSVSET bit)
|
||||
STR r1,[r0] ; ICSR[28] := 1 (pend PendSV)
|
||||
|
||||
no_preemption:
|
||||
.if __TI_TMS470_V7M3__ | __TI_TMS470_V7M4__ ; | __TI_TMS470_V7M7__
|
||||
MOVS r0,#0
|
||||
MSR BASEPRI,r0 ; set BASEPRI (disable interrupts)
|
||||
.else ; M0/M0+/M1
|
||||
CPSIE i ; enable interrupts (set PRIMASK)
|
||||
.endif ; M0/M0+/M1
|
||||
|
||||
POP {r0,pc} ; pop the stack "aligner" and saved LR to PC
|
||||
.endasmfunc
|
||||
|
||||
|
||||
;*****************************************************************************
|
||||
; The assert_failed() function restores the SP (in case stack is corrupted)
|
||||
; and calls Q_onAssert(module, loc)
|
||||
@ -289,7 +246,6 @@ VTOR_addr: .word 0xE000ED08
|
||||
;*****************************************************************************
|
||||
; Addresses for PC-relative LDR
|
||||
;*****************************************************************************
|
||||
QK_nextPrio_addr: .word QK_nextPrio_
|
||||
QK_sched_addr: .word QK_sched_
|
||||
QK_intNest_addr: .word QK_intNest_
|
||||
PendSV_sched_ret_addr .word PendSV_sched_ret
|
||||
|
@ -1,7 +1,7 @@
|
||||
;*****************************************************************************
|
||||
; Product: QXK port to ARM Cortex-M (M0,M0+,M1,M3,M4,M7), ARM-Keil assembler
|
||||
; Last Updated for Version: 5.6.0
|
||||
; Date of the Last Update: 2015-12-14
|
||||
; Last Updated for Version: 5.6.4
|
||||
; Date of the Last Update: 2016-04-23
|
||||
;
|
||||
; Q u a n t u m L e a P s
|
||||
; ---------------------------
|
||||
@ -200,6 +200,12 @@ PendSV_Handler
|
||||
ENDIF ; M3/M4/M7
|
||||
ISB ; flush the instruction pipeline
|
||||
|
||||
; un-pend any PendSV pended from the time this PendSV was called...
|
||||
LDR r2,=0xE000ED04 ; Interrupt Control and State Register
|
||||
MOVS r1,#1
|
||||
LSLS r1,r1,#27 ; r0 := (1 << 27) (UNPENDSVSET bit)
|
||||
STR r1,[r2] ; ICSR[27] := 1 (unpend PendSV)
|
||||
|
||||
; store the SP of the current QXK thread...
|
||||
LDR r1,=QXK_attr_
|
||||
LDR r2,[r1,#QXK_CURR]
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
* Product: QXK port to ARM Cortex-M (M0,M0+,M1,M3,M4,M7), GNU-ARM assembler
|
||||
* Last Updated for Version: 5.6.0
|
||||
* Date of the Last Update: 2015-12-10
|
||||
* Last Updated for Version: 5.6.4
|
||||
* Date of the Last Update: 2016-04-23
|
||||
*
|
||||
* Q u a n t u m L e a P s
|
||||
* ---------------------------
|
||||
@ -200,6 +200,12 @@ PendSV_Handler:
|
||||
.endif /* M3/M4/M7 */
|
||||
ISB /* reset the instruction pipeline */
|
||||
|
||||
/* un-pend any PendSV pended from the time this PendSV was called... */
|
||||
LDR r2,=0xE000ED04 /* Interrupt Control and State Register */
|
||||
MOVS r1,#1
|
||||
LSLS r1,r1,#27 /* r0 := (1 << 27) (UNPENDSVSET bit) */
|
||||
STR r1,[r2] /* ICSR[27] := 1 (unpend PendSV) */
|
||||
|
||||
/* store the SP of the current QXK thread... */
|
||||
LDR r1,=QXK_attr_
|
||||
LDR r2,[r1,#QXK_CURR]
|
||||
|
@ -1,7 +1,7 @@
|
||||
;*****************************************************************************
|
||||
; Product: QXK port to ARM Cortex-M (M0,M0+,M1,M3,M4,M7), IAR ARM assembler
|
||||
; Last Updated for Version: 5.6.0
|
||||
; Date of the Last Update: 2015-12-09
|
||||
; Last Updated for Version: 5.6.4
|
||||
; Date of the Last Update: 2016-04-23
|
||||
;
|
||||
; Q u a n t u m L e a P s
|
||||
; ---------------------------
|
||||
@ -196,6 +196,12 @@ PendSV_Handler:
|
||||
#endif ; M3/M4/M7
|
||||
ISB ; flush the instruction pipeline
|
||||
|
||||
; un-pend any PendSV pended from the time this PendSV was called...
|
||||
LDR r2,=0xE000ED04 ; Interrupt Control and State Register
|
||||
MOVS r1,#1
|
||||
LSLS r1,r1,#27 ; r0 := (1 << 27) (UNPENDSVSET bit)
|
||||
STR r1,[r2] ; ICSR[27] := 1 (unpend PendSV)
|
||||
|
||||
; store the SP of the current QXK thread...
|
||||
LDR r1,=QXK_attr_
|
||||
LDR r2,[r1,#QXK_CURR]
|
||||
|
@ -1,7 +1,7 @@
|
||||
;*****************************************************************************
|
||||
; Product: QXK port to ARM Cortex-M (M0,M0+,M1,M3,M4,M7), TI-ARM assembler
|
||||
; Last Updated for Version: 5.6.0
|
||||
; Date of the Last Update: 2015-12-12
|
||||
; Last Updated for Version: 5.6.4
|
||||
; Date of the Last Update: 2016-04-24
|
||||
;
|
||||
; Q u a n t u m L e a P s
|
||||
; ---------------------------
|
||||
@ -206,6 +206,12 @@ PendSV_Handler: .asmfunc
|
||||
.endif ; M0/M0+/M1
|
||||
ISB ; flush the instruction pipeline
|
||||
|
||||
; un-pend any PendSV pended from the time this PendSV was called...
|
||||
LDR r2,ICSR_addr ; Interrupt Control and State Register
|
||||
MOVS r1,#1
|
||||
LSLS r1,r1,#27 ; r0 := (1 << 27) (UNPENDSVSET bit)
|
||||
STR r1,[r2] ; ICSR[27] := 1 (unpend PendSV)
|
||||
|
||||
; store the SP of the current QXK thread...
|
||||
LDR r1,QXK_attr_addr
|
||||
LDR r2,[r1,#QXK_CURR]
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,2 +0,0 @@
|
||||
QP/C++ 5.6.3
|
||||
2016-04-12
|
2
version-5.6.4
Normal file
2
version-5.6.4
Normal file
@ -0,0 +1,2 @@
|
||||
QP/C++ 5.6.4
|
||||
2016-04-25
|
Loading…
x
Reference in New Issue
Block a user