5.9.6-beta

This commit is contained in:
Quantum Leaps 2017-07-28 22:54:35 -04:00
parent d90418fdb9
commit f691fd14b9
35 changed files with 3756 additions and 3519 deletions

View File

@ -1,9 +1,6 @@
//*****************************************************************************
// Updated by Quantum Leaps for CMIS 5.0.1
// 2016-12-12
//*****************************************************************************
//
// Copyright (C) 2012 - 2014 Texas Instruments Incorporated - http://www.ti.com/
// Copyright (C) 2012 - 2017 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
@ -40,63 +37,18 @@
#ifndef CMSIS_CCS_H_
#define CMSIS_CCS_H_
// Data Synchronization Barrier
__attribute__( ( always_inline ) ) static inline void __DSB(void)
{
__asm(" dsb");
}
// Instruction Synchronization Barrier
__attribute__( ( always_inline ) ) static inline void __ISB(void)
{
__asm(" isb");
}
#if (0)
// Get Main Stack Pointer
static inline uint32_t __get_MSP(void)
{
register uint32_t result;
//__asm (" mrs result, msp");
return(result);
}
// Set Main Stack Pointer
static inline void __set_MSP(uint32_t topOfMainStack)
{
asm(" .global topOfMainStack");
__asm (" msr msp, topOfMainStack");
}
// Get Priority Mask
static inline uint32_t __get_PRIMASK(void)
{
uint32_t result;
__asm (" mrs result, primask");
return(result);
}
// Set Priority Mask
static inline void __set_PRIMASK(uint32_t priMask)
{
__asm (" msr primask, priMask");
}
#endif
//*****************************************************************************
// CMSIS-compatible instruction calls
//*****************************************************************************
//
// v5e, v6, Cortex-M3, Cortex-M4, Cortex-R4, and Cortex-A8 compiler intrinsics
//
#define __CLZ _norm
#define __SXTB _sxtb
#define __SXTH _sxth
#define __UXTB _uxtb
#define __UXTH _uxth
#define __NOP __nop
#define __WFI __wfi
#define __CLZ _norm
#define __SXTB _sxtb
#define __SXTH _sxth
#define __UXTB _uxtb
#define __UXTH _uxth
// CCS supports intrinsics to take advantage of the shift operand left/right
// before saturation extension of SSAT, but CMSIS does not take advantage
// of those, so tell the compiler to use a sat & shift left with a shift
@ -108,18 +60,67 @@ static inline void __set_PRIMASK(uint32_t priMask)
// Only define M4 based intrinsics if we're not using an M4
//
#if defined (__TI_TMS470_V7M4__)
//
// Add definitions for enable and disable interrupts
//
#if defined (__TI_COMPILER_VERSION__)
#if (__TI_COMPILER_VERSION__ >= 5002000)
#define __enable_irq _enable_IRQ
#define __disable_irq _disable_IRQ
// No Operation
#define __NOP __nop
// Data Synchronization Barrier
#define __DSB _dsb
#define __ISB _isb
#elif (__TI_COMPILER_VERSION__ >= 4009000)
#define __enable_fault_irq _enable_interrupts
#define __disable_fault_irq _disable_interrupts
// No Operation
__attribute__( ( always_inline ) ) static inline void __nop(void)
{
__asm(" nop");
}
__attribute__( ( always_inline ) ) static inline void __NOP(void)
{
__asm(" nop");
}
// Data Synchronization Barrier
__attribute__( ( always_inline ) ) static inline void __DSB(void)
{
__asm(" dsb");
}
__attribute__( ( always_inline ) ) static inline void __ISB(void)
{
__asm(" isb");
}
#endif /*__TI_COMPILER_VERSION__ version*/
#endif /*__TI_COMPILER_VERSION__*/
//
// V5E, V6, Cortex-M4, Cortex-R4, and Cortex-A8 compiler intrinsics
//
#define __QADD _sadd
#define __QDADD _sdadd
#define __QDSUB _sdsub
#define __SMLABB _smlabb
#define __SMLABT _smlabt
#define __SMLALBB _smlalbb
#define __SMLALBT _smlalbt
#define __SMLALTB _smlaltb
#define __SMLALTT _smlaltt
#define __ROR __ror
#define __SXTB16(src) _sxtb16((src),0)
#define __QADD _sadd
#define __QDADD _sdadd
#define __QDSUB _sdsub
#define __SMLABB _smlabb
#define __SMLABT _smlabt
#define __SMLALBB _smlalbb
#define __SMLALBT _smlalbt
#define __SMLALTB _smlaltb
#define __SMLALTT _smlaltt
#define __SMLATB _smlatb
#define __SMLATT _smlatt
#define __SMLAWB _smlawb
@ -131,77 +132,77 @@ static inline void __set_PRIMASK(uint32_t priMask)
#define __SMULTT _smultt
#define __SMULWB _smulwb
#define __SMULWT _smulwt
#define __QSUB _ssub
#define __SUBC _subc
#define __QSUB _ssub
#define __SUBC _subc
//
// v6, Cortex-M4, Cortex-R4, and Cortex-A8 compiler intrinsics
//
#define __SHASX _shaddsubx
#define __SHSAX _shsubaddx
#define __PKHBT _pkhbt
#define __PKHTB _pkhtb
#define __SHASX _shaddsubx
#define __SHSAX _shsubaddx
#define __PKHBT _pkhbt
#define __PKHTB _pkhtb
#define __QADD16 _qadd16
#define __QADD8 _qadd8
#define __QADD8 _qadd8
#define __QSUB16 _qsub16
#define __QSUB8 _qsub8
#define __QASX _saddsubx
#define __QSAX _qsubaddx
#define __QSUB8 _qsub8
#define __QASX _saddsubx
#define __QSAX _qsubaddx
#define __SADD16 _sadd16
#define __SADD8 _sadd8
#define __SASX _saddsubx
#define __SEL _sel
#define __SHADD16 _shadd16
#define __SADD8 _sadd8
#define __SASX _saddsubx
#define __SEL _sel
#define __SHADD16 _shadd16
#define __SHADD8 _shadd8
#define __SHSUB16 _shsub16
#define __SHSUB16 _shsub16
#define __SHSUB8 _shsub8
#define __SMLAD _smlad
#define __SMLAD _smlad
#define __SMLADX _smladx
#define __SMLALD _smlald
#define __SMLALDX _smlaldx
#define __SMLSD _smlsd
#define __SMLALD(src1, src2, accumulator) _smlald(accumulator, src1, src2)
#define __SMLALDX _smlaldx
#define __SMLSD _smlsd
#define __SMLSDX _smlsdx
#define __SMLSLD _smlsld
#define __SMLSLDX _smlsldx
#define __SMMLA _smmla
#define __SMLSLDX _smlsldx
#define __SMMLA _smmla
#define __SMMLAR _smmlar
#define __SMMLS _smmls
#define __SMMLS _smmls
#define __SMMLSR _smmlsr
#define __SMMUL _smmul
#define __SMMUL _smmul
#define __SMMULR _smmulr
#define __SMUAD _smuad
#define __SMUAD _smuad
#define __SMUADX _smuadx
#define __SMUSD _smusd
#define __SMUSDX _smusd
#define __SMUSD _smusd
#define __SMUSDX _smusdx
#define __SSAT16 _ssat16
#define __SSUB16 _ssub16
#define __SSUB8 _ssub8
#define __SSAX _ssubaddx
#define __SXTAB _sxtab
#define __SXTAB16 _sxtab16
#define __SXTAH _sxtah
#define __UMAAL _umaal
#define __SSUB8 _ssub8
#define __SSAX _ssubaddx
#define __SXTAB _sxtab
#define __SXTAB16 _sxtab16
#define __SXTAH _sxtah
#define __UMAAL _umaal
#define __UADD16 _uadd16
#define __UADD8 _uadd8
#define __UHADD16 _uhadd16
#define __UADD8 _uadd8
#define __UHADD16 _uhadd16
#define __UHADD8 _uhadd8
#define __UASX _uaddsubx
#define __UHSUB16 _uhsub16
#define __UASX _uaddsubx
#define __UHSUB16 _uhsub16
#define __UHSUB8 _uhsub8
#define __UQADD16 _uqadd16
#define __UQADD16 _uqadd16
#define __UQADD8 _uqadd8
#define __UQASX _uqaddsubx
#define __UQSUB16 _uqsub16
#define __UQASX _uqaddsubx
#define __UQSUB16 _uqsub16
#define __UQSUB8 _uqsub8
#define __UQSAX _uqsubaddx
#define __USAD8 _usad8
#define __UQSAX _uqsubaddx
#define __USAD8 _usad8
#define __USAT16 _usat16
#define __USUB16 _usub16
#define __USUB8 _usub8
#define __USAX _usubaddx
#define __UXTAB _uxtab
#define __UXTAB16 _uxtab16
#define __UXTAH _uxtah
#define __USUB8 _usub8
#define __USAX _usubaddx
#define __UXTAB _uxtab
#define __UXTAB16 _uxtab16
#define __UXTAH _uxtah
#define __UXTB16 _uxtb16
#endif /*__TI_TMS470_V7M4__*/

View File

@ -1,8 +1,9 @@
![QP framework](https://state-machine.com/img/qp_banner.jpg)
> **NOTE:** If your company has a policy forbidding open source in your product, all QP frameworks can be [licensed commercially](https://state-machine.com/licensing), in which case you don't use any open source license and you do not violate your policy.
# What's New?
View QP/C++ Revision History at:
https://state-machine.com/qpcpp/history.html
View QP/C++ Revision History at: https://state-machine.com/qpcpp/history.html
---------------------------------------------------------------------------
# About QP/C++
@ -71,14 +72,20 @@ https://state-machine.com/doc/AN_Getting_Started_with_QPCpp.pdf
The guide also contains a tutorial, in which you build a simple "Blinky"
application.
> NOTE: QP/C++ can be unzipped anywhere in your file system, but the
> **NOTE:** QP/C++ can be unzipped anywhere in your file system, but the
recommended location is `C:\qp\qpcpp` on Windows and `~/qp/qpcpp`
on Linux/MacOS.
---------------------------------------------------------------------------
# QP/C++ Licensing
QP/C++ is licensed under the increasingly popular [dual licensing model](https://state-machine.com/licensing), in which both the open source software distribution mechanism and traditional closed source software distribution models are combined.
> **NOTE:** If your company has a policy forbidding open source in your product, all QP frameworks can be [licensed commercially](https://state-machine.com/licensing), in which case you don't use any open source license and you do not violate your policy.
---------------------------------------------------------------------------
# QP/C++ Documentation
The **QP/C++ Manual** is located online at:
- https://state-machine.com/qpcpp
The **QP/C++ Manual** is located online at: https://state-machine.com/qpcpp
---------------------------------------------------------------------------
# How to get help?

View File

@ -4,8 +4,8 @@ namespace QP {
@section qpcpp_5_9_5 Version 5.9.5, 2017-07-20
This release fixes the following bugs:
- <a href="https://sourceforge.net/p/qpc/bugs/178/" class="extern">bug#178</a> "GNU-ARM compiler reports "Error: unaligned opcodes..." in startup code for QP/C/C++/nano examples". The bug fix entails modifying the startup code for the GNU-ARM compiler in the `3rd_party` directory. Specifically, the proper alignment directives have been added to the inline assembly in the exception handlers.
- <a href="https://sourceforge.net/p/qpc/bugs/179/" class="extern">bug#179</a> "Assertion ID 210 fires when signaling on a QXK semaphore"
- <a href="https://sourceforge.net/p/qpc/bugs/178/" class="extern">bug#178</a> "GNU-ARM compiler reports "Error: unaligned opcodes..." in startup code for QP/C/C++/nano examples". The bug fix entails modifying the startup code for the GNU-ARM compiler in the `3rd_party` directory. Specifically, the proper alignment directives have been added to the inline assembly in the exception handlers.
- <a href="https://sourceforge.net/p/qpc/bugs/179/" class="extern">bug#179</a> "Assertion ID 210 fires when signaling on a QXK semaphore"
This release fixes the naming problem of the startup code for the
STM32F7-Discovery board (in the `3rd_party/stm32f7-discovery/gnu/ and arm/`

File diff suppressed because it is too large Load Diff

View File

@ -7,15 +7,15 @@ private:
uint8_t m_opKey;
public:
Calc() : QHsm(Q_STATE_CAST(&QCalc::initial)) { // ctor
Calc() : QHsm(Q_STATE_CAST(&Calc::initial)) { // ctor
}
protected:
static QState initial (Calc * const me, QEvt const *e);
static QState on (Calc * const me, QEvt const *e);
static QState error (Calc * const me, QEvt const *e);
static QState ready (Calc * const me, QEvt const *e);
static QState result (Calc * const me, QEvt const *e);
static QState begin (Calc * const me, QEvt const *e);
static QState initial(Calc * const me, QEvt const *e);
static QState on (Calc * const me, QEvt const *e);
static QState error (Calc * const me, QEvt const *e);
static QState ready (Calc * const me, QEvt const *e);
static QState result (Calc * const me, QEvt const *e);
static QState begin (Calc * const me, QEvt const *e);
. . .
};

View File

@ -13,11 +13,11 @@ protected:
// NOTE: QMsm state machine code is not intended for manual
// coding but rather needs to be generated automatically by
// the QM modeling tool
static QState initial (Calc * const me, QEvt const *e);
static QState on (Calc * const me, QEvt const *e);
static QState error (Calc * const me, QEvt const *e);
static QState ready (Calc * const me, QEvt const *e);
static QState result (Calc * const me, QEvt const *e);
static QState begin (Calc * const me, QEvt const *e);
static QState initial(Calc * const me, QEvt const *e);
static QState on (Calc * const me, QEvt const *e);
static QState error (Calc * const me, QEvt const *e);
static QState ready (Calc * const me, QEvt const *e);
static QState result (Calc * const me, QEvt const *e);
static QState begin (Calc * const me, QEvt const *e);
. . .
};

View File

@ -32,11 +32,11 @@
</option>
<option>
<name>Input description</name>
<state>No specifier n, no float nor long long, no scan set, no assignment suppressing.</state>
<state>No specifier n, no float nor long long, no scan set, no assignment suppressing, without multibyte support.</state>
</option>
<option>
<name>Output description</name>
<state>No specifier a, A, no specifier n, no float nor long long, no flags.</state>
<state>No specifier a, A, no specifier n, no float nor long long, no flags, without multibyte support.</state>
</option>
<option>
<name>GOutputBinary</name>
@ -143,12 +143,12 @@
<option>
<name>FPU2</name>
<version>0</version>
<state>4</state>
<state>0</state>
</option>
<option>
<name>NrRegs</name>
<version>0</version>
<state>1</state>
<state>0</state>
</option>
<option>
<name>NEON</name>
@ -339,7 +339,7 @@
<state>$PROJ_DIR$\..</state>
<state>$PROJ_DIR$\..\..</state>
<state>$PROJ_DIR$\..\..\..\..\..\include</state>
<state>$PROJ_DIR$\..\..\..\..\..\source</state>
<state>$PROJ_DIR$\..\..\..\..\..\src</state>
<state>$PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qxk\iar</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\CMSIS\Include</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b</state>
@ -1087,7 +1087,7 @@
</option>
<option>
<name>OGLastSavedByProductVersion</name>
<state>7.60.1.11206</state>
<state>8.11.1.13270</state>
</option>
<option>
<name>GeneralEnableMisra</name>
@ -1361,7 +1361,7 @@
<state>$PROJ_DIR$\..</state>
<state>$PROJ_DIR$\..\..</state>
<state>$PROJ_DIR$\..\..\..\..\..\include</state>
<state>$PROJ_DIR$\..\..\..\..\..\source</state>
<state>$PROJ_DIR$\..\..\..\..\..\src</state>
<state>$PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qxk\iar</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\CMSIS\Include</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b</state>
@ -2109,7 +2109,7 @@
</option>
<option>
<name>OGLastSavedByProductVersion</name>
<state>7.60.1.11206</state>
<state>8.11.1.13270</state>
</option>
<option>
<name>GeneralEnableMisra</name>
@ -2383,7 +2383,7 @@
<state>$PROJ_DIR$\..</state>
<state>$PROJ_DIR$\..\..</state>
<state>$PROJ_DIR$\..\..\..\..\..\include</state>
<state>$PROJ_DIR$\..\..\..\..\..\source</state>
<state>$PROJ_DIR$\..\..\..\..\..\src</state>
<state>$PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qxk\iar</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\CMSIS\Include</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b</state>
@ -3117,58 +3117,52 @@
<group>
<name>QP</name>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qep_hsm.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qep_hsm.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qep_msm.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qep_msm.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_act.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_act.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_actq.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_actq.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_defer.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_defer.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_dyn.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_dyn.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_mem.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_mem.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_pkg.h</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_ps.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_ps.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_qact.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_qact.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_qeq.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_qeq.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_qmact.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_qmact.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_time.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qf_time.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qxk\qxk.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qxk.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qxk\qxk_mutex.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qxk_mutex.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qxk\qxk_sema.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qxk_pkg.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qxk_sema.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qxk_xthr.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qxk\qxk_xthr.cpp</name>
</file>
</group>
<group>
@ -3184,16 +3178,19 @@
<configuration>Release</configuration>
</excluded>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qs.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qs_fp.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_64bit.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qs_pkg.h</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_fp.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\source\qs_rx.cpp</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_rx.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qutest.cpp</name>
</file>
</group>
</project>

View File

@ -1,7 +1,7 @@
//****************************************************************************
// DPP example for QXK
// Last updated for version 5.9.4
// Last updated on 2017-07-06
// Last updated for version 5.9.6
// Last updated on 2017-07-27
//
// Q u a n t u m L e a P s
// ---------------------------
@ -41,7 +41,6 @@ namespace DPP {
static void Thread1_run(QP::QXThread * const me);
static void Thread2_run(QP::QXThread * const me);
static QP::QXThread l_test1(&Thread1_run, 0U);
static QP::QXThread l_test2(&Thread2_run, 0U);
static QP::QXMutex l_mutex;
@ -76,11 +75,11 @@ static void Thread1_run(QP::QXThread * const me) {
(void)l_sema.wait(BSP::TICKS_PER_SEC, 0U);
BSP::ledOn();
l_mutex.lock(); // exercise the mutex
// some flating point code to exercise the VFP...
float volatile x = 1.4142135F;
x = x * 1.4142135F;
//QP::QXThread::delay(1U, 0U); // asserts (blocking while holding a mutex)
l_mutex.unlock();
QP::QXThread::delay(BSP::TICKS_PER_SEC/7, 0U); // BLOCK
@ -105,7 +104,8 @@ static void Thread2_run(QP::QXThread * const me) {
// NOTE: the semaphore is initialized in the highest-priority thread
// that uses it. Alternatively, the semaphore can be initialized
// before any thread runs.
l_sema.init(0U); // start with zero count
l_sema.init(0U, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
for (;;) {
// some flating point code to exercise the VFP...
@ -120,7 +120,7 @@ static void Thread2_run(QP::QXThread * const me) {
QP::QF::gc(e); // recycle the event manually!
}
else {
me->delay(BSP::TICKS_PER_SEC/2, 0U); // wait some more (BLOCK)
QP::QXThread::delay(BSP::TICKS_PER_SEC/2, 0U); // BLOCK
l_sema.signal(); // signal Thread1
}

View File

@ -1,7 +1,7 @@
//****************************************************************************
// DPP example for QXK
// Last updated for version 5.7.2
// Last updated on 2016-09-28
// Last updated for version 5.9.6
// Last updated on 2017-07-27
//
// Q u a n t u m L e a P s
// ---------------------------
@ -41,7 +41,6 @@ namespace DPP {
static void Thread1_run(QP::QXThread * const me);
static void Thread2_run(QP::QXThread * const me);
static QP::QXThread l_test1(&Thread1_run, 0U);
static QP::QXThread l_test2(&Thread2_run, 0U);
static QP::QXMutex l_mutex;
@ -62,11 +61,11 @@ static void Thread1_run(QP::QXThread * const /*me*/) {
(void)l_sema.wait(BSP::TICKS_PER_SEC, 0U);
BSP::ledOn();
l_mutex.lock(); // exercise the mutex
// some flating point code to exercise the VFP...
float volatile x = 1.4142135F;
x = x * 1.4142135F;
//QP::QXThread::delay(1U, 0U); // asserts (blocking while holding a mutex)
l_mutex.unlock();
QP::QXThread::delay(BSP::TICKS_PER_SEC/7, 0U); // BLOCK
@ -86,7 +85,8 @@ static void Thread2_run(QP::QXThread * const me) {
// NOTE: the semaphore is initialized in the highest-priority thread
// that uses it. Alternatively, the semaphore can be initialized
// before any thread runs.
l_sema.init(0U); // start with zero count
l_sema.init(0U, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
for (;;) {
// some flating point code to exercise the VFP...
@ -101,7 +101,7 @@ static void Thread2_run(QP::QXThread * const me) {
QP::QF::gc(e); // recycle the event manually!
}
else {
me->delay(BSP::TICKS_PER_SEC/2, 0U); // wait some more (BLOCK)
QP::QXThread::delay(BSP::TICKS_PER_SEC/2, 0U); // BLOCK
l_sema.signal(); // signal Thread1
}
}

View File

@ -1,7 +1,7 @@
//****************************************************************************
// DPP example for QXK
// Last updated for version 5.7.2
// Last updated on 2016-09-28
// Last updated for version 5.9.6
// Last updated on 2017-07-27
//
// Q u a n t u m L e a P s
// ---------------------------
@ -41,7 +41,6 @@ namespace DPP {
static void Thread1_run(QP::QXThread * const me);
static void Thread2_run(QP::QXThread * const me);
static QP::QXThread l_test1(&Thread1_run, 0U);
static QP::QXThread l_test2(&Thread2_run, 0U);
static QP::QXMutex l_mutex;
@ -62,11 +61,11 @@ static void Thread1_run(QP::QXThread * const /*me*/) {
(void)l_sema.wait(BSP::TICKS_PER_SEC, 0U);
BSP::ledOn();
l_mutex.lock(); // exercise the mutex
// some flating point code to exercise the VFP...
float volatile x = 1.4142135F;
x = x * 1.4142135F;
//QP::QXThread::delay(1U, 0U); // asserts (blocking while holding a mutex)
l_mutex.unlock();
QP::QXThread::delay(BSP::TICKS_PER_SEC/7, 0U); // BLOCK
@ -86,7 +85,8 @@ static void Thread2_run(QP::QXThread * const me) {
// NOTE: the semaphore is initialized in the highest-priority thread
// that uses it. Alternatively, the semaphore can be initialized
// before any thread runs.
l_sema.init(0U); // start with zero count
l_sema.init(0U, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
for (;;) {
// some flating point code to exercise the VFP...
@ -101,7 +101,7 @@ static void Thread2_run(QP::QXThread * const me) {
QP::QF::gc(e); // recycle the event manually!
}
else {
me->delay(BSP::TICKS_PER_SEC/2, 0U); // wait some more (BLOCK)
QP::QXThread::delay(BSP::TICKS_PER_SEC/2, 0U); // BLOCK
l_sema.signal(); // signal Thread1
}
}

View File

@ -1,7 +1,7 @@
//****************************************************************************
// DPP example for QXK
// Last updated for version 5.7.2
// Last updated on 2016-09-28
// Last updated for version 5.9.6
// Last updated on 2017-07-27
//
// Q u a n t u m L e a P s
// ---------------------------
@ -41,7 +41,6 @@ namespace DPP {
static void Thread1_run(QP::QXThread * const me);
static void Thread2_run(QP::QXThread * const me);
static QP::QXThread l_test1(&Thread1_run, 0U);
static QP::QXThread l_test2(&Thread2_run, 0U);
static QP::QXMutex l_mutex;
@ -62,11 +61,11 @@ static void Thread1_run(QP::QXThread * const /*me*/) {
(void)l_sema.wait(BSP::TICKS_PER_SEC, 0U);
BSP::ledOn();
l_mutex.lock(); // exercise the mutex
// some flating point code to exercise the VFP...
float volatile x = 1.4142135F;
x = x * 1.4142135F;
//QP::QXThread::delay(1U, 0U); // asserts (blocking while holding a mutex)
l_mutex.unlock();
QP::QXThread::delay(BSP::TICKS_PER_SEC/7, 0U); // BLOCK
@ -86,7 +85,8 @@ static void Thread2_run(QP::QXThread * const me) {
// NOTE: the semaphore is initialized in the highest-priority thread
// that uses it. Alternatively, the semaphore can be initialized
// before any thread runs.
l_sema.init(0U); // start with zero count
l_sema.init(0U, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
for (;;) {
// some flating point code to exercise the VFP...
@ -101,7 +101,7 @@ static void Thread2_run(QP::QXThread * const me) {
QP::QF::gc(e); // recycle the event manually!
}
else {
me->delay(BSP::TICKS_PER_SEC/2, 0U); // wait some more (BLOCK)
QP::QXThread::delay(BSP::TICKS_PER_SEC/2, 0U); // BLOCK
l_sema.signal(); // signal Thread1
}
}

View File

@ -1,7 +1,7 @@
//****************************************************************************
// DPP example for QXK
// Last updated for version 5.8.2
// Last updated on 2017-02-03
// Last updated for version 5.9.6
// Last updated on 2017-07-27
//
// Q u a n t u m L e a P s
// ---------------------------
@ -41,7 +41,6 @@ namespace DPP {
static void Thread1_run(QP::QXThread * const me);
static void Thread2_run(QP::QXThread * const me);
static QP::QXThread l_test1(&Thread1_run, 0U);
static QP::QXThread l_test2(&Thread2_run, 0U);
static QP::QXMutex l_mutex;
@ -67,6 +66,7 @@ static void Thread1_run(QP::QXThread * const /*me*/) {
// some flating point code to exercise the VFP...
float volatile x = 1.4142135F;
x = x * 1.4142135F;
//QP::QXThread::delay(1U, 0U); // asserts (blocking while holding a mutex)
l_mutex.unlock();
QP::QXThread::delay(BSP::TICKS_PER_SEC/7, 0U); // BLOCK
@ -86,7 +86,8 @@ static void Thread2_run(QP::QXThread * const me) {
// NOTE: the semaphore is initialized in the highest-priority thread
// that uses it. Alternatively, the semaphore can be initialized
// before any thread runs.
l_sema.init(0U); // start with zero count
l_sema.init(0U, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
for (;;) {
// some flating point code to exercise the VFP...
@ -101,7 +102,7 @@ static void Thread2_run(QP::QXThread * const me) {
QP::QF::gc(e); // recycle the event manually!
}
else {
me->delay(BSP::TICKS_PER_SEC/2, 0U); // wait some more (BLOCK)
QP::QXThread::delay(BSP::TICKS_PER_SEC/2, 0U); // BLOCK
l_sema.signal(); // signal Thread1
}
}

View File

@ -1,7 +1,7 @@
//****************************************************************************
// DPP example for QXK
// Last updated for version 5.8.0
// Last updated on 2016-11-30
// Last updated for version 5.9.6
// Last updated on 2017-07-27
//
// Q u a n t u m L e a P s
// ---------------------------

View File

@ -3,8 +3,8 @@
/// @ingroup qxk
/// @cond
///***************************************************************************
/// Last updated for version 5.8.0
/// Last updated on 2016-11-19
/// Last updated for version 5.9.6
/// Last updated on 2017-07-27
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -69,18 +69,19 @@ class QXThread : public QActive {
public:
//! public constructor
QXThread(QXThreadHandler const handler, uint_fast8_t const tickRate);
QXThread(QXThreadHandler const handler,
uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0));
//! delay (block) the current extended thread for a specified # ticks
static bool delay(uint_fast16_t const nTicks,
uint_fast8_t const tickRate);
uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0));
//! cancel the delay
bool delayCancel(void);
//! obtain a message from the private message queue (block if no messages)
static QEvt const *queueGet(uint_fast16_t const nTicks,
uint_fast8_t const tickRate);
uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0));
// virtual function overrides...
//! Executes the top-most initial transition in QP::QMsm.
@ -123,7 +124,7 @@ private:
void block_(void) const;
void unblock_(void) const;
void teArm_(enum_t const sig, uint_fast16_t const nTicks,
uint_fast8_t const tickRate);
uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0));
bool teDisarm_(void);
// attributes...
@ -141,18 +142,20 @@ private:
class QXSemaphore {
public:
//! initialize the counting semaphore
void init(uint_fast16_t const count);
void init(uint_fast16_t const count,
uint_fast16_t const max_count = UINT16_MAX);
//! signal (unblock) the semaphore
void signal(void);
bool signal(void);
//! wait (block) on the semaphore
bool wait(uint_fast16_t const nTicks,
uint_fast8_t const tickRate);
uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0));
private:
uint_fast16_t m_count;
QPSet m_waitSet; //!< set of extended threads waiting on this semaphore
uint_fast16_t m_count;
uint_fast16_t m_max_count;
};
} // namespace QP

86
include/stdint_c.h Normal file
View File

@ -0,0 +1,86 @@
/// @file
/// @brief Macros for casting strongly-typed integer constants.
///
/// @description This header file provides the standard C99 and C++11
/// macros of the form UINT8_C(), UINT_FAST8_C(), etc. for building
/// strongly-typed constants of standard integers from <stdint.h>.
///
/// @cond
///***************************************************************************
/// Last updated for version 5.9.5
/// Last updated on 2017-07-20
///
/// Q u a n t u m L e a P s
/// ---------------------------
/// innovating embedded systems
///
/// Copyright (C) Quantum Leaps. 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
/// by the Free Software Foundation, either version 3 of the License, or
/// (at your option) any later version.
///
/// Alternatively, this program may be distributed and modified under the
/// terms of Quantum Leaps commercial licenses, which expressly supersede
/// the GNU General Public License and are specifically designed for
/// licensees interested in retaining the proprietary status of their code.
///
/// This program is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU General Public License for more details.
///
/// You should have received a copy of the GNU General Public License
/// along with this program. If not, see <http://www.gnu.org/licenses/>.
///
/// Contact information:
/// https://state-machine.com
/// mailto:info@state-machine.com
///***************************************************************************
/// @endcond
#ifndef stdint_c_h
#define stdint_c_h
#ifndef UINT8_C
#define UINT8_C(x_) (static_cast<std::uint8_t>(x_))
#endif
#ifndef INT8_C
#define INT8_C(x_) (static_cast<std::int8_t>(x_))
#endif
#ifndef UINT_FAST8_C
#define UINT_FAST8_C(x_) (static_cast<std::uint_fast8_t>(x_))
#endif
#ifndef INT_FAST8_C
#define INT_FAST8_C(x_) (static_cast<std::int_fast8_t>(x_))
#endif
#ifndef UINT16_C
#define UINT16_C(x_) (static_cast<std::uint16_t>(x_))
#endif
#ifndef INT16_C
#define INT16_C(x_) (static_cast<std::int16_t>(x_))
#endif
#ifndef UINT_FAST16_C
#define UINT_FAST16_C(x_) (static_cast<std::uint_fast16_t>(x_))
#endif
#ifndef UINT32_C
#define UINT32_C(x_) (static_cast<std::uint32_t>(x_))
#endif
#ifndef INT32_C
#define INT32_C(x_) (static_cast<std::int32_t>(x_))
#endif
#ifndef UINT_FAST32_C
#define UINT_FAST32_C(x_) (static_cast<std::uint_fast32_t>(x_))
#endif
#endif // stdint_c_h

View File

@ -1,7 +1,7 @@
;*****************************************************************************
; Product: QK port to ARM Cortex-M (M0,M0+,M3,M4,M7), ARM-KEIL assembler
; Last Updated for Version: 5.9.0
; Date of the Last Update: 2017-03-17
; Last Updated for Version: 5.9.6
; Date of the Last Update: 2017-07-28
;
; Q u a n t u m L e a P s
; ---------------------------
@ -111,16 +111,17 @@ QK_init FUNCTION
LSLS r1,r1,#8
ORRS r1,r1,#QF_BASEPRI
LDR r3,=0xE000E004 ; Interrupt Controller Type Register
LDR r3,[r3] ; r3 := INTLINESUM
LDR r2,=0xE000E400 ; NVIC_PRI0 register
LDR r3,=0xE000E004 ; Interrupt Controller Type Register (ICTR)
LDR r3,[r3]
ANDS r3,r3,#7 ; r3 := ICTR[0:2] (INTLINESNUM)
LSLS r3,r3,#3
ADDS r3,r3,#8 ; r3 == number of NVIC_PRIO registers
ADDS r3,r3,#8 ; r3 == (# NVIC_PRIO registers)/4
; loop over all implemented NVIC_PRIO registers for IRQs...
QK_init_irq
SUBS r3,r3,#1
LDR r2,=0xE000E400 ; NVIC_PRI0 register
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
CMP r3,#0
BNE QK_init_irq

View File

@ -1,7 +1,7 @@
/*****************************************************************************
* Product: QK port to ARM Cortex-M (M0,M0+,M3,M4,M7), GNU-ARM assembler
* Last Updated for Version: 5.9.3
* Date of the Last Update: 2017-06-17
* Last Updated for Version: 5.9.6
* Date of the Last Update: 2017-07-28
*
* Q u a n t u m L e a P s
* ---------------------------
@ -106,16 +106,18 @@ QK_init:
LSLS r1,r1,#8
ORRS r1,r1,#QF_BASEPRI
LDR r3,=0xE000E004 /* Interrupt Controller Type Register */
LDR r3,[r3] /* r3 := INTLINESUM */
LDR r2,=0xE000E400 /* NVIC_PRI0 register */
LDR r3,=0xE000E004 /* Interrupt Controller Type Register (ICTR) */
LDR r3,[r3]
LDR r3,[r3]
ANDS r3,r3,#7 /* r3 := ICTR[0:2] (INTLINESNUM) */
LSLS r3,r3,#3
ADDS r3,r3,#8 /* r3 == number of NVIC_PRIO registers */
ADDS r3,r3,#8 /* r3 == (# NVIC_PRIO registers)/4 */
/* loop over all implemented NVIC_PRIO registers for IRQs... */
QK_init_irq:
SUBS r3,r3,#1
LDR r2,=0xE000E400 /* NVIC_PRI0 register */
STR r1,[r2,r3,LSL #2] /* NVIC_PRI0[r3] := r1 */
STR r1,[r2,r3,LSL #2] /* NVIC_PRI0[r3] := r1 */
CMP r3,#0
BNE QK_init_irq

View File

@ -1,7 +1,7 @@
;*****************************************************************************
; Product: QK port to ARM Cortex-M (M0,M0+,M3,M4,M7), IAR-ARM assembler
; Last Updated for Version: 5.9.0
; Date of the Last Update: 2017-03-17
; Last Updated for Version: 5.9.6
; Date of the Last Update: 2017-07-28
;
; Q u a n t u m L e a P s
; ---------------------------
@ -110,16 +110,17 @@ QK_init:
LSLS r1,r1,#8
ORRS r1,r1,#QF_BASEPRI
LDR r3,=0xE000E004 ; Interrupt Controller Type Register
LDR r3,[r3] ; r3 := INTLINESUM
LDR r2,=0xE000E400 ; NVIC_PRI0 register
LDR r3,=0xE000E004 ; Interrupt Controller Type Register (ICTR)
LDR r3,[r3]
ANDS r3,r3,#7 ; r3 := ICTR[0:2] (INTLINESNUM)
LSLS r3,r3,#3
ADDS r3,r3,#8 ; r3 == number of NVIC_PRIO registers
ADDS r3,r3,#8 ; r3 == (# NVIC_PRIO registers)/4
; loop over all implemented NVIC_PRIO registers for IRQs...
QK_init_irq:
SUBS r3,r3,#1
LDR r2,=0xE000E400 ; NVIC_PRI0 register
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
CMP r3,#0
BNE QK_init_irq

View File

@ -1,7 +1,7 @@
;*****************************************************************************
; Product: QK port to ARM Cortex-M (M0,M0+,M3,M4,M7), TI-ARM assembler
; Last Updated for Version: 5.9.0
; Date of the Last Update: 2017-03-17
; Last Updated for Version: 5.9.6
; Date of the Last Update: 2017-07-28
;
; Q u a n t u m L e a P s
; ---------------------------
@ -109,16 +109,17 @@ QK_init: .asmfunc
LSLS r1,r1,#8
ORRS r1,r1,#QF_BASEPRI
LDR r3,ICTR_addr ; Interrupt Controller Type Register
LDR r3,[r3] ; r3 := INTLINESUM
LDR r2,PRI0_addr ; NVIC_PRI0 register
LDR r3,ICTR_addr ; Interrupt Controller Type Register (ICTR)
LDR r3,[r3] ; r3 := ICTR
ANDS r3,r3,#7 ; r3 := ICTR[0:2] (INTLINESNUM)
LSLS r3,r3,#3
ADDS r3,r3,#8 ; r3 == number of NVIC_PRIO registers
ADDS r3,r3,#8 ; r3 == (# NVIC_PRIO registers)/4
; loop over all implemented NVIC_PRIO registers for IRQs...
QK_init_irq:
SUBS r3,r3,#1
LDR r2,PRI0_addr ; NVIC_PRI0 register
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
CMP r3,#0
BNE QK_init_irq

View File

@ -1,9 +1,9 @@
/// @file
/// @brief QP/C++ port to ARM Cortex-M, cooperative QV kernel, IAR-ARM toolset
/// @brief QP/C++ port to ARM Cortex-M, cooperative QV kernel, ARM-KEIL toolset
/// @cond
///***************************************************************************
/// Last updated for version 5.8.1
/// Last updated on 2016-12-12
/// Last updated for version 5.9.6
/// Last updated on 2017-07-28
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -30,7 +30,7 @@
/// along with this program. If not, see <http://www.gnu.org/licenses/>.
///
/// Contact information:
/// www.state-machine.com
/// https://state-machine.com
/// mailto:info@state-machine.com
///***************************************************************************
/// @endcond
@ -61,7 +61,6 @@ extern "C" {
* The interrupt priorities established in QV_init() can be later
* changed by the application-level code.
*/
void QV_init(void) {
// set exception priorities to QF_BASEPRI...
@ -75,7 +74,7 @@ void QV_init(void) {
SCB_SYSPRI[3] |= (QF_BASEPRI << 24) | (QF_BASEPRI << 16) | QF_BASEPRI;
// set all implemented IRQ priories to QF_BASEPRI...
uint32_t n = 8 + (*SCnSCB_ICTR << 3); // # interrupt priority registers
uint32_t n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3); // (# NVIC_PRIO regs)/4
do {
--n;
NVIC_IP[n] = (QF_BASEPRI << 24) | (QF_BASEPRI << 16)

View File

@ -1,9 +1,9 @@
/// @file
/// @brief QP/C++ port to ARM Cortex-M, cooperative QV kernel, IAR-ARM toolset
/// @brief QP/C++ port to ARM Cortex-M, cooperative QV kernel, GNU-ARM toolset
/// @cond
///***************************************************************************
/// Last updated for version 5.8.1
/// Last updated on 2016-12-12
/// Last updated for version 5.9.6
/// Last updated on 2017-07-28
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -30,21 +30,21 @@
/// along with this program. If not, see <http://www.gnu.org/licenses/>.
///
/// Contact information:
/// www.state-machine.com
/// https://state-machine.com
/// mailto:info@state-machine.com
///***************************************************************************
/// @endcond
#include "qf_port.h"
#if (__ARM_ARCH != 6) /* NOT Cortex-M0/M0+/M1 ? */
#if (__ARM_ARCH != 6) // NOT Cortex-M0/M0+/M1 ?
extern "C" {
#define SCnSCB_ICTR ((uint32_t volatile *)0xE000E004)
#define SCB_SYSPRI ((uint32_t volatile *)0xE000ED14)
#define NVIC_IP ((uint32_t volatile *)0xE000E400)
extern "C" {
/*
* Initialize the exception priorities and IRQ priorities to safe values.
*
@ -74,7 +74,7 @@ void QV_init(void) {
SCB_SYSPRI[3] |= (QF_BASEPRI << 24) | (QF_BASEPRI << 16) | QF_BASEPRI;
// set all implemented IRQ priories to QF_BASEPRI...
uint32_t n = 8 + (*SCnSCB_ICTR << 3); // # interrupt priority registers
uint32_t n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3); // (# NVIC_PRIO regs)/4
do {
--n;
NVIC_IP[n] = (QF_BASEPRI << 24) | (QF_BASEPRI << 16)

View File

@ -2,8 +2,8 @@
/// @brief QP/C++ port to ARM Cortex-M, cooperative QV kernel, IAR-ARM toolset
/// @cond
///***************************************************************************
/// Last updated for version 5.8.1
/// Last updated on 2016-12-12
/// Last updated for version 5.9.6
/// Last updated on 2017-07-28
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -30,7 +30,7 @@
/// along with this program. If not, see <http://www.gnu.org/licenses/>.
///
/// Contact information:
/// www.state-machine.com
/// https://state-machine.com
/// mailto:info@state-machine.com
///***************************************************************************
/// @endcond
@ -61,7 +61,6 @@ extern "C" {
* The interrupt priorities established in QV_init() can be later
* changed by the application-level code.
*/
void QV_init(void) {
// set exception priorities to QF_BASEPRI...
@ -75,7 +74,7 @@ void QV_init(void) {
SCB_SYSPRI[3] |= (QF_BASEPRI << 24) | (QF_BASEPRI << 16) | QF_BASEPRI;
// set all implemented IRQ priories to QF_BASEPRI...
uint32_t n = 8 + (*SCnSCB_ICTR << 3); // # interrupt priority registers
uint32_t n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3); // (# NVIC_PRIO regs)/4
do {
--n;
NVIC_IP[n] = (QF_BASEPRI << 24) | (QF_BASEPRI << 16)
@ -86,4 +85,3 @@ void QV_init(void) {
} // extern "C"
#endif // NOT Cortex-M0/M0+/M1 ?

View File

@ -1,7 +1,7 @@
;*****************************************************************************
; Product: QV port to ARM Cortex-M (M0,M0+,M1,M3,M4,M7), TI-ARM assembler
; Last Updated for Version: 5.9.0
; Date of the Last Update: 2017-03-17
; Product: QV port to ARM Cortex-M (M0,M0+,M3,M4,M7), TI-ARM assembler
; Last Updated for Version: 5.9.6
; Date of the Last Update: 2017-07-28
;
; Q u a n t u m L e a P s
; ---------------------------
@ -139,16 +139,17 @@ QV_init: .asmfunc
LSLS r1,r1,#8
ORRS r1,r1,#QF_BASEPRI
LDR r2,PRI0_addr ; NVIC_PRI0 register
LDR r3,ICTR_addr ; Interrupt Controller Type Register
LDR r3,[r3] ; r3 := INTLINESUM
LDR r3,[r3] ; r3 := ICTR
ANDS r3,r3,#7 ; r3 := ICTR[0:2] (INTLINESNUM)
LSLS r3,r3,#3
ADDS r3,r3,#8 ; r3 == number of NVIC_PRIO registers
ADDS r3,r3,#8 ; r3 == (# NVIC_PRIO registers)/4
; loop over all implemented NVIC_PRIO registers for IRQs...
QV_init_irq:
SUBS r3,r3,#1
LDR r2,PRI0_addr ; NVIC_PRI0 register
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
CMP r3,#0
BNE QV_init_irq

View File

@ -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.9.4
; Date of the Last Update: 2017-07-06
; Product: QXK port to ARM Cortex-M (M0,M0+,M3,M4,M7), ARM-Keil assembler
; Last Updated for Version: 5.9.6
; Date of the Last Update: 2017-07-28
;
; Q u a n t u m L e a P s
; ---------------------------
@ -83,7 +83,7 @@ QXK_init FUNCTION
ELSE ; Cortex-M3/M4/..
; NOTE:
; On Cortex-M3/M4/M7.., this QK port disables interrupts by means of
; On Cortex-M3/M4/M7.., this QXK port disables interrupts by means of
; the BASEPRI register. However, this method cannot disable interrupt
; priority zero, which is the default for all interrupts out of reset.
; The following code changes the SysTick priority and all IRQ priorities
@ -124,16 +124,17 @@ QXK_init FUNCTION
LSLS r1,r1,#8
ORRS r1,r1,#QF_BASEPRI
LDR r3,=0xE000E004 ; Interrupt Controller Type Register
LDR r3,[r3] ; r3 := INTLINESUM
LDR r2,=0xE000E400 ; NVIC_PRI0 register
LDR r3,=0xE000E004 ; Interrupt Controller Type Register (ICTR)
LDR r3,[r3]
ANDS r3,r3,#7 ; r3 := ICTR[0:2] (INTLINESNUM)
LSLS r3,r3,#3
ADDS r3,r3,#8 ; r3 == number of NVIC_PRIO registers
ADDS r3,r3,#8 ; r3 == (# NVIC_PRIO registers)/4
; loop over all implemented NVIC_PRIO registers for IRQs...
QXK_init_irq
SUBS r3,r3,#1
LDR r2,=0xE000E400 ; NVIC_PRI0 register
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
CMP r3,#0
BNE QXK_init_irq

View File

@ -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.9.4
* Date of the Last Update: 2017-07-06
* Product: QXK port to ARM Cortex-M (M0,M0+,M3,M4,M7), GNU-ARM assembler
* Last Updated for Version: 5.9.6
* Date of the Last Update: 2017-07-28
*
* Q u a n t u m L e a P s
* ---------------------------
@ -114,16 +114,17 @@ QXK_init:
LSLS r1,r1,#8
ORRS r1,r1,#QF_BASEPRI
LDR r3,=0xE000E004 /* Interrupt Controller Type Register */
LDR r3,[r3] /* r3 := INTLINESUM */
LDR r2,=0xE000E400 /* NVIC_PRI0 register */
LDR r3,=0xE000E004 /* Interrupt Controller Type Register (ICTR) */
LDR r3,[r3]
ANDS r3,r3,#7 /* r3 := ICTR[0:2] (INTLINESNUM) */
LSLS r3,r3,#3
ADDS r3,r3,#8 /* r3 == number of NVIC_PRIO registers */
ADDS r3,r3,#8 /* r3 == (# NVIC_PRIO registers)/4 */
/* loop over all implemented NVIC_PRIO registers for IRQs... */
QXK_init_irq:
SUBS r3,r3,#1
LDR r2,=0xE000E400 /* NVIC_PRI0 register */
STR r1,[r2,r3,LSL #2] /* NVIC_PRI0[r3] := r1 */
STR r1,[r2,r3,LSL #2] /* NVIC_PRI0[r3] := r1 */
CMP r3,#0
BNE QXK_init_irq

View File

@ -1,7 +1,7 @@
;*****************************************************************************
; Product: QXK port to ARM Cortex-M (M0,M0+,M3,M4,M7), IAR-ARM assembler
; Last Updated for Version: 5.9.4
; Date of the Last Update: 2017-07-06
; Last Updated for Version: 5.9.6
; Date of the Last Update: 2017-07-28
;
; Q u a n t u m L e a P s
; ---------------------------
@ -51,7 +51,7 @@ QXK_NEXT EQU 4
QXK_TOP_PRIO EQU 8
; NOTE: keep in synch with the QMActive struct in "qf.h/qxk.h" !!!
QMACTIVE_OSOBJ EQU 40
QMACTIVE_OSOBJ EQU 40
QMACTIVE_PRIO EQU 48
@ -123,20 +123,21 @@ QXK_init:
LSLS r1,r1,#8
ORRS r1,r1,#QF_BASEPRI
LDR r3,=0xE000E004 ; Interrupt Controller Type Register
LDR r3,[r3] ; r3 := INTLINESUM
LDR r2,=0xE000E400 ; NVIC_PRI0 register
LDR r3,=0xE000E004 ; Interrupt Controller Type Register (ICTR)
LDR r3,[r3]
ANDS r3,r3,#7 ; r3 := ICTR[0:2] (INTLINESNUM)
LSLS r3,r3,#3
ADDS r3,r3,#8 ; r3 == number of NVIC_PRIO registers
ADDS r3,r3,#8 ; r3 == (# NVIC_PRIO registers)/4
; loop over all implemented NVIC_PRIO registers for IRQs...
QXK_init_irq:
SUBS r3,r3,#1
LDR r2,=0xE000E400 ; NVIC_PRI0 register
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
CMP r3,#0
BNE QXK_init_irq
#endif ; Cortex-M3/M4/...
#endif ; Cortex-M3/M4/M7
MOV r0,r12 ; r0 := original PRIMASK
MSR PRIMASK,r0 ; PRIMASK := r0

View File

@ -1,7 +1,7 @@
;*****************************************************************************
; Product: QXK port to ARM Cortex-M (M0,M0+,M3,M4,M7), TI-ARM assembler
; Last Updated for Version: 5.9.4
; Date of the Last Update: 2017-07-06
; Last Updated for Version: 5.9.6
; Date of the Last Update: 2017-07-28
;
; Q u a n t u m L e a P s
; ---------------------------
@ -59,7 +59,7 @@ QXK_NEXT .equ 4
QXK_TOP_PRIO .equ 8
; NOTE: keep in synch with the QMActive struct in "qf.h/qxk.h" !!!
QMACTIVE_OSOBJ .equ 44
QMACTIVE_OSOBJ .equ 40
QMACTIVE_PRIO .equ 48
.text
@ -77,7 +77,7 @@ QXK_init: .asmfunc
.if __TI_TMS470_V7M3__ | __TI_TMS470_V7M4__ ; | __TI_TMS470_V7M7__ ; M3/4/7?
; NOTE:
; On Cortex-M3/M4/M7.., this QK port disables interrupts by means of
; On Cortex-M3/M4/M7.., this QXK port disables interrupts by means of
; the BASEPRI register. However, this method cannot disable interrupt
; priority zero, which is the default for all interrupts out of reset.
; The following code changes the SysTick priority and all IRQ priorities
@ -118,16 +118,17 @@ QXK_init: .asmfunc
LSLS r1,r1,#8
ORRS r1,r1,#QF_BASEPRI
LDR r2,PRI0_addr ; NVIC_PRI0 register
LDR r3,ICTR_addr ; Interrupt Controller Type Register
LDR r3,[r3] ; r3 := INTLINESUM
LDR r3,[r3] ; r3 := INTLINESNUM
ANDS r3,r3,#7 ; r3 := ICTR[0:2] (INTLINESNUM)
LSLS r3,r3,#3
ADDS r3,r3,#8 ; r3 == number of NVIC_PRIO registers
ADDS r3,r3,#8 ; r3 == (# NVIC_PRIO registers)/4
; loop over all implemented NVIC_PRIO registers for IRQs...
QXK_init_irq:
SUBS r3,r3,#1
LDR r2,PRI0_addr ; NVIC_PRI0 register
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
STR r1,[r2,r3,LSL #2] ; NVIC_PRI0[r3] := r1
CMP r3,#0
BNE QXK_init_irq

View File

@ -4,8 +4,8 @@
/// @ingroup qxk
/// @cond
///***************************************************************************
/// Last updated for version 5.9.4
/// Last updated on 2017-07-06
/// Last updated for version 5.9.6
/// Last updated on 2017-07-27
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -52,6 +52,8 @@
#error "Source file included in a project NOT based on the QXK kernel"
#endif // qxk_h
Q_DEFINE_THIS_MODULE("qxk")
// Public-scope objects ******************************************************
extern "C" {
QXK_Attr QXK_attr_; // global attributes of the QXK kernel
@ -59,8 +61,6 @@ extern "C" {
namespace QP {
Q_DEFINE_THIS_MODULE("qxk")
// Local-scope objects *******************************************************
class QXKIdleThread : public QActive {
public:
@ -441,8 +441,14 @@ QP::QActive *QXK_current(void) {
QF_CRIT_ENTRY_();
curr = QXK_attr_.curr;
if (curr == static_cast<QP::QActive *>(0)) { // basic thread?
curr = QP::QF::active_[QXK_attr_.actPrio];
}
QF_CRIT_EXIT_();
//! @post the current thread must be valid
Q_ENSURE_ID(900, curr != static_cast<QP::QActive *>(0));
return curr;
}

View File

@ -5,8 +5,8 @@
/// @cond
///***************************************************************************
/// Product: QK/C++
/// Last updated for version 5.9.4
/// Last updated on 2017-07-05
/// Last updated for version 5.9.6
/// Last updated on 2017-07-27
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -105,7 +105,7 @@ void QXMutex::lock(void) {
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre scheduler cannot be locked from the ISR context
/// @pre The mutex cannot be locked from the ISR context
/// and the mutex must be unused
Q_REQUIRE_ID(700, (!QXK_ISR_CONTEXT_())
&& (m_prevPrio == static_cast<uint_fast8_t>(MUTEX_UNUSED)));
@ -124,7 +124,7 @@ void QXMutex::lock(void) {
QS_BEGIN_NOCRIT_(QS_SCHED_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(m_prevPrio), /* previouis lock prio */
QS_2U8_(static_cast<uint8_t>(m_prevPrio), /* previous lock prio */
static_cast<uint8_t>(QXK_attr_.lockPrio)); // new lock prio
QS_END_NOCRIT_()
@ -152,7 +152,7 @@ void QXMutex::unlock(void) {
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre scheduler cannot be unlocked from the ISR context
/// @pre The mutex cannot be unlocked from the ISR context
/// and the mutex must NOT be unused
Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_())
&& (m_prevPrio != static_cast<uint_fast8_t>(MUTEX_UNUSED)));
@ -164,19 +164,41 @@ void QXMutex::unlock(void) {
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(QXK_attr_.lockPrio), /* prev lock prio */
(QXK_attr_.lockPrio > p) /* the new lock prio */
? static_cast<uint8_t>(p)
: static_cast<uint8_t>(QXK_attr_.lockPrio));
if (QXK_attr_.lockPrio > p) {
QS_2U8_(static_cast<uint8_t>(QXK_attr_.lockPrio), /* prev lock */
static_cast<uint8_t>(p)); // new lock prio
}
else {
p = QXK_attr_.lockPrio;
QS_2U8_(static_cast<uint8_t>(p), /* prev lock prio */
static_cast<uint8_t>(p)); // new lock prio
}
QS_END_NOCRIT_()
if (QXK_attr_.lockPrio > p) {
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(QXK_attr_.lockPrio), /* prev lock */
static_cast<uint8_t>(p)); // new lock prio
QS_END_NOCRIT_()
QXK_attr_.lockPrio = p; // restore the previous lock prio
// find the highest-prio thread ready to run
if (QXK_sched_() != static_cast<uint_fast8_t>(0)) { // priority found?
QXK_activate_(); // activate any unlocked basic threads
}
}
else {
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
p = QXK_attr_.lockPrio;
QS_2U8_(static_cast<uint8_t>(p), /* prev lock */
static_cast<uint8_t>(p)); // new lock prio
QS_END_NOCRIT_()
}
QF_CRIT_EXIT_();
}

View File

@ -3,8 +3,8 @@
/// @ingroup qxk
/// @cond
////**************************************************************************
/// Last updated for version 5.9.5
/// Last updated on 2017-07-20
/// Last updated for version 5.9.6
/// Last updated on 2017-07-27
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -57,21 +57,30 @@ Q_DEFINE_THIS_MODULE("qxk_sema")
//****************************************************************************
/// @description
/// Initializes a semaphore with the specified count. If the semaphore is used
/// for resource sharing, the initial value of the semaphore count should be
/// set to the number of identical resources guarded by the semaphore. If the
/// semaphore is used as a signaling mechanism, the initial count should set
/// to 0.
/// Initializes a semaphore with the specified count and maximum count.
/// If the semaphore is used for resource sharing, both the initial count
/// and maximum count should be set to the number of identical resources
/// guarded by the semaphore. If the semaphore is used as a signaling
/// mechanism, the initial count should set to 0 and maximum count to 1
/// (binary semaphore).
///
/// @param[in] count initial value of the semaphore counter
///
/// @param[in] max_count maximum value of the semaphore counter.
/// The purpose of the max_count is to limit the counter
/// so that the semaphore cannot unblock more times than
/// the maximum.
/// @note
/// QXSemaphore::init() must be called **before** the semaphore can be used
/// (signaled or waited on).
///
void QXSemaphore::init(uint_fast16_t const count) {
m_count = count;
void QXSemaphore::init(uint_fast16_t const count,
uint_fast16_t const max_count)
{
Q_REQUIRE_ID(100, max_count > static_cast<uint_fast16_t>(0));
m_waitSet.setEmpty();
m_count = count;
m_max_count = max_count;
}
//****************************************************************************
@ -105,8 +114,14 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr);
Q_REQUIRE_ID(100, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
/// @pre this function must:
/// (1) NOT be called from an ISR; (2) be called from an extended thread;
/// (3) the thread must NOT be holding a mutex and
/// (4) the thread must NOT be already blocked on any object.
///
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* no lock */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked
if (m_count > static_cast<uint_fast16_t>(0)) {
@ -125,7 +140,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
QF_CRIT_ENTRY_();
// the blocking object must be this semaphore
Q_ASSERT_ID(110, thr->m_temp.obj
Q_ASSERT_ID(210, thr->m_temp.obj
== reinterpret_cast<QMState const *>(this));
thr->m_temp.obj = static_cast<QMState const *>(0); // clear
}
@ -145,11 +160,15 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
/// if the awakened thread is now the highest-priority thread that is
/// ready-to-run.
///
/// @returns true when the semaphore gets signaled and false when
/// the semaphore count exceeded the maximum.
///
/// @note
/// A semaphore can be signaled from many places, including from ISRs, basic
/// threads (AOs), and extended threads.
///
void QXSemaphore::signal(void) {
bool QXSemaphore::signal(void) {
bool signaled = true; // assume that the semaphore will be signaled
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
@ -161,8 +180,9 @@ void QXSemaphore::signal(void) {
QXThread *thr = static_cast<QXThread *>(QF::active_[p]);
// the thread must be extended and the semaphore count must be zero
Q_ASSERT_ID(210, (thr->m_osObject != static_cast<void *>(0))
&& (m_count == static_cast<uint_fast16_t>(0)));
Q_ASSERT_ID(210, (thr != static_cast<QXThread *>(0)) /* registered */
&& (thr->m_osObject != static_cast<void *>(0)) /* extended */
&& (m_count == static_cast<uint_fast16_t>(0))); // not signaled
// disarm the internal time event
(void)thr->teDisarm_();
@ -172,9 +192,16 @@ void QXSemaphore::signal(void) {
}
}
else {
++m_count;
if (m_count < m_max_count) {
++m_count;
}
else {
signaled = false; // semaphore NOT signaled
}
}
QF_CRIT_EXIT_();
return signaled;
}
} // namespace QP

View File

@ -3,8 +3,8 @@
/// @ingroup qxk
/// @cond
///***************************************************************************
/// Last updated for version 5.9.4
/// Last updated on 2017-07-05
/// Last updated for version 5.9.6
/// Last updated on 2017-07-27
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -335,8 +335,14 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks,
QF_CRIT_ENTRY_();
QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr);
/// @pre this function must:
/// (1) NOT be called from an ISR; (2) be called from an extended thread;
/// (3) the thread must NOT be holding a mutex and
/// (4) the thread must NOT be already blocked on any object.
///
Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* !locked */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked
// is the queue empty? -- block and wait for event(s)
@ -453,7 +459,7 @@ void QXThread::teArm_(enum_t const sig,
uint_fast16_t const nTicks,
uint_fast8_t const tickRate)
{
// the time event must be unused
/// @pre the time event must be unused
Q_REQUIRE_ID(700, m_timeEvt.m_ctr == static_cast<QTimeEvtCtr>(0));
m_timeEvt.sig = static_cast<QSignal>(sig);
@ -517,8 +523,16 @@ bool QXThread::delay(uint_fast16_t const nTicks,
QF_CRIT_ENTRY_();
QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr);
// the delaying thread must not be blocked on any object
Q_REQUIRE_ID(900, thr->m_temp.obj == static_cast<QMState const *>(0));
/// @pre this function must:
/// (1) NOT be called from an ISR; (2) be called from an extended thread;
/// (3) the thread must NOT be holding a mutex and
/// (4) the thread must NOT be already blocked on any object.
///
Q_REQUIRE_ID(900, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* !locked */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked
// remember the blocking object
thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_timeEvt);

View File

@ -4,8 +4,8 @@
/// @ingroup qxk
/// @cond
///***************************************************************************
/// Last updated for version 5.9.5
/// Last updated on 2017-07-19
/// Last updated for version 5.9.6
/// Last updated on 2017-07-27
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -441,6 +441,9 @@ QP::QActive *QXK_current(void) {
QF_CRIT_ENTRY_();
curr = QXK_attr_.curr;
if (curr == static_cast<QP::QActive *>(0)) { // basic thread?
curr = QP::QF::active_[QXK_attr_.actPrio];
}
QF_CRIT_EXIT_();
//! @post the current thread must be valid

View File

@ -5,8 +5,8 @@
/// @cond
///***************************************************************************
/// Product: QK/C++
/// Last updated for version 5.9.4
/// Last updated on 2017-07-05
/// Last updated for version 5.9.6
/// Last updated on 2017-07-27
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -105,7 +105,7 @@ void QXMutex::lock(void) {
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre scheduler cannot be locked from the ISR context
/// @pre The mutex cannot be locked from the ISR context
/// and the mutex must be unused
Q_REQUIRE_ID(700, (!QXK_ISR_CONTEXT_())
&& (m_prevPrio == static_cast<uint_fast8_t>(MUTEX_UNUSED)));
@ -124,7 +124,7 @@ void QXMutex::lock(void) {
QS_BEGIN_NOCRIT_(QS_SCHED_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(m_prevPrio), /* previouis lock prio */
QS_2U8_(static_cast<uint8_t>(m_prevPrio), /* previous lock prio */
static_cast<uint8_t>(QXK_attr_.lockPrio)); // new lock prio
QS_END_NOCRIT_()
@ -152,7 +152,7 @@ void QXMutex::unlock(void) {
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre scheduler cannot be unlocked from the ISR context
/// @pre The mutex cannot be unlocked from the ISR context
/// and the mutex must NOT be unused
Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_())
&& (m_prevPrio != static_cast<uint_fast8_t>(MUTEX_UNUSED)));
@ -164,19 +164,41 @@ void QXMutex::unlock(void) {
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(QXK_attr_.lockPrio), /* prev lock prio */
(QXK_attr_.lockPrio > p) /* the new lock prio */
? static_cast<uint8_t>(p)
: static_cast<uint8_t>(QXK_attr_.lockPrio));
if (QXK_attr_.lockPrio > p) {
QS_2U8_(static_cast<uint8_t>(QXK_attr_.lockPrio), /* prev lock */
static_cast<uint8_t>(p)); // new lock prio
}
else {
p = QXK_attr_.lockPrio;
QS_2U8_(static_cast<uint8_t>(p), /* prev lock prio */
static_cast<uint8_t>(p)); // new lock prio
}
QS_END_NOCRIT_()
if (QXK_attr_.lockPrio > p) {
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(QXK_attr_.lockPrio), /* prev lock */
static_cast<uint8_t>(p)); // new lock prio
QS_END_NOCRIT_()
QXK_attr_.lockPrio = p; // restore the previous lock prio
// find the highest-prio thread ready to run
if (QXK_sched_() != static_cast<uint_fast8_t>(0)) { // priority found?
QXK_activate_(); // activate any unlocked basic threads
}
}
else {
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
p = QXK_attr_.lockPrio;
QS_2U8_(static_cast<uint8_t>(p), /* prev lock */
static_cast<uint8_t>(p)); // new lock prio
QS_END_NOCRIT_()
}
QF_CRIT_EXIT_();
}

View File

@ -3,8 +3,8 @@
/// @ingroup qxk
/// @cond
////**************************************************************************
/// Last updated for version 5.9.5
/// Last updated on 2017-07-20
/// Last updated for version 5.9.6
/// Last updated on 2017-07-27
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -57,21 +57,30 @@ Q_DEFINE_THIS_MODULE("qxk_sema")
//****************************************************************************
/// @description
/// Initializes a semaphore with the specified count. If the semaphore is used
/// for resource sharing, the initial value of the semaphore count should be
/// set to the number of identical resources guarded by the semaphore. If the
/// semaphore is used as a signaling mechanism, the initial count should set
/// to 0.
/// Initializes a semaphore with the specified count and maximum count.
/// If the semaphore is used for resource sharing, both the initial count
/// and maximum count should be set to the number of identical resources
/// guarded by the semaphore. If the semaphore is used as a signaling
/// mechanism, the initial count should set to 0 and maximum count to 1
/// (binary semaphore).
///
/// @param[in] count initial value of the semaphore counter
///
/// @param[in] max_count maximum value of the semaphore counter.
/// The purpose of the max_count is to limit the counter
/// so that the semaphore cannot unblock more times than
/// the maximum.
/// @note
/// QXSemaphore::init() must be called **before** the semaphore can be used
/// (signaled or waited on).
///
void QXSemaphore::init(uint_fast16_t const count) {
m_count = count;
void QXSemaphore::init(uint_fast16_t const count,
uint_fast16_t const max_count)
{
Q_REQUIRE_ID(100, max_count > static_cast<uint_fast16_t>(0));
m_waitSet.setEmpty();
m_count = count;
m_max_count = max_count;
}
//****************************************************************************
@ -105,8 +114,14 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr);
Q_REQUIRE_ID(100, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
/// @pre this function must:
/// (1) NOT be called from an ISR; (2) be called from an extended thread;
/// (3) the thread must NOT be holding a mutex and
/// (4) the thread must NOT be already blocked on any object.
///
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* no lock */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked
if (m_count > static_cast<uint_fast16_t>(0)) {
@ -125,7 +140,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
QF_CRIT_ENTRY_();
// the blocking object must be this semaphore
Q_ASSERT_ID(110, thr->m_temp.obj
Q_ASSERT_ID(210, thr->m_temp.obj
== reinterpret_cast<QMState const *>(this));
thr->m_temp.obj = static_cast<QMState const *>(0); // clear
}
@ -145,11 +160,15 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
/// if the awakened thread is now the highest-priority thread that is
/// ready-to-run.
///
/// @returns true when the semaphore gets signaled and false when
/// the semaphore count exceeded the maximum.
///
/// @note
/// A semaphore can be signaled from many places, including from ISRs, basic
/// threads (AOs), and extended threads.
///
void QXSemaphore::signal(void) {
bool QXSemaphore::signal(void) {
bool signaled = true; // assume that the semaphore will be signaled
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
@ -161,8 +180,9 @@ void QXSemaphore::signal(void) {
QXThread *thr = static_cast<QXThread *>(QF::active_[p]);
// the thread must be extended and the semaphore count must be zero
Q_ASSERT_ID(210, (thr->m_osObject != static_cast<void *>(0))
&& (m_count == static_cast<uint_fast16_t>(0)));
Q_ASSERT_ID(210, (thr != static_cast<QXThread *>(0)) /* registered */
&& (thr->m_osObject != static_cast<void *>(0)) /* extended */
&& (m_count == static_cast<uint_fast16_t>(0))); // not signaled
// disarm the internal time event
(void)thr->teDisarm_();
@ -172,9 +192,16 @@ void QXSemaphore::signal(void) {
}
}
else {
++m_count;
if (m_count < m_max_count) {
++m_count;
}
else {
signaled = false; // semaphore NOT signaled
}
}
QF_CRIT_EXIT_();
return signaled;
}
} // namespace QP

View File

@ -3,8 +3,8 @@
/// @ingroup qxk
/// @cond
///***************************************************************************
/// Last updated for version 5.9.4
/// Last updated on 2017-07-05
/// Last updated for version 5.9.6
/// Last updated on 2017-07-27
///
/// Q u a n t u m L e a P s
/// ---------------------------
@ -335,8 +335,14 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks,
QF_CRIT_ENTRY_();
QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr);
/// @pre this function must:
/// (1) NOT be called from an ISR; (2) be called from an extended thread;
/// (3) the thread must NOT be holding a mutex and
/// (4) the thread must NOT be already blocked on any object.
///
Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* !locked */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked
// is the queue empty? -- block and wait for event(s)
@ -453,7 +459,7 @@ void QXThread::teArm_(enum_t const sig,
uint_fast16_t const nTicks,
uint_fast8_t const tickRate)
{
// the time event must be unused
/// @pre the time event must be unused
Q_REQUIRE_ID(700, m_timeEvt.m_ctr == static_cast<QTimeEvtCtr>(0));
m_timeEvt.sig = static_cast<QSignal>(sig);
@ -517,8 +523,16 @@ bool QXThread::delay(uint_fast16_t const nTicks,
QF_CRIT_ENTRY_();
QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr);
// the delaying thread must not be blocked on any object
Q_REQUIRE_ID(900, thr->m_temp.obj == static_cast<QMState const *>(0));
/// @pre this function must:
/// (1) NOT be called from an ISR; (2) be called from an extended thread;
/// (3) the thread must NOT be holding a mutex and
/// (4) the thread must NOT be already blocked on any object.
///
Q_REQUIRE_ID(900, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* !locked */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked
// remember the blocking object
thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_timeEvt);