This commit is contained in:
Quantum Leaps 2017-08-21 18:21:15 -04:00
parent 4098f977b3
commit f94afe12dc
100 changed files with 25600 additions and 17356 deletions

View File

@ -0,0 +1,121 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_common_tables.h
* Description: Extern declaration for common tables
*
* $Date: 27. January 2017
* $Revision: V.1.5.1
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _ARM_COMMON_TABLES_H
#define _ARM_COMMON_TABLES_H
#include "arm_math.h"
extern const uint16_t armBitRevTable[1024];
extern const q15_t armRecipTableQ15[64];
extern const q31_t armRecipTableQ31[64];
extern const float32_t twiddleCoef_16[32];
extern const float32_t twiddleCoef_32[64];
extern const float32_t twiddleCoef_64[128];
extern const float32_t twiddleCoef_128[256];
extern const float32_t twiddleCoef_256[512];
extern const float32_t twiddleCoef_512[1024];
extern const float32_t twiddleCoef_1024[2048];
extern const float32_t twiddleCoef_2048[4096];
extern const float32_t twiddleCoef_4096[8192];
#define twiddleCoef twiddleCoef_4096
extern const q31_t twiddleCoef_16_q31[24];
extern const q31_t twiddleCoef_32_q31[48];
extern const q31_t twiddleCoef_64_q31[96];
extern const q31_t twiddleCoef_128_q31[192];
extern const q31_t twiddleCoef_256_q31[384];
extern const q31_t twiddleCoef_512_q31[768];
extern const q31_t twiddleCoef_1024_q31[1536];
extern const q31_t twiddleCoef_2048_q31[3072];
extern const q31_t twiddleCoef_4096_q31[6144];
extern const q15_t twiddleCoef_16_q15[24];
extern const q15_t twiddleCoef_32_q15[48];
extern const q15_t twiddleCoef_64_q15[96];
extern const q15_t twiddleCoef_128_q15[192];
extern const q15_t twiddleCoef_256_q15[384];
extern const q15_t twiddleCoef_512_q15[768];
extern const q15_t twiddleCoef_1024_q15[1536];
extern const q15_t twiddleCoef_2048_q15[3072];
extern const q15_t twiddleCoef_4096_q15[6144];
extern const float32_t twiddleCoef_rfft_32[32];
extern const float32_t twiddleCoef_rfft_64[64];
extern const float32_t twiddleCoef_rfft_128[128];
extern const float32_t twiddleCoef_rfft_256[256];
extern const float32_t twiddleCoef_rfft_512[512];
extern const float32_t twiddleCoef_rfft_1024[1024];
extern const float32_t twiddleCoef_rfft_2048[2048];
extern const float32_t twiddleCoef_rfft_4096[4096];
/* floating-point bit reversal tables */
#define ARMBITREVINDEXTABLE_16_TABLE_LENGTH ((uint16_t)20)
#define ARMBITREVINDEXTABLE_32_TABLE_LENGTH ((uint16_t)48)
#define ARMBITREVINDEXTABLE_64_TABLE_LENGTH ((uint16_t)56)
#define ARMBITREVINDEXTABLE_128_TABLE_LENGTH ((uint16_t)208)
#define ARMBITREVINDEXTABLE_256_TABLE_LENGTH ((uint16_t)440)
#define ARMBITREVINDEXTABLE_512_TABLE_LENGTH ((uint16_t)448)
#define ARMBITREVINDEXTABLE_1024_TABLE_LENGTH ((uint16_t)1800)
#define ARMBITREVINDEXTABLE_2048_TABLE_LENGTH ((uint16_t)3808)
#define ARMBITREVINDEXTABLE_4096_TABLE_LENGTH ((uint16_t)4032)
extern const uint16_t armBitRevIndexTable16[ARMBITREVINDEXTABLE_16_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable32[ARMBITREVINDEXTABLE_32_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable64[ARMBITREVINDEXTABLE_64_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable128[ARMBITREVINDEXTABLE_128_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable256[ARMBITREVINDEXTABLE_256_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable512[ARMBITREVINDEXTABLE_512_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable1024[ARMBITREVINDEXTABLE_1024_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable2048[ARMBITREVINDEXTABLE_2048_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable4096[ARMBITREVINDEXTABLE_4096_TABLE_LENGTH];
/* fixed-point bit reversal tables */
#define ARMBITREVINDEXTABLE_FIXED_16_TABLE_LENGTH ((uint16_t)12)
#define ARMBITREVINDEXTABLE_FIXED_32_TABLE_LENGTH ((uint16_t)24)
#define ARMBITREVINDEXTABLE_FIXED_64_TABLE_LENGTH ((uint16_t)56)
#define ARMBITREVINDEXTABLE_FIXED_128_TABLE_LENGTH ((uint16_t)112)
#define ARMBITREVINDEXTABLE_FIXED_256_TABLE_LENGTH ((uint16_t)240)
#define ARMBITREVINDEXTABLE_FIXED_512_TABLE_LENGTH ((uint16_t)480)
#define ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH ((uint16_t)992)
#define ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH ((uint16_t)1984)
#define ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH ((uint16_t)4032)
extern const uint16_t armBitRevIndexTable_fixed_16[ARMBITREVINDEXTABLE_FIXED_16_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable_fixed_32[ARMBITREVINDEXTABLE_FIXED_32_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable_fixed_64[ARMBITREVINDEXTABLE_FIXED_64_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable_fixed_128[ARMBITREVINDEXTABLE_FIXED_128_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable_fixed_256[ARMBITREVINDEXTABLE_FIXED_256_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable_fixed_512[ARMBITREVINDEXTABLE_FIXED_512_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable_fixed_1024[ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable_fixed_2048[ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable_fixed_4096[ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH];
/* Tables for Fast Math Sine and Cosine */
extern const float32_t sinTable_f32[FAST_MATH_TABLE_SIZE + 1];
extern const q31_t sinTable_q31[FAST_MATH_TABLE_SIZE + 1];
extern const q15_t sinTable_q15[FAST_MATH_TABLE_SIZE + 1];
#endif /* ARM_COMMON_TABLES_H */

View File

@ -0,0 +1,66 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_const_structs.h
* Description: Constant structs that are initialized for user convenience.
* For example, some can be given as arguments to the arm_cfft_f32() function.
*
* $Date: 27. January 2017
* $Revision: V.1.5.1
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _ARM_CONST_STRUCTS_H
#define _ARM_CONST_STRUCTS_H
#include "arm_math.h"
#include "arm_common_tables.h"
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048;
extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048;
extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096;
#endif

7257
3rd_party/CMSIS/Include/arm_math.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -73,6 +73,9 @@
#ifndef __PACKED_STRUCT #ifndef __PACKED_STRUCT
#define __PACKED_STRUCT __packed struct #define __PACKED_STRUCT __packed struct
#endif #endif
#ifndef __PACKED_UNION
#define __PACKED_UNION __packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */ #ifndef __UNALIGNED_UINT32 /* deprecated */
#define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x))) #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
#endif #endif
@ -91,7 +94,9 @@
#ifndef __ALIGNED #ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x))) #define __ALIGNED(x) __attribute__((aligned(x)))
#endif #endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
/* ########################### Core Function Access ########################### */ /* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface /** \ingroup CMSIS_Core_FunctionInterface

View File

@ -22,7 +22,7 @@
* limitations under the License. * limitations under the License.
*/ */
//lint -esym(9058, IRQn) disable MISRA 2012 Rule 2.4 for IRQn /*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */
#ifndef __CMSIS_ARMCLANG_H #ifndef __CMSIS_ARMCLANG_H
#define __CMSIS_ARMCLANG_H #define __CMSIS_ARMCLANG_H
@ -56,10 +56,13 @@
#ifndef __PACKED_STRUCT #ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
#endif #endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */ #ifndef __UNALIGNED_UINT32 /* deprecated */
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpacked" #pragma clang diagnostic ignored "-Wpacked"
//lint -esym(9058, T_UINT32) disable MISRA 2012 Rule 2.4 for T_UINT32 /*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */
struct __attribute__((packed)) T_UINT32 { uint32_t v; }; struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#pragma clang diagnostic pop #pragma clang diagnostic pop
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
@ -67,7 +70,7 @@
#ifndef __UNALIGNED_UINT16_WRITE #ifndef __UNALIGNED_UINT16_WRITE
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpacked" #pragma clang diagnostic ignored "-Wpacked"
//lint -esym(9058, T_UINT16_WRITE) disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE /*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#pragma clang diagnostic pop #pragma clang diagnostic pop
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
@ -75,7 +78,7 @@
#ifndef __UNALIGNED_UINT16_READ #ifndef __UNALIGNED_UINT16_READ
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpacked" #pragma clang diagnostic ignored "-Wpacked"
//lint -esym(9058, T_UINT16_READ) disable MISRA 2012 Rule 2.4 for T_UINT16_READ /*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
__PACKED_STRUCT T_UINT16_READ { uint16_t v; }; __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#pragma clang diagnostic pop #pragma clang diagnostic pop
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
@ -83,7 +86,7 @@
#ifndef __UNALIGNED_UINT32_WRITE #ifndef __UNALIGNED_UINT32_WRITE
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpacked" #pragma clang diagnostic ignored "-Wpacked"
//lint -esym(9058, T_UINT32_WRITE) disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE /*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#pragma clang diagnostic pop #pragma clang diagnostic pop
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
@ -91,6 +94,7 @@
#ifndef __UNALIGNED_UINT32_READ #ifndef __UNALIGNED_UINT32_READ
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpacked" #pragma clang diagnostic ignored "-Wpacked"
/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */
__PACKED_STRUCT T_UINT32_READ { uint32_t v; }; __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#pragma clang diagnostic pop #pragma clang diagnostic pop
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
@ -98,6 +102,9 @@
#ifndef __ALIGNED #ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x))) #define __ALIGNED(x) __attribute__((aligned(x)))
#endif #endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
/* ########################### Core Function Access ########################### */ /* ########################### Core Function Access ########################### */

View File

@ -44,11 +44,12 @@
// //
// v5e, v6, Cortex-M3, Cortex-M4, Cortex-R4, and Cortex-A8 compiler intrinsics // v5e, v6, Cortex-M3, Cortex-M4, Cortex-R4, and Cortex-A8 compiler intrinsics
// //
#define __CLZ _norm #define __CLZ _norm
#define __SXTB _sxtb #define __SXTB _sxtb
#define __SXTH _sxth #define __SXTH _sxth
#define __UXTB _uxtb #define __UXTB _uxtb
#define __UXTH _uxth #define __UXTH _uxth
// CCS supports intrinsics to take advantage of the shift operand left/right // CCS supports intrinsics to take advantage of the shift operand left/right
// before saturation extension of SSAT, but CMSIS does not take advantage // 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 // of those, so tell the compiler to use a sat & shift left with a shift
@ -78,6 +79,8 @@
#define __ISB _isb #define __ISB _isb
#define __WFI() __asm(" wfi")
#elif (__TI_COMPILER_VERSION__ >= 4009000) #elif (__TI_COMPILER_VERSION__ >= 4009000)
#define __enable_fault_irq _enable_interrupts #define __enable_fault_irq _enable_interrupts
@ -88,10 +91,12 @@ __attribute__( ( always_inline ) ) static inline void __nop(void)
{ {
__asm(" nop"); __asm(" nop");
} }
__attribute__( ( always_inline ) ) static inline void __NOP(void) __attribute__( ( always_inline ) ) static inline void __NOP(void)
{ {
__asm(" nop"); __asm(" nop");
} }
// Data Synchronization Barrier // Data Synchronization Barrier
__attribute__( ( always_inline ) ) static inline void __DSB(void) __attribute__( ( always_inline ) ) static inline void __DSB(void)
{ {
@ -103,6 +108,11 @@ __attribute__( ( always_inline ) ) static inline void __ISB(void)
__asm(" isb"); __asm(" isb");
} }
__attribute__( ( always_inline ) ) static inline void __WFI(void)
{
__asm(" wfi");
}
#endif /*__TI_COMPILER_VERSION__ version*/ #endif /*__TI_COMPILER_VERSION__ version*/
#endif /*__TI_COMPILER_VERSION__*/ #endif /*__TI_COMPILER_VERSION__*/
@ -112,15 +122,15 @@ __attribute__( ( always_inline ) ) static inline void __ISB(void)
// //
#define __ROR __ror #define __ROR __ror
#define __SXTB16(src) _sxtb16((src),0) #define __SXTB16(src) _sxtb16((src),0)
#define __QADD _sadd #define __QADD _sadd
#define __QDADD _sdadd #define __QDADD _sdadd
#define __QDSUB _sdsub #define __QDSUB _sdsub
#define __SMLABB _smlabb #define __SMLABB _smlabb
#define __SMLABT _smlabt #define __SMLABT _smlabt
#define __SMLALBB _smlalbb #define __SMLALBB _smlalbb
#define __SMLALBT _smlalbt #define __SMLALBT _smlalbt
#define __SMLALTB _smlaltb #define __SMLALTB _smlaltb
#define __SMLALTT _smlaltt #define __SMLALTT _smlaltt
#define __SMLATB _smlatb #define __SMLATB _smlatb
#define __SMLATT _smlatt #define __SMLATT _smlatt
#define __SMLAWB _smlawb #define __SMLAWB _smlawb
@ -132,77 +142,77 @@ __attribute__( ( always_inline ) ) static inline void __ISB(void)
#define __SMULTT _smultt #define __SMULTT _smultt
#define __SMULWB _smulwb #define __SMULWB _smulwb
#define __SMULWT _smulwt #define __SMULWT _smulwt
#define __QSUB _ssub #define __QSUB _ssub
#define __SUBC _subc #define __SUBC _subc
// //
// v6, Cortex-M4, Cortex-R4, and Cortex-A8 compiler intrinsics // v6, Cortex-M4, Cortex-R4, and Cortex-A8 compiler intrinsics
// //
#define __SHASX _shaddsubx #define __SHASX _shaddsubx
#define __SHSAX _shsubaddx #define __SHSAX _shsubaddx
#define __PKHBT _pkhbt #define __PKHBT _pkhbt
#define __PKHTB _pkhtb #define __PKHTB _pkhtb
#define __QADD16 _qadd16 #define __QADD16 _qadd16
#define __QADD8 _qadd8 #define __QADD8 _qadd8
#define __QSUB16 _qsub16 #define __QSUB16 _qsub16
#define __QSUB8 _qsub8 #define __QSUB8 _qsub8
#define __QASX _saddsubx #define __QASX _saddsubx
#define __QSAX _qsubaddx #define __QSAX _qsubaddx
#define __SADD16 _sadd16 #define __SADD16 _sadd16
#define __SADD8 _sadd8 #define __SADD8 _sadd8
#define __SASX _saddsubx #define __SASX _saddsubx
#define __SEL _sel #define __SEL _sel
#define __SHADD16 _shadd16 #define __SHADD16 _shadd16
#define __SHADD8 _shadd8 #define __SHADD8 _shadd8
#define __SHSUB16 _shsub16 #define __SHSUB16 _shsub16
#define __SHSUB8 _shsub8 #define __SHSUB8 _shsub8
#define __SMLAD _smlad #define __SMLAD _smlad
#define __SMLADX _smladx #define __SMLADX _smladx
#define __SMLALD(src1, src2, accumulator) _smlald(accumulator, src1, src2) #define __SMLALD(src1, src2, accumulator) _smlald(accumulator, src1, src2)
#define __SMLALDX _smlaldx #define __SMLALDX _smlaldx
#define __SMLSD _smlsd #define __SMLSD _smlsd
#define __SMLSDX _smlsdx #define __SMLSDX _smlsdx
#define __SMLSLD _smlsld #define __SMLSLD _smlsld
#define __SMLSLDX _smlsldx #define __SMLSLDX _smlsldx
#define __SMMLA _smmla #define __SMMLA _smmla
#define __SMMLAR _smmlar #define __SMMLAR _smmlar
#define __SMMLS _smmls #define __SMMLS _smmls
#define __SMMLSR _smmlsr #define __SMMLSR _smmlsr
#define __SMMUL _smmul #define __SMMUL _smmul
#define __SMMULR _smmulr #define __SMMULR _smmulr
#define __SMUAD _smuad #define __SMUAD _smuad
#define __SMUADX _smuadx #define __SMUADX _smuadx
#define __SMUSD _smusd #define __SMUSD _smusd
#define __SMUSDX _smusdx #define __SMUSDX _smusdx
#define __SSAT16 _ssat16 #define __SSAT16 _ssat16
#define __SSUB16 _ssub16 #define __SSUB16 _ssub16
#define __SSUB8 _ssub8 #define __SSUB8 _ssub8
#define __SSAX _ssubaddx #define __SSAX _ssubaddx
#define __SXTAB _sxtab #define __SXTAB _sxtab
#define __SXTAB16 _sxtab16 #define __SXTAB16 _sxtab16
#define __SXTAH _sxtah #define __SXTAH _sxtah
#define __UMAAL _umaal #define __UMAAL _umaal
#define __UADD16 _uadd16 #define __UADD16 _uadd16
#define __UADD8 _uadd8 #define __UADD8 _uadd8
#define __UHADD16 _uhadd16 #define __UHADD16 _uhadd16
#define __UHADD8 _uhadd8 #define __UHADD8 _uhadd8
#define __UASX _uaddsubx #define __UASX _uaddsubx
#define __UHSUB16 _uhsub16 #define __UHSUB16 _uhsub16
#define __UHSUB8 _uhsub8 #define __UHSUB8 _uhsub8
#define __UQADD16 _uqadd16 #define __UQADD16 _uqadd16
#define __UQADD8 _uqadd8 #define __UQADD8 _uqadd8
#define __UQASX _uqaddsubx #define __UQASX _uqaddsubx
#define __UQSUB16 _uqsub16 #define __UQSUB16 _uqsub16
#define __UQSUB8 _uqsub8 #define __UQSUB8 _uqsub8
#define __UQSAX _uqsubaddx #define __UQSAX _uqsubaddx
#define __USAD8 _usad8 #define __USAD8 _usad8
#define __USAT16 _usat16 #define __USAT16 _usat16
#define __USUB16 _usub16 #define __USUB16 _usub16
#define __USUB8 _usub8 #define __USUB8 _usub8
#define __USAX _usubaddx #define __USAX _usubaddx
#define __UXTAB _uxtab #define __UXTAB _uxtab
#define __UXTAB16 _uxtab16 #define __UXTAB16 _uxtab16
#define __UXTAH _uxtah #define __UXTAH _uxtah
#define __UXTB16 _uxtb16 #define __UXTB16 _uxtb16
#endif /*__TI_TMS470_V7M4__*/ #endif /*__TI_TMS470_V7M4__*/

View File

@ -53,6 +53,7 @@
*/ */
#elif defined ( __ICCARM__ ) #elif defined ( __ICCARM__ )
#ifndef __ASM #ifndef __ASM
#define __ASM __asm #define __ASM __asm
#endif #endif
@ -65,6 +66,21 @@
#include <cmsis_iar.h> #include <cmsis_iar.h>
/* CMSIS compiler control architecture macros */
#if (__CORE__ == __ARM6M__) || (__CORE__ == __ARM6SM__)
#ifndef __ARM_ARCH_6M__
#define __ARM_ARCH_6M__ 1
#endif
#elif (__CORE__ == __ARM7M__)
#ifndef __ARM_ARCH_7M__
#define __ARM_ARCH_7M__ 1
#endif
#elif (__CORE__ == __ARM7EM__)
#ifndef __ARM_ARCH_7EM__
#define __ARM_ARCH_7EM__ 1
#endif
#endif
#ifndef __NO_RETURN #ifndef __NO_RETURN
#define __NO_RETURN __noreturn #define __NO_RETURN __noreturn
#endif #endif
@ -80,6 +96,9 @@
#ifndef __PACKED_STRUCT #ifndef __PACKED_STRUCT
#define __PACKED_STRUCT __packed struct #define __PACKED_STRUCT __packed struct
#endif #endif
#ifndef __PACKED_UNION
#define __PACKED_UNION __packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */ #ifndef __UNALIGNED_UINT32 /* deprecated */
__packed struct T_UINT32 { uint32_t v; }; __packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
@ -104,6 +123,32 @@
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x) #define __ALIGNED(x)
#endif #endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
// Workaround for missing __CLZ intrinsic in
// various versions of the IAR compilers.
// __IAR_FEATURE_CLZ__ should be defined by
// the compiler that supports __CLZ internally.
#if (defined (__ARM_ARCH_6M__)) && (__ARM_ARCH_6M__ == 1) && (!defined (__IAR_FEATURE_CLZ__))
__STATIC_INLINE uint32_t __CLZ(uint32_t data)
{
if (data == 0u) { return 32u; }
uint32_t count = 0;
uint32_t mask = 0x80000000;
while ((data & mask) == 0)
{
count += 1u;
mask = mask >> 1u;
}
return (count);
}
#endif
/* /*
@ -136,6 +181,9 @@
#ifndef __PACKED_STRUCT #ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed)) #define __PACKED_STRUCT struct __attribute__((packed))
#endif #endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */ #ifndef __UNALIGNED_UINT32 /* deprecated */
struct __attribute__((packed)) T_UINT32 { uint32_t v; }; struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
@ -159,6 +207,10 @@
#ifndef __ALIGNED #ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x))) #define __ALIGNED(x) __attribute__((aligned(x)))
#endif #endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
/* /*
@ -195,6 +247,9 @@
#ifndef __PACKED_STRUCT #ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __packed__ #define __PACKED_STRUCT struct __packed__
#endif #endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __packed__
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */ #ifndef __UNALIGNED_UINT32 /* deprecated */
struct __packed__ T_UINT32 { uint32_t v; }; struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
@ -218,6 +273,10 @@
#ifndef __ALIGNED #ifndef __ALIGNED
#define __ALIGNED(x) __align(x) #define __ALIGNED(x) __align(x)
#endif #endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
/* /*
@ -252,6 +311,9 @@
#ifndef __PACKED_STRUCT #ifndef __PACKED_STRUCT
#define __PACKED_STRUCT @packed struct #define __PACKED_STRUCT @packed struct
#endif #endif
#ifndef __PACKED_UNION
#define __PACKED_UNION @packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */ #ifndef __UNALIGNED_UINT32 /* deprecated */
@packed struct T_UINT32 { uint32_t v; }; @packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
@ -276,6 +338,10 @@
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x) #define __ALIGNED(x)
#endif #endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#else #else

View File

@ -31,6 +31,11 @@
#pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
/* Fallback for __has_builtin */
#ifndef __has_builtin
#define __has_builtin(x) (0)
#endif
/* CMSIS compiler specific defines */ /* CMSIS compiler specific defines */
#ifndef __ASM #ifndef __ASM
#define __ASM __asm #define __ASM __asm
@ -56,6 +61,9 @@
#ifndef __PACKED_STRUCT #ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
#endif #endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */ #ifndef __UNALIGNED_UINT32 /* deprecated */
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked" #pragma GCC diagnostic ignored "-Wpacked"
@ -99,6 +107,9 @@
#ifndef __ALIGNED #ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x))) #define __ALIGNED(x) __attribute__((aligned(x)))
#endif #endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
/* ########################### Core Function Access ########################### */ /* ########################### Core Function Access ########################### */
@ -694,12 +705,17 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void)
{ {
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) ) (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
#if __has_builtin(__builtin_arm_get_fpscr) || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
/* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
return __builtin_arm_get_fpscr();
#else
uint32_t result; uint32_t result;
__ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
return(result); return(result);
#endif
#else #else
return(0U); return(0U);
#endif #endif
} }
@ -713,7 +729,12 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{ {
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) ) (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
#if __has_builtin(__builtin_arm_set_fpscr) || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
/* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
__builtin_arm_set_fpscr(fpscr);
#else
__ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory");
#endif
#else #else
(void)fpscr; (void)fpscr;
#endif #endif

39
3rd_party/CMSIS/Include/cmsis_version.h vendored Normal file
View File

@ -0,0 +1,39 @@
/**************************************************************************//**
* @file cmsis_version.h
* @brief CMSIS Core(M) Version definitions
* @version V5.0.2
* @date 19. April 2017
******************************************************************************/
/*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CMSIS_VERSION_H
#define __CMSIS_VERSION_H
/* CMSIS Version definitions */
#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
#define __CM_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS Core(M) sub version */
#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
__CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
#endif

View File

@ -2,7 +2,7 @@
* @file core_armv8mbl.h * @file core_armv8mbl.h
* @brief CMSIS ARMv8MBL Core Peripheral Access Layer Header File * @brief CMSIS ARMv8MBL Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
/* CMSIS cmGrebe definitions */ #include "cmsis_version.h"
#define __ARMv8MBL_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */
#define __ARMv8MBL_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ /* CMSIS definitions */
#define __ARMv8MBL_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __ARMv8MBL_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __ARMv8MBL_CMSIS_VERSION ((__ARMv8MBL_CMSIS_VERSION_MAIN << 16U) | \ #define __ARMv8MBL_CMSIS_VERSION ((__ARMv8MBL_CMSIS_VERSION_MAIN << 16U) | \
__ARMv8MBL_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __ARMv8MBL_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M ( 2U) /*!< Cortex-M Core */ #define __CORTEX_M ( 2U) /*!< Cortex-M Core */

View File

@ -2,7 +2,7 @@
* @file core_armv8mml.h * @file core_armv8mml.h
* @brief CMSIS ARMv8MML Core Peripheral Access Layer Header File * @brief CMSIS ARMv8MML Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
#include "cmsis_version.h"
/* CMSIS ARMv8MML definitions */ /* CMSIS ARMv8MML definitions */
#define __ARMv8MML_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ #define __ARMv8MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __ARMv8MML_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ #define __ARMv8MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __ARMv8MML_CMSIS_VERSION ((__ARMv8MML_CMSIS_VERSION_MAIN << 16U) | \ #define __ARMv8MML_CMSIS_VERSION ((__ARMv8MML_CMSIS_VERSION_MAIN << 16U) | \
__ARMv8MML_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __ARMv8MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M (81U) /*!< Cortex-M Core */ #define __CORTEX_M (81U) /*!< Cortex-M Core */
@ -480,7 +482,7 @@ typedef struct
uint32_t RESERVED4[15U]; uint32_t RESERVED4[15U];
__IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
__IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
__IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
uint32_t RESERVED5[1U]; uint32_t RESERVED5[1U];
__OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
uint32_t RESERVED6[1U]; uint32_t RESERVED6[1U];

View File

@ -2,7 +2,7 @@
* @file core_cm0.h * @file core_cm0.h
* @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
#include "cmsis_version.h"
/* CMSIS CM0 definitions */ /* CMSIS CM0 definitions */
#define __CM0_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ #define __CM0_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __CM0_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ #define __CM0_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \ #define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \
__CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __CM0_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M (0U) /*!< Cortex-M Core */ #define __CORTEX_M (0U) /*!< Cortex-M Core */

View File

@ -2,7 +2,7 @@
* @file core_cm0plus.h * @file core_cm0plus.h
* @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
#include "cmsis_version.h"
/* CMSIS CM0+ definitions */ /* CMSIS CM0+ definitions */
#define __CM0PLUS_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ #define __CM0PLUS_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __CM0PLUS_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ #define __CM0PLUS_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16U) | \ #define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16U) | \
__CM0PLUS_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __CM0PLUS_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M (0U) /*!< Cortex-M Core */ #define __CORTEX_M (0U) /*!< Cortex-M Core */
@ -932,6 +934,13 @@ __STATIC_INLINE void __NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */ /*@} end of CMSIS_Core_NVICFunctions */
/* ########################## MPU functions #################################### */
#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
#include "mpu_armv7.h"
#endif
/* ########################## FPU functions #################################### */ /* ########################## FPU functions #################################### */
/** /**

View File

@ -2,7 +2,7 @@
* @file core_cm23.h * @file core_cm23.h
* @brief CMSIS Cortex-M23 Core Peripheral Access Layer Header File * @brief CMSIS Cortex-M23 Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
/* CMSIS cmGrebe definitions */ #include "cmsis_version.h"
#define __CM23_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */
#define __CM23_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ /* CMSIS definitions */
#define __CM23_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __CM23_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM23_CMSIS_VERSION ((__CM23_CMSIS_VERSION_MAIN << 16U) | \ #define __CM23_CMSIS_VERSION ((__CM23_CMSIS_VERSION_MAIN << 16U) | \
__CM23_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __CM23_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M (23U) /*!< Cortex-M Core */ #define __CORTEX_M (23U) /*!< Cortex-M Core */

View File

@ -2,7 +2,7 @@
* @file core_cm3.h * @file core_cm3.h
* @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
#include "cmsis_version.h"
/* CMSIS CM3 definitions */ /* CMSIS CM3 definitions */
#define __CM3_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ #define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __CM3_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ #define __CM3_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \ #define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \
__CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __CM3_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M (3U) /*!< Cortex-M Core */ #define __CORTEX_M (3U) /*!< Cortex-M Core */
@ -1761,6 +1763,13 @@ __STATIC_INLINE void __NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */ /*@} end of CMSIS_Core_NVICFunctions */
/* ########################## MPU functions #################################### */
#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
#include "mpu_armv7.h"
#endif
/* ########################## FPU functions #################################### */ /* ########################## FPU functions #################################### */
/** /**

View File

@ -2,7 +2,7 @@
* @file core_cm33.h * @file core_cm33.h
* @brief CMSIS Cortex-M33 Core Peripheral Access Layer Header File * @brief CMSIS Cortex-M33 Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
#include "cmsis_version.h"
/* CMSIS CM33 definitions */ /* CMSIS CM33 definitions */
#define __CM33_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ #define __CM33_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __CM33_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ #define __CM33_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM33_CMSIS_VERSION ((__CM33_CMSIS_VERSION_MAIN << 16U) | \ #define __CM33_CMSIS_VERSION ((__CM33_CMSIS_VERSION_MAIN << 16U) | \
__CM33_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __CM33_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M (33U) /*!< Cortex-M Core */ #define __CORTEX_M (33U) /*!< Cortex-M Core */
@ -480,7 +482,7 @@ typedef struct
uint32_t RESERVED4[15U]; uint32_t RESERVED4[15U];
__IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
__IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
__IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
uint32_t RESERVED5[1U]; uint32_t RESERVED5[1U];
__OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
uint32_t RESERVED6[1U]; uint32_t RESERVED6[1U];

View File

@ -2,7 +2,7 @@
* @file core_cm4.h * @file core_cm4.h
* @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
/* CMSIS CM4 definitions */ #include "cmsis_version.h"
#define __CM4_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */
#define __CM4_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ /* CMSIS CM4 definitions */
#define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ #define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \
__CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M (4U) /*!< Cortex-M Core */ #define __CORTEX_M (4U) /*!< Cortex-M Core */
@ -1935,6 +1937,14 @@ __STATIC_INLINE void __NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */ /*@} end of CMSIS_Core_NVICFunctions */
/* ########################## MPU functions #################################### */
#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
#include "mpu_armv7.h"
#endif
/* ########################## FPU functions #################################### */ /* ########################## FPU functions #################################### */
/** /**

View File

@ -2,7 +2,7 @@
* @file core_cm7.h * @file core_cm7.h
* @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
#include "cmsis_version.h"
/* CMSIS CM7 definitions */ /* CMSIS CM7 definitions */
#define __CM7_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ #define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __CM7_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ #define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ #define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \
__CM7_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M (7U) /*!< Cortex-M Core */ #define __CORTEX_M (7U) /*!< Cortex-M Core */
@ -482,7 +484,7 @@ typedef struct
uint32_t RESERVED4[15U]; uint32_t RESERVED4[15U];
__IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
__IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
__IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 1 */ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
uint32_t RESERVED5[1U]; uint32_t RESERVED5[1U];
__OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
uint32_t RESERVED6[1U]; uint32_t RESERVED6[1U];
@ -2143,6 +2145,13 @@ __STATIC_INLINE void __NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */ /*@} end of CMSIS_Core_NVICFunctions */
/* ########################## MPU functions #################################### */
#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
#include "mpu_armv7.h"
#endif
/* ########################## FPU functions #################################### */ /* ########################## FPU functions #################################### */
/** /**

View File

@ -2,7 +2,7 @@
* @file core_sc000.h * @file core_sc000.h
* @brief CMSIS SC000 Core Peripheral Access Layer Header File * @brief CMSIS SC000 Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
#include "cmsis_version.h"
/* CMSIS SC000 definitions */ /* CMSIS SC000 definitions */
#define __SC000_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ #define __SC000_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __SC000_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ #define __SC000_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \ #define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \
__SC000_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __SC000_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_SC (000U) /*!< Cortex secure core */ #define __CORTEX_SC (000U) /*!< Cortex secure core */

View File

@ -2,7 +2,7 @@
* @file core_sc300.h * @file core_sc300.h
* @brief CMSIS SC300 Core Peripheral Access Layer Header File * @brief CMSIS SC300 Core Peripheral Access Layer Header File
* @version V5.0.2 * @version V5.0.2
* @date 13. February 2017 * @date 19. April 2017
******************************************************************************/ ******************************************************************************/
/* /*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved. * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
@ -60,11 +60,13 @@
@{ @{
*/ */
#include "cmsis_version.h"
/* CMSIS SC300 definitions */ /* CMSIS SC300 definitions */
#define __SC300_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ #define __SC300_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __SC300_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ #define __SC300_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \ #define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \
__SC300_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ __SC300_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_SC (300U) /*!< Cortex secure core */ #define __CORTEX_SC (300U) /*!< Cortex secure core */

182
3rd_party/CMSIS/Include/mpu_armv7.h vendored Normal file
View File

@ -0,0 +1,182 @@
/******************************************************************************
* @file mpu_armv7.h
* @brief CMSIS MPU API for ARMv7 MPU
* @version V5.0.2
* @date 09. June 2017
******************************************************************************/
/*
* Copyright (c) 2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ARM_MPU_ARMV7_H
#define ARM_MPU_ARMV7_H
#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U)
#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U)
#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U)
#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U)
#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U)
#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U)
#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU)
#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU)
#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU)
#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU)
#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU)
#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU)
#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U)
#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U)
#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U)
#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U)
#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U)
#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U)
#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U)
#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U)
#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U)
#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U)
#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU)
#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU)
#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU)
#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU)
#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU)
#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU)
#define ARM_MPU_AP_NONE 0u
#define ARM_MPU_AP_PRIV 1u
#define ARM_MPU_AP_URO 2u
#define ARM_MPU_AP_FULL 3u
#define ARM_MPU_AP_PRO 5u
#define ARM_MPU_AP_RO 6u
/** MPU Region Base Address Register Value
*
* \param Region The region to be configured, number 0 to 15.
* \param BaseAddress The base address for the region.
*/
#define ARM_MPU_RBAR(Region, BaseAddress) ((BaseAddress & MPU_RBAR_ADDR_Msk) | (Region & MPU_RBAR_REGION_Msk) | (1UL << MPU_RBAR_VALID_Pos))
/**
* MPU Region Attribut and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable Region is shareable between multiple bus masters.
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
((DisableExec << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
((AccessPermission << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
((TypeExtField << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
((IsShareable << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
((IsCacheable << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
((IsBufferable << MPU_RASR_B_Pos) & MPU_RASR_B_Msk) | \
((SubRegionDisable << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \
((Size << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \
((1UL << MPU_RASR_ENABLE_Pos) & MPU_RASR_ENABLE_Msk)
/**
* Struct for a single MPU Region
*/
typedef struct _ARM_MPU_Region_t {
uint32_t RBAR; //!< The region base address register value (RBAR)
uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
} ARM_MPU_Region_t;
/** Enable the MPU.
* \param MPU_Control Default access permissions for unconfigured regions.
*/
__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
{
__DSB();
__ISB();
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
#endif
}
/** Disable the MPU.
*/
__STATIC_INLINE void ARM_MPU_Disable()
{
__DSB();
__ISB();
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
#endif
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
}
/** Clear and disable the given MPU region.
* \param rnr Region number to be cleared.
*/
__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
{
MPU->RNR = rnr;
MPU->RASR = 0u;
}
/** Configure an MPU region.
* \param rbar Value for RBAR register.
* \param rsar Value for RSAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
{
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Configure the given MPU region.
* \param rnr Region number to be configured.
* \param rbar Value for RBAR register.
* \param rsar Value for RSAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
{
MPU->RNR = rnr;
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Memcopy with strictly ordered memory access, e.g. for register targets.
* \param dst Destination data is copied to.
* \param src Source data is copied from.
* \param len Amount of data words to be copied.
*/
__STATIC_INLINE void orderedCpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
{
uint32_t i;
for (i = 0u; i < len; ++i)
{
dst[i] = src[i];
}
}
/** Load the given number of MPU regions from a table.
* \param table Pointer to the MPU configuration table.
* \param cnt Amount of regions to be configured.
*/
__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
{
orderedCpy(&(MPU->RBAR), &(table->RBAR), cnt*sizeof(ARM_MPU_Region_t)/4u);
}
#endif

View File

@ -1,201 +1,201 @@
Apache License Apache License
Version 2.0, January 2004 Version 2.0, January 2004
http://www.apache.org/licenses/ http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions. 1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, "License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document. and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by "Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License. the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all "Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition, control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the "control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity. outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity "You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License. exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, "Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation including but not limited to software source code, documentation
source, and configuration files. source, and configuration files.
"Object" form shall mean any form resulting from mechanical "Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation, not limited to compiled object code, generated documentation,
and conversions to other media types. and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or "Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work copyright notice that is included in or attached to the work
(an example is provided in the Appendix below). (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object "Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of, separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof. the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including "Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted" the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution." designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity "Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work. subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of 2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual, this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of, copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form. Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of 3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual, this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made, (except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work, use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s) Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate granted to You under this License for that Work shall terminate
as of the date such litigation is filed. as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the 4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You modifications, and in Source or Object form, provided that You
meet the following conditions: meet the following conditions:
(a) You must give any other recipients of the Work or (a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices (b) You must cause any modified files to carry prominent notices
stating that You changed the files; and stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works (c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work, attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of excluding those notices that do not pertain to any part of
the Derivative Works; and the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its (d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or, documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed that such additional attribution notices cannot be construed
as modifying the License. as modifying the License.
You may add Your own copyright statement to Your modifications and You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use, for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License. the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, 5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions. this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions. with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade 6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor, names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file. origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or 7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS, Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License. risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, 8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise, whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill, Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages. has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing 9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer, the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity, and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify, of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability. of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work. APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}" boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright {yyyy} {name of copyright owner} Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.

View File

@ -1,7 +1,7 @@
About CMSIS About CMSIS
=========== ===========
This folder contains the Cortex Microcontroller Software Interface Standard This folder contains the Cortex Microcontroller Software Interface Standard
(CMSIS) V5.0.2, which provides a single standard across all Cortex-Mx (CMSIS) V5.1.0, which provides a single standard across all Cortex-Mx
processor series vendors. It enables code re-use and code sharing across processor series vendors. It enables code re-use and code sharing across
software projects and reduces time-to-market for new embedded applications. software projects and reduces time-to-market for new embedded applications.

View File

@ -42,7 +42,7 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* start and end of stack defined in the linker script ---------------------*/ /* start and end of stack defined in the linker script ---------------------*/
extern int __stack_start__; /*extern int __stack_start__;*/
extern int __stack_end__; extern int __stack_end__;
/* Weak prototypes for error handlers --------------------------------------*/ /* Weak prototypes for error handlers --------------------------------------*/

View File

@ -42,7 +42,7 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* start and end of stack defined in the linker script ---------------------*/ /* start and end of stack defined in the linker script ---------------------*/
extern int __stack_start__; /*extern int __stack_start__;*/
extern int __stack_end__; extern int __stack_end__;
/* Weak prototypes for error handlers --------------------------------------*/ /* Weak prototypes for error handlers --------------------------------------*/

View File

@ -42,7 +42,7 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* start and end of stack defined in the linker script ---------------------*/ /* start and end of stack defined in the linker script ---------------------*/
extern int __stack_start__; /*extern int __stack_start__;*/
extern int __stack_end__; extern int __stack_end__;
/* Weak prototypes for error handlers --------------------------------------*/ /* Weak prototypes for error handlers --------------------------------------*/

View File

@ -41,7 +41,7 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* start and end of stack defined in the linker script ---------------------*/ /* start and end of stack defined in the linker script ---------------------*/
extern int __stack_start__; /*extern int __stack_start__;*/
extern int __stack_end__; extern int __stack_end__;
/* Weak prototypes for error handlers --------------------------------------*/ /* Weak prototypes for error handlers --------------------------------------*/

View File

@ -42,7 +42,7 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* start and end of stack defined in the linker script ---------------------*/ /* start and end of stack defined in the linker script ---------------------*/
extern int __stack_start__; /*extern int __stack_start__;*/
extern int __stack_end__; extern int __stack_end__;
/* Weak prototypes for error handlers --------------------------------------*/ /* Weak prototypes for error handlers --------------------------------------*/

View File

@ -42,7 +42,7 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* start and end of stack defined in the linker script ---------------------*/ /* start and end of stack defined in the linker script ---------------------*/
extern int __stack_start__; /*extern int __stack_start__;*/
extern int __stack_end__; extern int __stack_end__;
/* Weak prototypes for error handlers --------------------------------------*/ /* Weak prototypes for error handlers --------------------------------------*/

View File

@ -42,7 +42,7 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* start and end of stack defined in the linker script ---------------------*/ /* start and end of stack defined in the linker script ---------------------*/
extern int __stack_start__; /*extern int __stack_start__;*/
extern int __stack_end__; extern int __stack_end__;
/* Weak prototypes for error handlers --------------------------------------*/ /* Weak prototypes for error handlers --------------------------------------*/

View File

@ -42,7 +42,7 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* start and end of stack defined in the linker script ---------------------*/ /* start and end of stack defined in the linker script ---------------------*/
extern int __stack_start__; /*extern int __stack_start__;*/
extern int __stack_end__; extern int __stack_end__;
/* Weak prototypes for error handlers --------------------------------------*/ /* Weak prototypes for error handlers --------------------------------------*/

View File

@ -5,7 +5,7 @@
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8 DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "QP/C++" PROJECT_NAME = "QP/C++"
PROJECT_NUMBER = "5.9.6" PROJECT_NUMBER = "5.9.7"
PROJECT_BRIEF = PROJECT_BRIEF =
PROJECT_LOGO = images/header_logo_ql.png PROJECT_LOGO = images/header_logo_ql.png
OUTPUT_DIRECTORY = OUTPUT_DIRECTORY =
@ -71,13 +71,13 @@ HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO HIDE_SCOPE_NAMES = YES
HIDE_COMPOUND_REFERENCE= NO HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES INLINE_INFO = YES
SORT_MEMBER_DOCS = YES SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO SORT_GROUP_NAMES = NO
@ -112,6 +112,7 @@ INPUT = \
main.dox \ main.dox \
gs.dox \ gs.dox \
struct.dox \ struct.dox \
api.dox \
exa.dox \ exa.dox \
exa_apps.dox \ exa_apps.dox \
exa_native.dox \ exa_native.dox \

View File

@ -5,7 +5,7 @@
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8 DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "QP/C++" PROJECT_NAME = "QP/C++"
PROJECT_NUMBER = "5.9.6" PROJECT_NUMBER = "5.9.7"
PROJECT_BRIEF = PROJECT_BRIEF =
PROJECT_LOGO = images/header_logo_ql.png PROJECT_LOGO = images/header_logo_ql.png
OUTPUT_DIRECTORY = OUTPUT_DIRECTORY =
@ -71,13 +71,13 @@ HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO HIDE_SCOPE_NAMES = YES
HIDE_COMPOUND_REFERENCE= NO HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES INLINE_INFO = YES
SORT_MEMBER_DOCS = YES SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO SORT_GROUP_NAMES = NO
@ -112,6 +112,7 @@ INPUT = \
main.dox \ main.dox \
gs.dox \ gs.dox \
struct.dox \ struct.dox \
api.dox \
exa.dox \ exa.dox \
exa_apps.dox \ exa_apps.dox \
exa_native.dox \ exa_native.dox \

263
doxygen/api.dox Normal file
View File

@ -0,0 +1,263 @@
@namespace QP {
/*! @page api API Reference
@tableofcontents
@section api_qep QEP (Hierarchical State Machines)
QEP is a universal, UML-compliant event processor that enables developers to code UML state machines in highly readable ANSI-C, in which every state machine element is mapped to code precisely, unambiguously, and exactly once (traceability). QEP fully supports hierarchical state nesting, which is the fundamental mechanism for reusing behavior across many states instead of repeating the same actions and transitions over and over again.
<div class="separate"></div>
@subsection api_qep_hsm Hierarchical State Machines
- QHsm class
- QHsm::QHsm()
- QHsm::init()
- QHsm::dispatch()
- QHsm::isIn()
- QHsm::state()
- QHsm::top()
- QMsm class
- QMsm::QMsm()
- QMsm::isInState()
- QMsm::stateObj()
- Q_STATE_CAST()
- Q_EVT_CAST()
------------------------------------------------------------------------------
@section api_qf QF (Active Object Framework)
QF is a portable, event-driven, real-time framework for execution of active objects (concurrent state machines) specifically designed for real-time embedded (RTE) systems.
<div class="separate"></div>
@subsection api_qf_act Active Objects
- QActive class
- QActive::QActive()
- QActive::start()
- %QActive:: POST()
- %QActive:: POST_X()
- QActive::postLIFO()
- QActive::defer()
- QActive::recall()
- QActive::flushDeferred()
- QActive::stop()
- QMActive class
- QMActive::QMActive()
<div class="separate"></div>
@subsection api_qf_ps Publish-Subscribe
- ::QSubscrList (Subscriber List struct)
- QF::psInit()
- %QF:: PUBLISH()
- QActive::subscribe()
- QActive::unsubscribe()
- QActive::unsubscribeAll()
<div class="separate"></div>
@subsection api_qf_evt Dynamic Events
- QEvt class
- Q_NEW()
- Q_NEW_X()
- Q_NEW_REF()
- Q_DELETE_REF()
- QF::gc()
<div class="separate"></div>
@subsection api_qf_time Time Events
- QTimeEvt class
- QTimeEvt::QTimeEvt(QActive * const, enum_t const, uint_fast8_t const)
- QTimeEvt::armX()
- QTimeEvt::disarm()
- QTimeEvt::rearm()
- QTimeEvt::ctr()
- QTicker active object
- %QF:: TICK()
- %QF:: TICK_X()
<div class="separate"></div>
@subsection api_qf_queue Event Queues (raw thread-safe)
- QEQueue class
- QEQueue::init()
- QEQueue::post()
- QEQueue::postLIFO()
- QEQueue::get()
- QEQueue::getNFree()
- QEQueue::getNMin()
- QEQueue::isEmpty()
- QEQueueCtr()
<div class="separate"></div>
@subsection api_qf_mem Memory Pools
- QMPool class
- QMPool::init()
- QMPool::get()
- QMPool::put()
------------------------------------------------------------------------------
@section api_qs QS ("Quantum Spy" Software Tracing)
QS is a software tracing system that enables developers to monitor live event-driven QP applications with minimal target system resources and without stopping or significantly slowing down the code. QS is an ideal tool for testing, troubleshooting, and optimizing QP applications. QS can even be used to support acceptance testing in product manufacturing.
<div class="separate"></div>
@subsection api_qs_ini QS Initialization and Control
- QS_INIT()
- QS::initBuf()
- QS::getByte()
- QS::getBlock()
- QS::onStartup()
- QS::onCleanup()
- QS::onFlush()
- QS::onGetTime()
<div class="separate"></div>
@subsection api_qs_rx QS Receive-Channel (QS-RX)
- QS::rxInitBuf()
- QS::rxPut()
- QS::rxParse()
- QS::onCommand()
<div class="separate"></div>
@subsection api_qs_filter QS Filters
- QS_FILTER_ON()
- QS_FILTER_OFF()
- QS_FILTER_SM_OBJ()
- QS_FILTER_AO_OBJ()
- QS_FILTER_MP_OBJ()
- QS_FILTER_EQ_OBJ()
- QS_FILTER_TE_OBJ()
- QS_FILTER_AP_OBJ()
<div class="separate"></div>
@subsection api_qs_dict QS Dictionaries
- QS_SIG_DICTIONARY()
- QS_OBJ_DICTIONARY()
- QS_FUN_DICTIONARY()
- QS_USR_DICTIONARY()
<div class="separate"></div>
@subsection api_qs_user QS Application-Specific Records
- ::QS_USER enumeration
- QS_BEGIN()
- QS_END()
- QS_U8() / QS_I8()
- QS_U16() / QS_I16()
- QS_U32() / QS_I32()
- QS_U32_HEX()
- QS_STR()
- QS_MEM()
------------------------------------------------------------------------------
@section api_qv QV (Cooperative Kernel)
QV is a simple **cooperative** kernel (previously called "Vanilla" kernel). This kernel executes active objects one at a time, with priority-based scheduling performed before processing of each event. Due to naturally short duration of event processing in state machines, the simple QV kernel is often adequate for many real-time systems.
The QV scheduler is engaged after every RTC step of any @termref{active object} to choose the next active object to execute. The QV scheduler always chooses the highest-priority active object that has any events in its event queue. The QV scheduler then extracts the next event from this queue and dispatches it to the state machine associated with the active object. The state machine runs to completion, after which the QV scheduler runs and the cycle repeats.
Please note that because the state machines always return to the QV scheduler after each RTC step, a single stack can be used to process all state machines (memory-friendly architecture).
The QV scheduler can also very easily detect when all event queues are empty, at which point it can call the idle callback to let the application put the CPU and peripherals to a low-power sleep mode (power-friendly architecture).
Given the simplicity, portability, and low-resource consumption, the QV scheduler is very attractive. It allows you to partition the problem into active objects and execute these active objects orderly. The task-level response of this scheduler is the longest RTC step in the whole system, but because event-driven active objects dont block, the RTC steps tend to be very short (typically just a few microseconds). Also, often you can break up longer RTC steps into shorter pieces, by posting an event to self and returning (“Reminder” state pattern). The self-posted event then triggers the continuation of longer processing.
<div class="separate"></div>
@subsection api_qv_init Kernel Initialization and Control
- QV_INIT()
- <a href="qv_8c.html#a779a1bc9482e2d489dc87751cd100fdb"><b>QF_run()</b></a>
- QV::onIdle()
- QV_CPU_SLEEP()
- QV::getVersion()
------------------------------------------------------------------------------
@section api_qk Preemptive Run-to-Completion Kernel (QK)
QK is a tiny **preemptive**, priority-based, non-blocking kernel designed specifically for executing active objects. QK runs active objects in the same way as prioritized interrupt controller (such as NVIC in ARM Cortex-M) runs interrupts using the single stack. Active objects process their events in run-to-completion (RTC) fashion and remove themselves from the call stack, the same way as nested interrupts remove themselves from the stack upon completion. At the same time high-priority active objects can preempt lower-priority active objects, just like interrupts can preempt each other under a prioritized interrupt controller. QK meets all the requirement of the Rate Monotonic Scheduling (a.k.a. Rate Monotonic Analysis RMA) and can be used in hard real-time systems.
<div class="separate"></div>
@subsection api_qk_ctrl Kernel Initialization and Control
- QK_INIT()
- <a href="qk_8c.html#a779a1bc9482e2d489dc87751cd100fdb"><b>QF_run()</b></a>
- QK::onIdle()
- QK_schedLock()
- QK_schedUnlock()
- QK::getVersion()
<div class="separate"></div>
@subsection api_qk_isr Interrupt Management
- QK_ISR_ENTRY()
- QK_ISR_EXIT()
------------------------------------------------------------------------------
@section api_qxk Preemptive Dual-Mode (Run-to-Completion/Blocking) RTOS Kernel
QXK is a small, preemptive, priority-based, dual-mode **blocking** kernel that executes active objects like the @ref qk "QK kernel", but can also execute traditional __blocking__ threads (extended threads). In this respect, QXK behaves exactly as a conventional __RTOS__ (Real-Time Operating System). QXK has been designed specifically for mixing event-driven active objects with traditional blocking code, such as commercial middleware (TCP/IP stacks, UDP stacks, embedded file systems, etc.) or legacy software.
<div class="separate"></div>
@subsection api_qxk_ctrl Kernel Initialization and Control
- QXK_INIT()
- <a href="qxk_8c.html#a779a1bc9482e2d489dc87751cd100fdb"><b>QF_run()</b></a>
- QXK::onIdle()
- QXK_schedLock()
- QXK_schedUnlock()
- QXK::getVersion()
<div class="separate"></div>
@subsection api_qxk_isr Interrupt Management
- QXK_ISR_ENTRY()
- QXK_ISR_EXIT()
<div class="separate"></div>
@subsection api_qxk_xthr Extended Thread Management
- QXThread class
- QXThread::QXThread()
- QXThread::start()
- QXThread::postX()
- QXThread::delay()
- QXThread::delayCancel()
- QXThread::queueGet()
- Q_XTHREAD_CAST()
<div class="separate"></div>
@subsection api_qxk_sema Semaphores
- QXSemaphore class (Semaphore Control Block)
- QXSemaphore::init()
- QXSemaphore::wait()
- QXSemaphore::tryWait()
- QXSemaphore::signal()
<div class="separate"></div>
@subsection api_qxk_mutex Mutexes
- QXMutex class (Mutex Control Block)
- QXMutex::init()
- QXMutex::lock()
- QXMutex::tryLock()
- QXMutex::unlock()
<div class="separate"></div>
@subsection api_qxk_queue Message Queues
- QXThread::postX() - posting messages to blocking threads
- QXThread::queueGet() - waiting (blocking) on message queue
<div class="separate"></div>
@subsection api_qxk_mem Memory Pools
- QMPool class
- QMPool::init()
- QMPool::get()
- QMPool::put()
<div class="separate"></div>
@subsection api_qxk_tls Thread-Local Storage
- QXK_current()
- QXK_TLS()
*/
} // namespace QP

View File

@ -2,6 +2,34 @@ namespace QP {
/** @page history Revision History /** @page history Revision History
@section qpcpp_5_9_7 Version 5.9.7, 2017-08-18
The main focus of this release are new requested features for the @ref qxk "dual-mode QXK kernel":
- <a href="https://sourceforge.net/p/qpc/feature-requests/129" class="extern">feature#129 "Allow blocking while holding a mutex in QXK"</a>; and
- <a href="https://sourceforge.net/p/qpc/feature-requests/130" class="extern">feature#130 "Allow QXK mutex locks to nest while acquired by the same thread"</a>; and
- <a href="https://sourceforge.net/p/qpc/feature-requests/131" class="extern">feature#131 "Add a non-blocking "tryLock()" operation to the QXK mutex"</a>.
Additionally, this release adds also the non-blocking QXSemaphore::tryWait() operation.
In the process of re-implementing the QP::QXMutex, the previouis non-blocking priority ceiling mutex has been replaced with an equivalent selective QXK scheduler locking up to the specified ceiling priority. Specifically, this feature has been implemented with two new operations QXK::schedLock() and QXK::schedUnlock().
For consistency, the non-blocking mutex of the @ref qk "QK kernel" has been also replaced by the operations QK::schedLock() and QK::schedUnlock().
All related QXK and QK examples have been updated to use the selective scheduler locking instead of the mutex. The new blocking QXK mutex has been demonstrated in the following updated examples:
- @ref arm-cm_dpp_efm32-slstk3401a
- @ref arm-cm_dpp_ek-tm4c123gxl
@attention
The changes to QP::QXMutex in QXK and the now obsolete QMutex in QK **break backwards-compatiblity** with the exising code that relies these features. In the exising code, the mutexes should be replaced with selective scheduler locking.
@attention
Also, the blocking APIs with timeouts, such as QXMutex::lock(), QXSemaphore::wait(), QXThread::delay(), and QXThread::queueGet() no longer require the last `tickRate` parameter. This also **breaks backward-compatiblity** with the exising code that uses these operations.
This release also updates CMSIS to version 5.1.0 (3rd_party/CMSIS).
This release also adds the @ref api "API Reference" section to the QP/C++ documentation.
-----------------------------------------------------------------------------
@section qpcpp_5_9_6 Version 5.9.6, 2017-08-04 @section qpcpp_5_9_6 Version 5.9.6, 2017-08-04
The main focus of this release are improvements to the "dual-mode" QXK kernel. Specifically, this release implements the <a href="https://sourceforge.net/p/qpc/feature-requests/128/" class="extern">featrue request #128 "QP Semaphore Max Value Setting"</a> for QXK. This feature changes the QXK function QP::QXSemaphore::init(), which now takes additional parameter `count`. This parameter specifies the maximum allowed count for the semaphore (e.g., count of 1 makes the semaphore a binary-semaphore). The main focus of this release are improvements to the "dual-mode" QXK kernel. Specifically, this release implements the <a href="https://sourceforge.net/p/qpc/feature-requests/128/" class="extern">featrue request #128 "QP Semaphore Max Value Setting"</a> for QXK. This feature changes the QXK function QP::QXSemaphore::init(), which now takes additional parameter `count`. This parameter specifies the maximum allowed count for the semaphore (e.g., count of 1 makes the semaphore a binary-semaphore).

BIN
doxygen/images/car_mud.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

View File

@ -51,6 +51,9 @@ The most unique characteristic of the QP/C++&trade; framework is its very small
The behavior of active objects is specified in QP by means of The behavior of active objects is specified in QP by means of
<a class="extern" target="_blank" href="https://www.state-machine.com/doc/concepts#HSM">hierarchical state machines (UML statecharts)</a>. The frameworks support manual coding of UML state machines in C or C++ as well as fully automatic code generation by means of the free graphical <a class="extern" target="_blank" href="https://www.state-machine.com/qm">QM&trade; modeling tool</a>. <a class="extern" target="_blank" href="https://www.state-machine.com/doc/concepts#HSM">hierarchical state machines (UML statecharts)</a>. The frameworks support manual coding of UML state machines in C or C++ as well as fully automatic code generation by means of the free graphical <a class="extern" target="_blank" href="https://www.state-machine.com/qm">QM&trade; modeling tool</a>.
@remarks
State machines can be an incredibly powerful technique, but they require an event-driven **infrastructure** (framework) that provides, at a minimum: a run-to-completion (RTC) execution context for each state machine, queuing of events, and event-based timing services. This is really the pivotal point. Without an event-driven framewok (like QP/C++), state machines are like <a class="extern" target="_blank" href="https://state-machine.com/doc/concepts#Infrastructure">cars without an infrastructure of roads</a>.
<div class="separate"></div> <div class="separate"></div>
@subsection kernels Built-in Kernels @subsection kernels Built-in Kernels

View File

@ -1,8 +1,8 @@
@echo off @echo off
:: ========================================================================== :: ==========================================================================
:: Product: QP/C++ script for generating Doxygen documentation :: Product: QP/C++ script for generating Doxygen documentation
:: Last Updated for Version: 5.9.6 :: Last Updated for Version: 5.9.7
:: Date of the Last Update: 2017-08-01 :: Date of the Last Update: 2017-08-18
:: ::
:: Q u a n t u m L e a P s :: Q u a n t u m L e a P s
:: --------------------------- :: ---------------------------
@ -38,7 +38,7 @@ echo usage:
echo make echo make
echo make -CHM echo make -CHM
set VERSION=5.9.6 set VERSION=5.9.7
:: Generate Resource Standard Metrics for QP/C++ ............................. :: Generate Resource Standard Metrics for QP/C++ .............................
set DOXHOME="C:\tools\doxygen\bin" set DOXHOME="C:\tools\doxygen\bin"

View File

@ -1,7 +1,7 @@
/** @page metrics Code Metrics /** @page metrics Code Metrics
@code @code
Standard Code Metrics for QP/C++ 5.9.6 Standard Code Metrics for QP/C++ 5.9.7
Resource Standard Metrics (TM) for C, C++, C# and Java Resource Standard Metrics (TM) for C, C++, C# and Java
Version 7.75 - mSquaredTechnologies.com Version 7.75 - mSquaredTechnologies.com
@ -9,7 +9,7 @@
License Type: Windows Single User License License Type: Windows Single User License
Licensed To : Quantum Leaps, LLC Licensed To : Quantum Leaps, LLC
License No. : WS2975 License Date: Dec 15, 2013 License No. : WS2975 License Date: Dec 15, 2013
Build Date : Sep 2 2009 Run Date: Aug 04, 2017 Build Date : Sep 2 2009 Run Date: Aug 21, 2017
(C)1996-2009 M Squared Technologies LLC (C)1996-2009 M Squared Technologies LLC
________________________________________________________________________ ________________________________________________________________________
@ -154,7 +154,7 @@
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 259 eLOC 227 lLOC 129 Comment 317 Lines 664 LOC 259 eLOC 227 lLOC 129 Comment 318 Lines 666
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
@ -187,6 +187,11 @@
Complexity Param 0 Return 1 Cyclo Vg 1 Total 2 Complexity Param 0 Return 1 Cyclo Vg 1 Total 2
LOC 3 eLOC 2 lLOC 1 Comment 10 Lines 3 LOC 3 eLOC 2 lLOC 1 Comment 10 Lines 3
Inline Function: QP::QEQueue::getNMin
Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 1 Total 2
LOC 3 eLOC 2 lLOC 1 Comment 11 Lines 3
Inline Function: QP::QEQueue::isEmpty Inline Function: QP::QEQueue::isEmpty
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 1 Total 2 Complexity Param 0 Return 1 Cyclo Vg 1 Total 2
@ -196,17 +201,17 @@
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 46 eLOC 42 lLOC 24 Comment 184 Lines 257 LOC 49 eLOC 44 lLOC 25 Comment 195 Lines 272
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
File Function Count....: 2 File Function Count....: 3
Total Function LOC.....: 6 Total Function Pts LOC : 0.0 Total Function LOC.....: 9 Total Function Pts LOC : 0.0
Total Function eLOC....: 4 Total Function Pts eLOC: 0.0 Total Function eLOC....: 6 Total Function Pts eLOC: 0.0
Total Function lLOC....: 2 Total Function Pts lLOC: 0.0 Total Function lLOC....: 3 Total Function Pts lLOC: 0.0
Total Function Params .: 0 Total Function Return .: 2 Total Function Params .: 0 Total Function Return .: 3
Total Cyclo Complexity : 2 Total Function Complex.: 4 Total Cyclo Complexity : 3 Total Function Complex.: 6
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function LOC ......: 3 Average Function LOC ..: 3.00 Max Function LOC ......: 3 Average Function LOC ..: 3.00
Max Function eLOC .....: 2 Average Function eLOC .: 2.00 Max Function eLOC .....: 2 Average Function eLOC .: 2.00
@ -260,7 +265,7 @@
Parameters: (enum_t const sgnl) Non-ANSI Parameter Construct Defined By Parameters: (enum_t const sgnl) Non-ANSI Parameter Construct Defined By
Compiler Directive Compiler Directive
Complexity Param 1 Return 1 Cyclo Vg 1 Total 3 Complexity Param 1 Return 1 Cyclo Vg 1 Total 3
LOC 7 eLOC 5 lLOC 3 Comment 5 Lines 8 LOC 7 eLOC 5 lLOC 3 Comment 7 Lines 8
Inline Function: QP::QTimeEvt::postIn Inline Function: QP::QTimeEvt::postIn
Parameters: (QActive * const act, QTimeEvtCtr const nTicks) Parameters: (QActive * const act, QTimeEvtCtr const nTicks)
@ -296,7 +301,7 @@
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 280 eLOC 264 lLOC 117 Comment 483 Lines 867 LOC 283 eLOC 267 lLOC 118 Comment 490 Lines 878
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
@ -333,7 +338,7 @@
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 79 eLOC 73 lLOC 27 Comment 102 Lines 196 LOC 71 eLOC 66 lLOC 22 Comment 104 Lines 191
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
@ -576,7 +581,7 @@
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 517 eLOC 500 lLOC 123 Comment 601 Lines 1124 LOC 517 eLOC 500 lLOC 123 Comment 603 Lines 1124
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
@ -660,7 +665,7 @@
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 90 eLOC 83 lLOC 32 Comment 131 Lines 240 LOC 79 eLOC 73 lLOC 25 Comment 122 Lines 218
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
@ -704,7 +709,7 @@
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 60 eLOC 55 lLOC 28 Comment 83 Lines 165 LOC 70 eLOC 64 lLOC 38 Comment 115 Lines 212
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
@ -1763,7 +1768,7 @@
Function Base : 1 Function Base : 1
Loops for / foreach : 1 Loops for / foreach : 1
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3 Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 12 eLOC 10 lLOC 7 Comment 21 Lines 14 LOC 12 eLOC 10 lLOC 7 Comment 14 Lines 14
Function: QP::QActive::start Function: QP::QActive::start
Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t
@ -1774,7 +1779,7 @@
Conditional if / else if: 1 Conditional if / else if: 1
Logical and ( && ) : 3 Logical and ( && ) : 3
Complexity Param 6 Return 1 Cyclo Vg 5 Total 12 Complexity Param 6 Return 1 Cyclo Vg 5 Total 12
LOC 17 eLOC 14 lLOC 9 Comment 29 Lines 26 LOC 17 eLOC 14 lLOC 9 Comment 28 Lines 25
Function: QP::QActive::stop Function: QP::QActive::stop
Parameters: (void) Parameters: (void)
@ -1782,7 +1787,24 @@
Function Base : 1 Function Base : 1
Conditional if / else if: 1 Conditional if / else if: 1
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3 Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 11 eLOC 9 lLOC 6 Comment 14 Lines 14 LOC 11 eLOC 9 lLOC 6 Comment 13 Lines 15
Function: QP::QK::schedLock
Parameters: (uint_fast8_t const ceiling)
Cyclomatic Complexity Vg Detail
Function Base : 1
Conditional if / else if: 1
Complexity Param 1 Return 1 Cyclo Vg 2 Total 4
LOC 23 eLOC 20 lLOC 12 Comment 32 Lines 33
Function: QP::QK::schedUnlock
Parameters: (QSchedStatus const stat)
Cyclomatic Complexity Vg Detail
Function Base : 1
Conditional if / else if: 2
Logical and ( && ) : 1
Complexity Param 1 Return 1 Cyclo Vg 4 Total 6
LOC 23 eLOC 20 lLOC 10 Comment 29 Lines 34
Function: QK_activate_ Function: QK_activate_
Parameters: (void) Parameters: (void)
@ -1797,27 +1819,27 @@
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 164 eLOC 138 lLOC 70 Comment 217 Lines 365 LOC 210 eLOC 178 lLOC 92 Comment 269 Lines 466
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
File Function Count....: 7 File Function Count....: 9
Total Function LOC.....: 125 Total Function Pts LOC : 3.1 Total Function LOC.....: 171 Total Function Pts LOC : 4.0
Total Function eLOC....: 106 Total Function Pts eLOC: 2.6 Total Function eLOC....: 146 Total Function Pts eLOC: 3.4
Total Function lLOC....: 62 Total Function Pts lLOC: 1.3 Total Function lLOC....: 84 Total Function Pts lLOC: 1.7
Total Function Params .: 6 Total Function Return .: 7 Total Function Params .: 8 Total Function Return .: 9
Total Cyclo Complexity : 20 Total Function Complex.: 33 Total Cyclo Complexity : 26 Total Function Complex.: 43
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function LOC ......: 62 Average Function LOC ..: 17.86 Max Function LOC ......: 62 Average Function LOC ..: 19.00
Max Function eLOC .....: 54 Average Function eLOC .: 15.14 Max Function eLOC .....: 54 Average Function eLOC .: 16.22
Max Function lLOC .....: 28 Average Function lLOC .: 8.86 Max Function lLOC .....: 28 Average Function lLOC .: 9.33
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function Parameters: 6 Avg Function Parameters: 0.86 Max Function Parameters: 6 Avg Function Parameters: 0.89
Max Function Returns ..: 1 Avg Function Returns ..: 1.00 Max Function Returns ..: 1 Avg Function Returns ..: 1.00
Max Interface Complex. : 7 Avg Interface Complex. : 1.86 Max Interface Complex. : 7 Avg Interface Complex. : 1.89
Max Cyclomatic Complex.: 7 Avg Cyclomatic Complex.: 2.86 Max Cyclomatic Complex.: 7 Avg Cyclomatic Complex.: 2.89
Max Total Complexity ..: 12 Avg Total Complexity ..: 4.71 Max Total Complexity ..: 12 Avg Total Complexity ..: 4.78
________________________________________________________________________ ________________________________________________________________________
End of File: ..\src\qk\qk.cpp End of File: ..\src\qk\qk.cpp
@ -1825,55 +1847,9 @@
File: ..\src\qk\qk_mutex.cpp File: ..\src\qk\qk_mutex.cpp
________________________________________________________________________ ________________________________________________________________________
Function: QP::QMutex::init
Parameters: (uint_fast8_t const prio)
Complexity Param 1 Return 1 Cyclo Vg 1 Total 3
LOC 4 eLOC 3 lLOC 2 Comment 15 Lines 4
Function: QP::QMutex::lock
Parameters: (void)
Cyclomatic Complexity Vg Detail
Function Base : 1
Conditional if / else if: 1
Logical and ( && ) : 1
Complexity Param 0 Return 1 Cyclo Vg 3 Total 4
LOC 17 eLOC 15 lLOC 7 Comment 24 Lines 23
Function: QP::QMutex::unlock
Parameters: (void)
Cyclomatic Complexity Vg Detail
Function Base : 1
Conditional if / else if: 2
Inlined if-else ( ? : ) : 1
Logical and ( && ) : 1
Complexity Param 0 Return 1 Cyclo Vg 5 Total 6
LOC 23 eLOC 20 lLOC 9 Comment 25 Lines 31
------------------------------------------------------------------------
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 62 eLOC 54 lLOC 19 Comment 114 Lines 174 LOC 0 eLOC 0 lLOC 0 Comment 38 Lines 38
------------------------------------------------------------------------
~~ File Functional Summary ~~
File Function Count....: 3
Total Function LOC.....: 44 Total Function Pts LOC : 1.2
Total Function eLOC....: 38 Total Function Pts eLOC: 1.0
Total Function lLOC....: 18 Total Function Pts lLOC: 0.4
Total Function Params .: 1 Total Function Return .: 3
Total Cyclo Complexity : 9 Total Function Complex.: 13
------ ----- ----- ------ ------ -----
Max Function LOC ......: 23 Average Function LOC ..: 14.67
Max Function eLOC .....: 20 Average Function eLOC .: 12.67
Max Function lLOC .....: 9 Average Function lLOC .: 6.00
------ ----- ----- ------ ------ -----
Max Function Parameters: 1 Avg Function Parameters: 0.33
Max Function Returns ..: 1 Avg Function Returns ..: 1.00
Max Interface Complex. : 2 Avg Interface Complex. : 1.33
Max Cyclomatic Complex.: 5 Avg Cyclomatic Complex.: 3.00
Max Total Complexity ..: 6 Avg Total Complexity ..: 4.33
________________________________________________________________________ ________________________________________________________________________
End of File: ..\src\qk\qk_mutex.cpp End of File: ..\src\qk\qk_mutex.cpp
@ -1889,7 +1865,7 @@
Function: QP::QF::init Function: QP::QF::init
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 1 Total 2 Complexity Param 0 Return 1 Cyclo Vg 1 Total 2
LOC 15 eLOC 14 lLOC 11 Comment 15 Lines 21 LOC 16 eLOC 15 lLOC 12 Comment 15 Lines 23
Function: QP::QF::stop Function: QP::QF::stop
Parameters: (void) Parameters: (void)
@ -1910,7 +1886,7 @@
Function Base : 1 Function Base : 1
Loops for / foreach : 1 Loops for / foreach : 1
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3 Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 12 eLOC 10 lLOC 7 Comment 13 Lines 15 LOC 12 eLOC 10 lLOC 7 Comment 12 Lines 15
Function: QP::QActive::start Function: QP::QActive::start
Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t
@ -1921,16 +1897,33 @@
Conditional if / else if: 1 Conditional if / else if: 1
Logical and ( && ) : 4 Logical and ( && ) : 4
Complexity Param 6 Return 1 Cyclo Vg 6 Total 13 Complexity Param 6 Return 1 Cyclo Vg 6 Total 13
LOC 21 eLOC 18 lLOC 12 Comment 28 Lines 31 LOC 20 eLOC 17 lLOC 11 Comment 30 Lines 29
Function: QP::QActive::stop Function: QP::QActive::stop
Parameters: (void) Parameters: (void)
Cyclomatic Complexity Vg Detail Cyclomatic Complexity Vg Detail
Function Base : 1 Function Base : 1
Conditional if / else if: 1 Conditional if / else if: 1
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 11 eLOC 9 lLOC 6 Comment 13 Lines 14
Function: QP::QXK::schedLock
Parameters: (uint_fast8_t const ceiling)
Cyclomatic Complexity Vg Detail
Function Base : 1
Conditional if / else if: 1
Inlined if-else ( ? : ) : 1
Complexity Param 1 Return 1 Cyclo Vg 3 Total 5
LOC 26 eLOC 23 lLOC 12 Comment 30 Lines 35
Function: QP::QXK::schedUnlock
Parameters: (QSchedStatus const stat)
Cyclomatic Complexity Vg Detail
Function Base : 1
Conditional if / else if: 2
Logical and ( && ) : 1 Logical and ( && ) : 1
Complexity Param 0 Return 1 Cyclo Vg 3 Total 4 Complexity Param 1 Return 1 Cyclo Vg 4 Total 6
LOC 12 eLOC 10 lLOC 6 Comment 14 Lines 15 LOC 23 eLOC 20 lLOC 10 Comment 29 Lines 34
Function: static_cast<QP::QActive*> Function: static_cast<QP::QActive*>
Parameters: (0)) Parameters: (0))
@ -1947,7 +1940,7 @@
Loops while / do : 1 Loops while / do : 1
Conditional if / else if: 6 Conditional if / else if: 6
Complexity Param 0 Return 1 Cyclo Vg 8 Total 9 Complexity Param 0 Return 1 Cyclo Vg 8 Total 9
LOC 78 eLOC 68 lLOC 34 Comment 54 Lines 108 LOC 79 eLOC 69 lLOC 35 Comment 53 Lines 108
Function: QXK_current Function: QXK_current
Parameters: (void) Parameters: (void)
@ -1955,33 +1948,33 @@
Function Base : 1 Function Base : 1
Conditional if / else if: 1 Conditional if / else if: 1
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3 Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 12 eLOC 10 lLOC 7 Comment 3 Lines 16 LOC 14 eLOC 12 lLOC 8 Comment 4 Lines 21
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 240 eLOC 203 lLOC 103 Comment 232 Lines 455 LOC 291 eLOC 248 lLOC 127 Comment 290 Lines 567
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
File Function Count....: 10 File Function Count....: 12
Total Function LOC.....: 184 Total Function Pts LOC : 4.5 Total Function LOC.....: 235 Total Function Pts LOC : 5.5
Total Function eLOC....: 156 Total Function Pts eLOC: 3.8 Total Function eLOC....: 201 Total Function Pts eLOC: 4.7
Total Function lLOC....: 88 Total Function Pts lLOC: 1.9 Total Function lLOC....: 112 Total Function Pts lLOC: 2.4
Total Function Params .: 7 Total Function Return .: 10 Total Function Params .: 9 Total Function Return .: 12
Total Cyclo Complexity : 29 Total Function Complex.: 46 Total Cyclo Complexity : 35 Total Function Complex.: 56
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function LOC ......: 78 Average Function LOC ..: 18.40 Max Function LOC ......: 79 Average Function LOC ..: 19.58
Max Function eLOC .....: 68 Average Function eLOC .: 15.60 Max Function eLOC .....: 69 Average Function eLOC .: 16.75
Max Function lLOC .....: 34 Average Function lLOC .: 8.80 Max Function lLOC .....: 35 Average Function lLOC .: 9.33
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function Parameters: 6 Avg Function Parameters: 0.70 Max Function Parameters: 6 Avg Function Parameters: 0.75
Max Function Returns ..: 1 Avg Function Returns ..: 1.00 Max Function Returns ..: 1 Avg Function Returns ..: 1.00
Max Interface Complex. : 7 Avg Interface Complex. : 1.70 Max Interface Complex. : 7 Avg Interface Complex. : 1.75
Max Cyclomatic Complex.: 8 Avg Cyclomatic Complex.: 2.90 Max Cyclomatic Complex.: 8 Avg Cyclomatic Complex.: 2.92
Max Total Complexity ..: 13 Avg Total Complexity ..: 4.60 Max Total Complexity ..: 13 Avg Total Complexity ..: 4.67
________________________________________________________________________ ________________________________________________________________________
End of File: ..\src\qxk\qxk.cpp End of File: ..\src\qxk\qxk.cpp
@ -1990,54 +1983,65 @@
________________________________________________________________________ ________________________________________________________________________
Function: QP::QXMutex::init Function: QP::QXMutex::init
Parameters: (uint_fast8_t const prio) Parameters: (uint_fast8_t ceiling)
Complexity Param 1 Return 1 Cyclo Vg 1 Total 3 Cyclomatic Complexity Vg Detail
LOC 4 eLOC 3 lLOC 2 Comment 15 Lines 4 Function Base : 1
Logical and ( && ) : 2
Complexity Param 1 Return 1 Cyclo Vg 3 Total 5
LOC 12 eLOC 11 lLOC 7 Comment 20 Lines 22
Function: QP::QXMutex::lock Function: QP::QXMutex::lock
Parameters: (uint_fast16_t const nTicks)
Cyclomatic Complexity Vg Detail
Function Base : 1
Conditional if / else if: 2
Logical and ( && ) : 4
Complexity Param 1 Return 1 Cyclo Vg 7 Total 9
LOC 45 eLOC 41 lLOC 27 Comment 50 Lines 78
Function: QP::QXMutex::tryLock
Parameters: (void) Parameters: (void)
Cyclomatic Complexity Vg Detail Cyclomatic Complexity Vg Detail
Function Base : 1 Function Base : 1
Conditional if / else if: 1 Conditional if / else if: 3
Inlined if-else ( ? : ) : 1 Logical and ( && ) : 4
Logical and ( && ) : 1 Complexity Param 0 Return 1 Cyclo Vg 8 Total 9
Complexity Param 0 Return 1 Cyclo Vg 4 Total 5 LOC 39 eLOC 34 lLOC 19 Comment 41 Lines 59
LOC 22 eLOC 20 lLOC 9 Comment 28 Lines 29
Function: QP::QXMutex::unlock Function: QP::QXMutex::unlock
Parameters: (void) Parameters: (void)
Cyclomatic Complexity Vg Detail Cyclomatic Complexity Vg Detail
Function Base : 1 Function Base : 1
Conditional if / else if: 3 Conditional if / else if: 4
Logical and ( && ) : 1 Logical and ( && ) : 8
Complexity Param 0 Return 1 Cyclo Vg 5 Total 6 Complexity Param 0 Return 1 Cyclo Vg 13 Total 14
LOC 44 eLOC 38 lLOC 17 Comment 36 Lines 53 LOC 56 eLOC 49 lLOC 25 Comment 57 Lines 95
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 88 eLOC 77 lLOC 29 Comment 129 Lines 205 LOC 167 eLOC 149 lLOC 78 Comment 217 Lines 388
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
File Function Count....: 3 File Function Count....: 4
Total Function LOC.....: 70 Total Function Pts LOC : 1.7 Total Function LOC.....: 152 Total Function Pts LOC : 3.2
Total Function eLOC....: 61 Total Function Pts eLOC: 1.5 Total Function eLOC....: 135 Total Function Pts eLOC: 2.8
Total Function lLOC....: 28 Total Function Pts lLOC: 0.5 Total Function lLOC....: 78 Total Function Pts lLOC: 1.5
Total Function Params .: 1 Total Function Return .: 3 Total Function Params .: 2 Total Function Return .: 4
Total Cyclo Complexity : 10 Total Function Complex.: 14 Total Cyclo Complexity : 31 Total Function Complex.: 37
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function LOC ......: 44 Average Function LOC ..: 23.33 Max Function LOC ......: 56 Average Function LOC ..: 38.00
Max Function eLOC .....: 38 Average Function eLOC .: 20.33 Max Function eLOC .....: 49 Average Function eLOC .: 33.75
Max Function lLOC .....: 17 Average Function lLOC .: 9.33 Max Function lLOC .....: 27 Average Function lLOC .: 19.50
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function Parameters: 1 Avg Function Parameters: 0.33 Max Function Parameters: 1 Avg Function Parameters: 0.50
Max Function Returns ..: 1 Avg Function Returns ..: 1.00 Max Function Returns ..: 1 Avg Function Returns ..: 1.00
Max Interface Complex. : 2 Avg Interface Complex. : 1.33 Max Interface Complex. : 2 Avg Interface Complex. : 1.50
Max Cyclomatic Complex.: 5 Avg Cyclomatic Complex.: 3.33 Max Cyclomatic Complex.: 13 Avg Cyclomatic Complex.: 7.75
Max Total Complexity ..: 6 Avg Total Complexity ..: 4.67 Max Total Complexity ..: 14 Avg Total Complexity ..: 9.25
________________________________________________________________________ ________________________________________________________________________
End of File: ..\src\qxk\qxk_mutex.cpp End of File: ..\src\qxk\qxk_mutex.cpp
@ -2051,13 +2055,21 @@
LOC 6 eLOC 4 lLOC 4 Comment 18 Lines 7 LOC 6 eLOC 4 lLOC 4 Comment 18 Lines 7
Function: QP::QXSemaphore::wait Function: QP::QXSemaphore::wait
Parameters: (uint_fast16_t const nTicks, uint_fast8_t const tickRate) Parameters: (uint_fast16_t const nTicks)
Cyclomatic Complexity Vg Detail Cyclomatic Complexity Vg Detail
Function Base : 1 Function Base : 1
Conditional if / else if: 1 Conditional if / else if: 1
Logical and ( && ) : 3 Logical and ( && ) : 3
Complexity Param 2 Return 1 Cyclo Vg 5 Total 8 Complexity Param 1 Return 1 Cyclo Vg 5 Total 7
LOC 28 eLOC 24 lLOC 17 Comment 38 Lines 41 LOC 28 eLOC 25 lLOC 17 Comment 36 Lines 41
Function: QP::QXSemaphore::tryWait
Parameters: (void)
Cyclomatic Complexity Vg Detail
Function Base : 1
Conditional if / else if: 1
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 15 eLOC 12 lLOC 8 Comment 16 Lines 20
Function: QP::QXSemaphore::signal Function: QP::QXSemaphore::signal
Parameters: (void) Parameters: (void)
@ -2066,33 +2078,33 @@
Conditional if / else if: 3 Conditional if / else if: 3
Logical and ( && ) : 2 Logical and ( && ) : 2
Complexity Param 0 Return 1 Cyclo Vg 6 Total 7 Complexity Param 0 Return 1 Cyclo Vg 6 Total 7
LOC 28 eLOC 22 lLOC 13 Comment 25 Lines 36 LOC 29 eLOC 23 lLOC 14 Comment 26 Lines 39
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 81 eLOC 68 lLOC 34 Comment 129 Lines 207 LOC 95 eLOC 80 lLOC 43 Comment 144 Lines 240
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
File Function Count....: 3 File Function Count....: 4
Total Function LOC.....: 62 Total Function Pts LOC : 1.5 Total Function LOC.....: 78 Total Function Pts LOC : 1.8
Total Function eLOC....: 50 Total Function Pts eLOC: 1.3 Total Function eLOC....: 64 Total Function Pts eLOC: 1.5
Total Function lLOC....: 34 Total Function Pts lLOC: 0.6 Total Function lLOC....: 43 Total Function Pts lLOC: 0.8
Total Function Params .: 4 Total Function Return .: 3 Total Function Params .: 3 Total Function Return .: 4
Total Cyclo Complexity : 12 Total Function Complex.: 19 Total Cyclo Complexity : 14 Total Function Complex.: 21
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function LOC ......: 28 Average Function LOC ..: 20.67 Max Function LOC ......: 29 Average Function LOC ..: 19.50
Max Function eLOC .....: 24 Average Function eLOC .: 16.67 Max Function eLOC .....: 25 Average Function eLOC .: 16.00
Max Function lLOC .....: 17 Average Function lLOC .: 11.33 Max Function lLOC .....: 17 Average Function lLOC .: 10.75
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function Parameters: 2 Avg Function Parameters: 1.33 Max Function Parameters: 2 Avg Function Parameters: 0.75
Max Function Returns ..: 1 Avg Function Returns ..: 1.00 Max Function Returns ..: 1 Avg Function Returns ..: 1.00
Max Interface Complex. : 3 Avg Interface Complex. : 2.33 Max Interface Complex. : 3 Avg Interface Complex. : 1.75
Max Cyclomatic Complex.: 6 Avg Cyclomatic Complex.: 4.00 Max Cyclomatic Complex.: 6 Avg Cyclomatic Complex.: 3.50
Max Total Complexity ..: 8 Avg Total Complexity ..: 6.33 Max Total Complexity ..: 7 Avg Total Complexity ..: 5.25
________________________________________________________________________ ________________________________________________________________________
End of File: ..\src\qxk\qxk_sema.cpp End of File: ..\src\qxk\qxk_sema.cpp
@ -2124,7 +2136,7 @@
Conditional if / else if: 1 Conditional if / else if: 1
Logical and ( && ) : 4 Logical and ( && ) : 4
Complexity Param 6 Return 1 Cyclo Vg 6 Total 13 Complexity Param 6 Return 1 Cyclo Vg 6 Total 13
LOC 20 eLOC 17 lLOC 10 Comment 32 Lines 33 LOC 21 eLOC 18 lLOC 11 Comment 35 Lines 39
Function: QP::QXThread::post_ Function: QP::QXThread::post_
Parameters: (QEvt const * const e, uint_fast16_t const margin) Parameters: (QEvt const * const e, uint_fast16_t const margin)
@ -2132,7 +2144,7 @@
Function Base : 1 Function Base : 1
Conditional if / else if: 9 Conditional if / else if: 9
Complexity Param 2 Return 1 Cyclo Vg 10 Total 13 Complexity Param 2 Return 1 Cyclo Vg 10 Total 13
LOC 79 eLOC 64 lLOC 44 Comment 63 Lines 111 LOC 79 eLOC 64 lLOC 44 Comment 65 Lines 111
Function: QP::QXThread::postLIFO Function: QP::QXThread::postLIFO
Parameters: (QEvt const * const) Parameters: (QEvt const * const)
@ -2140,13 +2152,13 @@
LOC 3 eLOC 2 lLOC 1 Comment 9 Lines 3 LOC 3 eLOC 2 lLOC 1 Comment 9 Lines 3
Function: QP::QXThread::queueGet Function: QP::QXThread::queueGet
Parameters: (uint_fast16_t const nTicks, uint_fast8_t const tickRate) Parameters: (uint_fast16_t const nTicks)
Cyclomatic Complexity Vg Detail Cyclomatic Complexity Vg Detail
Function Base : 1 Function Base : 1
Conditional if / else if: 4 Conditional if / else if: 4
Logical and ( && ) : 3 Logical and ( && ) : 3
Complexity Param 2 Return 1 Cyclo Vg 8 Total 11 Complexity Param 1 Return 1 Cyclo Vg 8 Total 10
LOC 61 eLOC 53 lLOC 34 Comment 55 Lines 88 LOC 61 eLOC 54 lLOC 34 Comment 53 Lines 88
Function: QP::QXThread::block_ Function: QP::QXThread::block_
Parameters: (void) Parameters: (void)
@ -2163,13 +2175,12 @@
LOC 8 eLOC 5 lLOC 2 Comment 9 Lines 9 LOC 8 eLOC 5 lLOC 2 Comment 9 Lines 9
Function: QP::QXThread::teArm_ Function: QP::QXThread::teArm_
Parameters: (enum_t const sig, uint_fast16_t const nTicks, uint_fast8_t Parameters: (enum_t const sig, uint_fast16_t const nTicks)
const tickRate)
Cyclomatic Complexity Vg Detail Cyclomatic Complexity Vg Detail
Function Base : 1 Function Base : 1
Conditional if / else if: 2 Conditional if / else if: 2
Complexity Param 3 Return 1 Cyclo Vg 3 Total 7 Complexity Param 2 Return 1 Cyclo Vg 3 Total 6
LOC 16 eLOC 11 lLOC 7 Comment 21 Lines 32 LOC 18 eLOC 14 lLOC 8 Comment 20 Lines 33
Function: QP::QXThread::teDisarm_ Function: QP::QXThread::teDisarm_
Parameters: (void) Parameters: (void)
@ -2180,12 +2191,12 @@
LOC 11 eLOC 8 lLOC 5 Comment 10 Lines 14 LOC 11 eLOC 8 lLOC 5 Comment 10 Lines 14
Function: QP::QXThread::delay Function: QP::QXThread::delay
Parameters: (uint_fast16_t const nTicks, uint_fast8_t const tickRate) Parameters: (uint_fast16_t const nTicks)
Cyclomatic Complexity Vg Detail Cyclomatic Complexity Vg Detail
Function Base : 1 Function Base : 1
Logical and ( && ) : 3 Logical and ( && ) : 3
Complexity Param 2 Return 1 Cyclo Vg 4 Total 7 Complexity Param 1 Return 1 Cyclo Vg 4 Total 6
LOC 20 eLOC 18 lLOC 13 Comment 17 Lines 35 LOC 20 eLOC 19 lLOC 13 Comment 17 Lines 34
Function: QP::QXThread::delayCancel Function: QP::QXThread::delayCancel
Parameters: (void) Parameters: (void)
@ -2199,27 +2210,27 @@
~~ Total File Summary ~~ ~~ Total File Summary ~~
LOC 294 eLOC 243 lLOC 136 Comment 308 Lines 603 LOC 290 eLOC 242 lLOC 138 Comment 310 Lines 600
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ File Functional Summary ~~ ~~ File Functional Summary ~~
File Function Count....: 13 File Function Count....: 13
Total Function LOC.....: 246 Total Function Pts LOC : 5.5 Total Function LOC.....: 249 Total Function Pts LOC : 5.5
Total Function eLOC....: 198 Total Function Pts eLOC: 4.6 Total Function eLOC....: 204 Total Function Pts eLOC: 4.6
Total Function lLOC....: 129 Total Function Pts lLOC: 2.6 Total Function lLOC....: 131 Total Function Pts lLOC: 2.6
Total Function Params .: 20 Total Function Return .: 13 Total Function Params .: 17 Total Function Return .: 13
Total Cyclo Complexity : 43 Total Function Complex.: 76 Total Cyclo Complexity : 43 Total Function Complex.: 73
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function LOC ......: 79 Average Function LOC ..: 18.92 Max Function LOC ......: 79 Average Function LOC ..: 19.15
Max Function eLOC .....: 64 Average Function eLOC .: 15.23 Max Function eLOC .....: 64 Average Function eLOC .: 15.69
Max Function lLOC .....: 44 Average Function lLOC .: 9.92 Max Function lLOC .....: 44 Average Function lLOC .: 10.08
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max Function Parameters: 6 Avg Function Parameters: 1.54 Max Function Parameters: 6 Avg Function Parameters: 1.31
Max Function Returns ..: 1 Avg Function Returns ..: 1.00 Max Function Returns ..: 1 Avg Function Returns ..: 1.00
Max Interface Complex. : 7 Avg Interface Complex. : 2.54 Max Interface Complex. : 7 Avg Interface Complex. : 2.31
Max Cyclomatic Complex.: 10 Avg Cyclomatic Complex.: 3.31 Max Cyclomatic Complex.: 10 Avg Cyclomatic Complex.: 3.31
Max Total Complexity ..: 13 Avg Total Complexity ..: 5.85 Max Total Complexity ..: 13 Avg Total Complexity ..: 5.62
________________________________________________________________________ ________________________________________________________________________
End of File: ..\src\qxk\qxk_xthr.cpp End of File: ..\src\qxk\qxk_xthr.cpp
@ -2232,9 +2243,9 @@
~~ Total Project Summary ~~ ~~ Total Project Summary ~~
LOC 4748 eLOC 4203 lLOC 1797 Comment 6243 Lines 11244 LOC 4869 eLOC 4314 lLOC 1884 Comment 6428 Lines 11582
Average per File, metric/37 files Average per File, metric/37 files
LOC 128 eLOC 113 lLOC 48 Comment 168 Lines 303 LOC 131 eLOC 116 lLOC 50 Comment 173 Lines 313
------------------------------------------------------------------------ ------------------------------------------------------------------------
@ -2366,6 +2377,11 @@
Complexity Param 0 Return 1 Cyclo Vg 1 Total 2 Complexity Param 0 Return 1 Cyclo Vg 1 Total 2
LOC 3 eLOC 2 lLOC 1 Comment 10 Lines 3 LOC 3 eLOC 2 lLOC 1 Comment 10 Lines 3
Function: QP::QEQueue::getNMin
Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 1 Total 2
LOC 3 eLOC 2 lLOC 1 Comment 11 Lines 3
Function: QP::QEQueue::isEmpty Function: QP::QEQueue::isEmpty
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 1 Total 2 Complexity Param 0 Return 1 Cyclo Vg 1 Total 2
@ -2407,7 +2423,7 @@
Parameters: (enum_t const sgnl) Non-ANSI Parameter Construct Defined By Parameters: (enum_t const sgnl) Non-ANSI Parameter Construct Defined By
Compiler Directive Compiler Directive
Complexity Param 1 Return 1 Cyclo Vg 1 Total 3 Complexity Param 1 Return 1 Cyclo Vg 1 Total 3
LOC 7 eLOC 5 lLOC 3 Comment 5 Lines 8 LOC 7 eLOC 5 lLOC 3 Comment 7 Lines 8
Function: QP::QTimeEvt::postIn Function: QP::QTimeEvt::postIn
Parameters: (QActive * const act, QTimeEvtCtr const nTicks) Parameters: (QActive * const act, QTimeEvtCtr const nTicks)
@ -2941,40 +2957,35 @@
Function: QP::QF::run Function: QP::QF::run
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3 Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 12 eLOC 10 lLOC 7 Comment 21 Lines 14 LOC 12 eLOC 10 lLOC 7 Comment 14 Lines 14
Function: QP::QActive::start Function: QP::QActive::start
Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t
const qLen, void * const stkSto, uint_fast16_t const, QEvt c const qLen, void * const stkSto, uint_fast16_t const, QEvt c
onst * const ie) onst * const ie)
Complexity Param 6 Return 1 Cyclo Vg 5 Total 12 Complexity Param 6 Return 1 Cyclo Vg 5 Total 12
LOC 17 eLOC 14 lLOC 9 Comment 29 Lines 26 LOC 17 eLOC 14 lLOC 9 Comment 28 Lines 25
Function: QP::QActive::stop Function: QP::QActive::stop
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3 Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 11 eLOC 9 lLOC 6 Comment 14 Lines 14 LOC 11 eLOC 9 lLOC 6 Comment 13 Lines 15
Function: QP::QK::schedLock
Parameters: (uint_fast8_t const ceiling)
Complexity Param 1 Return 1 Cyclo Vg 2 Total 4
LOC 23 eLOC 20 lLOC 12 Comment 32 Lines 33
Function: QP::QK::schedUnlock
Parameters: (QSchedStatus const stat)
Complexity Param 1 Return 1 Cyclo Vg 4 Total 6
LOC 23 eLOC 20 lLOC 10 Comment 29 Lines 34
Function: QK_activate_ Function: QK_activate_
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 7 Total 8 Complexity Param 0 Return 1 Cyclo Vg 7 Total 8
LOC 62 eLOC 54 lLOC 28 Comment 48 Lines 89 LOC 62 eLOC 54 lLOC 28 Comment 48 Lines 89
Function: QP::QMutex::init
Parameters: (uint_fast8_t const prio)
Complexity Param 1 Return 1 Cyclo Vg 1 Total 3
LOC 4 eLOC 3 lLOC 2 Comment 15 Lines 4
Function: QP::QMutex::lock
Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 3 Total 4
LOC 17 eLOC 15 lLOC 7 Comment 24 Lines 23
Function: QP::QMutex::unlock
Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 5 Total 6
LOC 23 eLOC 20 lLOC 9 Comment 25 Lines 31
Function: QP::QXKIdleThread::QXKIdleThread Function: QP::QXKIdleThread::QXKIdleThread
Parameters: () Parameters: ()
Complexity Param 0 Return 1 Cyclo Vg 1 Total 2 Complexity Param 0 Return 1 Cyclo Vg 1 Total 2
@ -2983,7 +2994,7 @@
Function: QP::QF::init Function: QP::QF::init
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 1 Total 2 Complexity Param 0 Return 1 Cyclo Vg 1 Total 2
LOC 15 eLOC 14 lLOC 11 Comment 15 Lines 21 LOC 16 eLOC 15 lLOC 12 Comment 15 Lines 23
Function: QP::QF::stop Function: QP::QF::stop
Parameters: (void) Parameters: (void)
@ -2998,19 +3009,29 @@
Function: QP::QF::run Function: QP::QF::run
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3 Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 12 eLOC 10 lLOC 7 Comment 13 Lines 15 LOC 12 eLOC 10 lLOC 7 Comment 12 Lines 15
Function: QP::QActive::start Function: QP::QActive::start
Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t
const qLen, void * const stkSto, uint_fast16_t const stkSize const qLen, void * const stkSto, uint_fast16_t const stkSize
, QEvt const * const ie) , QEvt const * const ie)
Complexity Param 6 Return 1 Cyclo Vg 6 Total 13 Complexity Param 6 Return 1 Cyclo Vg 6 Total 13
LOC 21 eLOC 18 lLOC 12 Comment 28 Lines 31 LOC 20 eLOC 17 lLOC 11 Comment 30 Lines 29
Function: QP::QActive::stop Function: QP::QActive::stop
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 3 Total 4 Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 12 eLOC 10 lLOC 6 Comment 14 Lines 15 LOC 11 eLOC 9 lLOC 6 Comment 13 Lines 14
Function: QP::QXK::schedLock
Parameters: (uint_fast8_t const ceiling)
Complexity Param 1 Return 1 Cyclo Vg 3 Total 5
LOC 26 eLOC 23 lLOC 12 Comment 30 Lines 35
Function: QP::QXK::schedUnlock
Parameters: (QSchedStatus const stat)
Complexity Param 1 Return 1 Cyclo Vg 4 Total 6
LOC 23 eLOC 20 lLOC 10 Comment 29 Lines 34
Function: static_cast<QP::QActive*> Function: static_cast<QP::QActive*>
Parameters: (0)) Parameters: (0))
@ -3020,27 +3041,32 @@
Function: QXK_activate_ Function: QXK_activate_
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 8 Total 9 Complexity Param 0 Return 1 Cyclo Vg 8 Total 9
LOC 78 eLOC 68 lLOC 34 Comment 54 Lines 108 LOC 79 eLOC 69 lLOC 35 Comment 53 Lines 108
Function: QXK_current Function: QXK_current
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3 Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 12 eLOC 10 lLOC 7 Comment 3 Lines 16 LOC 14 eLOC 12 lLOC 8 Comment 4 Lines 21
Function: QP::QXMutex::init Function: QP::QXMutex::init
Parameters: (uint_fast8_t const prio) Parameters: (uint_fast8_t ceiling)
Complexity Param 1 Return 1 Cyclo Vg 1 Total 3 Complexity Param 1 Return 1 Cyclo Vg 3 Total 5
LOC 4 eLOC 3 lLOC 2 Comment 15 Lines 4 LOC 12 eLOC 11 lLOC 7 Comment 20 Lines 22
Function: QP::QXMutex::lock Function: QP::QXMutex::lock
Parameters: (uint_fast16_t const nTicks)
Complexity Param 1 Return 1 Cyclo Vg 7 Total 9
LOC 45 eLOC 41 lLOC 27 Comment 50 Lines 78
Function: QP::QXMutex::tryLock
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 4 Total 5 Complexity Param 0 Return 1 Cyclo Vg 8 Total 9
LOC 22 eLOC 20 lLOC 9 Comment 28 Lines 29 LOC 39 eLOC 34 lLOC 19 Comment 41 Lines 59
Function: QP::QXMutex::unlock Function: QP::QXMutex::unlock
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 5 Total 6 Complexity Param 0 Return 1 Cyclo Vg 13 Total 14
LOC 44 eLOC 38 lLOC 17 Comment 36 Lines 53 LOC 56 eLOC 49 lLOC 25 Comment 57 Lines 95
Function: QP::QXSemaphore::init Function: QP::QXSemaphore::init
Parameters: (uint_fast16_t const count, uint_fast16_t const max_count) Parameters: (uint_fast16_t const count, uint_fast16_t const max_count)
@ -3048,14 +3074,19 @@
LOC 6 eLOC 4 lLOC 4 Comment 18 Lines 7 LOC 6 eLOC 4 lLOC 4 Comment 18 Lines 7
Function: QP::QXSemaphore::wait Function: QP::QXSemaphore::wait
Parameters: (uint_fast16_t const nTicks, uint_fast8_t const tickRate) Parameters: (uint_fast16_t const nTicks)
Complexity Param 2 Return 1 Cyclo Vg 5 Total 8 Complexity Param 1 Return 1 Cyclo Vg 5 Total 7
LOC 28 eLOC 24 lLOC 17 Comment 38 Lines 41 LOC 28 eLOC 25 lLOC 17 Comment 36 Lines 41
Function: QP::QXSemaphore::tryWait
Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 2 Total 3
LOC 15 eLOC 12 lLOC 8 Comment 16 Lines 20
Function: QP::QXSemaphore::signal Function: QP::QXSemaphore::signal
Parameters: (void) Parameters: (void)
Complexity Param 0 Return 1 Cyclo Vg 6 Total 7 Complexity Param 0 Return 1 Cyclo Vg 6 Total 7
LOC 28 eLOC 22 lLOC 13 Comment 25 Lines 36 LOC 29 eLOC 23 lLOC 14 Comment 26 Lines 39
Function: QP::QXThread::QXThread Function: QP::QXThread::QXThread
Parameters: (QXThreadHandler const handler, uint_fast8_t const tickRate) Parameters: (QXThreadHandler const handler, uint_fast8_t const tickRate)
@ -3077,12 +3108,12 @@
const qLen, void * const stkSto, uint_fast16_t const stkSize const qLen, void * const stkSto, uint_fast16_t const stkSize
, QEvt const * const) , QEvt const * const)
Complexity Param 6 Return 1 Cyclo Vg 6 Total 13 Complexity Param 6 Return 1 Cyclo Vg 6 Total 13
LOC 20 eLOC 17 lLOC 10 Comment 32 Lines 33 LOC 21 eLOC 18 lLOC 11 Comment 35 Lines 39
Function: QP::QXThread::post_ Function: QP::QXThread::post_
Parameters: (QEvt const * const e, uint_fast16_t const margin) Parameters: (QEvt const * const e, uint_fast16_t const margin)
Complexity Param 2 Return 1 Cyclo Vg 10 Total 13 Complexity Param 2 Return 1 Cyclo Vg 10 Total 13
LOC 79 eLOC 64 lLOC 44 Comment 63 Lines 111 LOC 79 eLOC 64 lLOC 44 Comment 65 Lines 111
Function: QP::QXThread::postLIFO Function: QP::QXThread::postLIFO
Parameters: (QEvt const * const) Parameters: (QEvt const * const)
@ -3090,9 +3121,9 @@
LOC 3 eLOC 2 lLOC 1 Comment 9 Lines 3 LOC 3 eLOC 2 lLOC 1 Comment 9 Lines 3
Function: QP::QXThread::queueGet Function: QP::QXThread::queueGet
Parameters: (uint_fast16_t const nTicks, uint_fast8_t const tickRate) Parameters: (uint_fast16_t const nTicks)
Complexity Param 2 Return 1 Cyclo Vg 8 Total 11 Complexity Param 1 Return 1 Cyclo Vg 8 Total 10
LOC 61 eLOC 53 lLOC 34 Comment 55 Lines 88 LOC 61 eLOC 54 lLOC 34 Comment 53 Lines 88
Function: QP::QXThread::block_ Function: QP::QXThread::block_
Parameters: (void) Parameters: (void)
@ -3105,10 +3136,9 @@
LOC 8 eLOC 5 lLOC 2 Comment 9 Lines 9 LOC 8 eLOC 5 lLOC 2 Comment 9 Lines 9
Function: QP::QXThread::teArm_ Function: QP::QXThread::teArm_
Parameters: (enum_t const sig, uint_fast16_t const nTicks, uint_fast8_t Parameters: (enum_t const sig, uint_fast16_t const nTicks)
const tickRate) Complexity Param 2 Return 1 Cyclo Vg 3 Total 6
Complexity Param 3 Return 1 Cyclo Vg 3 Total 7 LOC 18 eLOC 14 lLOC 8 Comment 20 Lines 33
LOC 16 eLOC 11 lLOC 7 Comment 21 Lines 32
Function: QP::QXThread::teDisarm_ Function: QP::QXThread::teDisarm_
Parameters: (void) Parameters: (void)
@ -3116,9 +3146,9 @@
LOC 11 eLOC 8 lLOC 5 Comment 10 Lines 14 LOC 11 eLOC 8 lLOC 5 Comment 10 Lines 14
Function: QP::QXThread::delay Function: QP::QXThread::delay
Parameters: (uint_fast16_t const nTicks, uint_fast8_t const tickRate) Parameters: (uint_fast16_t const nTicks)
Complexity Param 2 Return 1 Cyclo Vg 4 Total 7 Complexity Param 1 Return 1 Cyclo Vg 4 Total 6
LOC 20 eLOC 18 lLOC 13 Comment 17 Lines 35 LOC 20 eLOC 19 lLOC 13 Comment 17 Lines 34
Function: QP::QXThread::delayCancel Function: QP::QXThread::delayCancel
Parameters: (void) Parameters: (void)
@ -3126,26 +3156,26 @@
LOC 14 eLOC 11 lLOC 7 Comment 2 Lines 16 LOC 14 eLOC 11 lLOC 7 Comment 2 Lines 16
Total: Functions Total: Functions
LOC 2584 eLOC 2142 lLOC 1274 InCmp 340 CycloCmp 439 LOC 2741 eLOC 2285 lLOC 1364 InCmp 344 CycloCmp 466
Function Points FP(LOC) 43.8 FP(eLOC) 36.8 FP(lLOC) 22.2 Function Points FP(LOC) 46.7 FP(eLOC) 39.5 FP(lLOC) 23.8
------------------------------------------------------------------------ ------------------------------------------------------------------------
~~ Project Functional Analysis ~~ ~~ Project Functional Analysis ~~
Total Functions .......: 173 Total Physical Lines ..: 3511 Total Functions .......: 177 Total Physical Lines ..: 3793
Total LOC .............: 2584 Total Function Pts LOC : 43.8 Total LOC .............: 2741 Total Function Pts LOC : 46.7
Total eLOC ............: 2142 Total Function Pts eLOC: 36.8 Total eLOC ............: 2285 Total Function Pts eLOC: 39.5
Total lLOC.............: 1274 Total Function Pts lLOC: 22.2 Total lLOC.............: 1364 Total Function Pts lLOC: 23.8
Total Cyclomatic Comp. : 439 Total Interface Comp. .: 340 Total Cyclomatic Comp. : 466 Total Interface Comp. .: 344
Total Parameters ......: 167 Total Return Points ...: 173 Total Parameters ......: 167 Total Return Points ...: 177
Total Comment Lines ...: 2516 Total Blank Lines .....: 465 Total Comment Lines ...: 2682 Total Blank Lines .....: 513
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Avg Physical Lines ....: 20.29 Avg Physical Lines ....: 21.43
Avg LOC ...............: 14.94 Avg eLOC ..............: 12.38 Avg LOC ...............: 15.49 Avg eLOC ..............: 12.91
Avg lLOC ..............: 7.36 Avg Cyclomatic Comp. ..: 2.54 Avg lLOC ..............: 7.71 Avg Cyclomatic Comp. ..: 2.63
Avg Interface Comp. ...: 1.97 Avg Parameters ........: 0.97 Avg Interface Comp. ...: 1.94 Avg Parameters ........: 0.94
Avg Return Points .....: 1.00 Avg Comment Lines .....: 14.54 Avg Return Points .....: 1.00 Avg Comment Lines .....: 15.15
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
Max LOC ...............: 117 Max LOC ...............: 117
Max eLOC ..............: 100 Max lLOC ..............: 61 Max eLOC ..............: 100 Max lLOC ..............: 61

View File

@ -0,0 +1,8 @@
namespace DPP {
// local extended-thread objects .............................................
static void Thread1_run(QP::QXThread * const me); // run routine for Thread1
static QP::QXThread l_test1(&Thread1_run, 0U); //<== QXThread::QXThread() ctor
. . .
} // namespace DPP

View File

@ -0,0 +1,21 @@
namespace DPP {
extern QP::QXThread * const XT_Test1;
} // namespace DPP
int main() {
// stacks and queues for the extended test threads
static QP::QEvt const *test1QueueSto[5];
static uint64_t test1StackSto[64];
// start the extended Test1 thread
// start the extended Test1 thread
DPP::XT_Test1->start(
static_cast<uint_fast8_t>(1), // QP prio of the thread
test1QueueSto, // event queue storage
Q_DIM(test1QueueSto), // queue length [events]
test1StackSto, // stack storage
sizeof(test1StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event
. . .
}

View File

@ -100,6 +100,7 @@
<tRSysVw>1</tRSysVw> <tRSysVw>1</tRSysVw>
<sRunDeb>0</sRunDeb> <sRunDeb>0</sRunDeb>
<sLrtime>0</sLrtime> <sLrtime>0</sLrtime>
<bEvRecOn>1</bEvRecOn>
<nTsel>3</nTsel> <nTsel>3</nTsel>
<sDll></sDll> <sDll></sDll>
<sDllPa></sDllPa> <sDllPa></sDllPa>
@ -199,9 +200,16 @@
<LintExecutable></LintExecutable> <LintExecutable></LintExecutable>
<LintConfigFile></LintConfigFile> <LintConfigFile></LintConfigFile>
<bLintAuto>0</bLintAuto> <bLintAuto>0</bLintAuto>
<Lin2Executable></Lin2Executable> <bAutoGenD>0</bAutoGenD>
<Lin2ConfigFile></Lin2ConfigFile> <LntExFlags>0</LntExFlags>
<bLin2Auto>0</bLin2Auto> <pMisraName></pMisraName>
<pszMrule></pszMrule>
<pSingCmds></pSingCmds>
<pMultCmds></pMultCmds>
<pMisraNamep></pMisraNamep>
<pszMrulep></pszMrulep>
<pSingCmdsp></pSingCmdsp>
<pMultCmdsp></pMultCmdsp>
</TargetOption> </TargetOption>
</Target> </Target>
@ -284,6 +292,7 @@
<tRSysVw>1</tRSysVw> <tRSysVw>1</tRSysVw>
<sRunDeb>0</sRunDeb> <sRunDeb>0</sRunDeb>
<sLrtime>0</sLrtime> <sLrtime>0</sLrtime>
<bEvRecOn>1</bEvRecOn>
<nTsel>3</nTsel> <nTsel>3</nTsel>
<sDll></sDll> <sDll></sDll>
<sDllPa></sDllPa> <sDllPa></sDllPa>
@ -383,9 +392,16 @@
<LintExecutable></LintExecutable> <LintExecutable></LintExecutable>
<LintConfigFile></LintConfigFile> <LintConfigFile></LintConfigFile>
<bLintAuto>0</bLintAuto> <bLintAuto>0</bLintAuto>
<Lin2Executable></Lin2Executable> <bAutoGenD>0</bAutoGenD>
<Lin2ConfigFile></Lin2ConfigFile> <LntExFlags>0</LntExFlags>
<bLin2Auto>0</bLin2Auto> <pMisraName></pMisraName>
<pszMrule></pszMrule>
<pSingCmds></pSingCmds>
<pMultCmds></pMultCmds>
<pMisraNamep></pMisraNamep>
<pszMrulep></pszMrulep>
<pSingCmdsp></pSingCmdsp>
<pMultCmdsp></pMultCmdsp>
</TargetOption> </TargetOption>
</Target> </Target>
@ -468,6 +484,7 @@
<tRSysVw>1</tRSysVw> <tRSysVw>1</tRSysVw>
<sRunDeb>0</sRunDeb> <sRunDeb>0</sRunDeb>
<sLrtime>0</sLrtime> <sLrtime>0</sLrtime>
<bEvRecOn>1</bEvRecOn>
<nTsel>3</nTsel> <nTsel>3</nTsel>
<sDll></sDll> <sDll></sDll>
<sDllPa></sDllPa> <sDllPa></sDllPa>
@ -579,9 +596,16 @@
<LintExecutable></LintExecutable> <LintExecutable></LintExecutable>
<LintConfigFile></LintConfigFile> <LintConfigFile></LintConfigFile>
<bLintAuto>0</bLintAuto> <bLintAuto>0</bLintAuto>
<Lin2Executable></Lin2Executable> <bAutoGenD>0</bAutoGenD>
<Lin2ConfigFile></Lin2ConfigFile> <LntExFlags>0</LntExFlags>
<bLin2Auto>0</bLin2Auto> <pMisraName></pMisraName>
<pszMrule></pszMrule>
<pSingCmds></pSingCmds>
<pMultCmds></pMultCmds>
<pMisraNamep></pMisraNamep>
<pszMrulep></pszMrulep>
<pSingCmdsp></pSingCmdsp>
<pMultCmdsp></pMultCmdsp>
</TargetOption> </TargetOption>
</Target> </Target>

View File

@ -10,7 +10,8 @@
<TargetName>blinky-dbg</TargetName> <TargetName>blinky-dbg</TargetName>
<ToolsetNumber>0x4</ToolsetNumber> <ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName> <ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>5060183::V5.06 update 2 (build 183)::ARMCC</pCCUsed> <pCCUsed>5060528::V5.06 update 5 (build 528)::ARMCC</pCCUsed>
<uAC6>0</uAC6>
<TargetOption> <TargetOption>
<TargetCommonOption> <TargetCommonOption>
<Device>EFM32PG1B200F256GM48</Device> <Device>EFM32PG1B200F256GM48</Device>
@ -330,6 +331,7 @@
<vShortWch>0</vShortWch> <vShortWch>0</vShortWch>
<v6Lto>0</v6Lto> <v6Lto>0</v6Lto>
<v6WtE>0</v6WtE> <v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define> <Define>EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define>
@ -347,6 +349,7 @@
<NoWarn>0</NoWarn> <NoWarn>0</NoWarn>
<uSurpInc>1</uSurpInc> <uSurpInc>1</uSurpInc>
<useXO>0</useXO> <useXO>0</useXO>
<uClangAs>0</uClangAs>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>Stack_Size=1024 Heap_Size=16</Define> <Define>Stack_Size=1024 Heap_Size=16</Define>
@ -566,6 +569,7 @@
<vShortWch>0</vShortWch> <vShortWch>0</vShortWch>
<v6Lto>0</v6Lto> <v6Lto>0</v6Lto>
<v6WtE>0</v6WtE> <v6WtE>0</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define></Define> <Define></Define>
@ -583,6 +587,7 @@
<NoWarn>2</NoWarn> <NoWarn>2</NoWarn>
<uSurpInc>2</uSurpInc> <uSurpInc>2</uSurpInc>
<useXO>2</useXO> <useXO>2</useXO>
<uClangAs>2</uClangAs>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define></Define> <Define></Define>
@ -621,7 +626,8 @@
<TargetName>blinky-rel</TargetName> <TargetName>blinky-rel</TargetName>
<ToolsetNumber>0x4</ToolsetNumber> <ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName> <ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>5060183::V5.06 update 2 (build 183)::ARMCC</pCCUsed> <pCCUsed>5060528::V5.06 update 5 (build 528)::ARMCC</pCCUsed>
<uAC6>0</uAC6>
<TargetOption> <TargetOption>
<TargetCommonOption> <TargetCommonOption>
<Device>EFM32PG1B200F256GM48</Device> <Device>EFM32PG1B200F256GM48</Device>
@ -941,11 +947,12 @@
<vShortWch>0</vShortWch> <vShortWch>0</vShortWch>
<v6Lto>0</v6Lto> <v6Lto>0</v6Lto>
<v6WtE>0</v6WtE> <v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>NDEBUG EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define> <Define>NDEBUG EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\src\qf;..\..\..\..\..\ports\arm-cm\qv\arm;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath> <IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\src;..\..\..\..\..\ports\arm-cm\qv\arm;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls> </VariousControls>
</Cads> </Cads>
<Aads> <Aads>
@ -958,6 +965,7 @@
<NoWarn>0</NoWarn> <NoWarn>0</NoWarn>
<uSurpInc>1</uSurpInc> <uSurpInc>1</uSurpInc>
<useXO>0</useXO> <useXO>0</useXO>
<uClangAs>0</uClangAs>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>Stack_Size=1024 Heap_Size=16</Define> <Define>Stack_Size=1024 Heap_Size=16</Define>
@ -1177,6 +1185,7 @@
<vShortWch>0</vShortWch> <vShortWch>0</vShortWch>
<v6Lto>0</v6Lto> <v6Lto>0</v6Lto>
<v6WtE>0</v6WtE> <v6WtE>0</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define></Define> <Define></Define>
@ -1194,6 +1203,7 @@
<NoWarn>2</NoWarn> <NoWarn>2</NoWarn>
<uSurpInc>2</uSurpInc> <uSurpInc>2</uSurpInc>
<useXO>2</useXO> <useXO>2</useXO>
<uClangAs>2</uClangAs>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define></Define> <Define></Define>
@ -1232,7 +1242,8 @@
<TargetName>blinky-spy</TargetName> <TargetName>blinky-spy</TargetName>
<ToolsetNumber>0x4</ToolsetNumber> <ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName> <ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>5060183::V5.06 update 2 (build 183)::ARMCC</pCCUsed> <pCCUsed>5060528::V5.06 update 5 (build 528)::ARMCC</pCCUsed>
<uAC6>0</uAC6>
<TargetOption> <TargetOption>
<TargetCommonOption> <TargetCommonOption>
<Device>EFM32PG1B200F256GM48</Device> <Device>EFM32PG1B200F256GM48</Device>
@ -1552,11 +1563,12 @@
<vShortWch>0</vShortWch> <vShortWch>0</vShortWch>
<v6Lto>0</v6Lto> <v6Lto>0</v6Lto>
<v6WtE>0</v6WtE> <v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>Q_SPY EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define> <Define>Q_SPY EFM32PG1B200F256GM48=1 __FPU_PRESENT</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\src\qf;..\..\..\..\..\ports\arm-cm\qv\arm;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath> <IncludePath>..\..;..\..\..\..\..\include;..\..\..\..\..\src;..\..\..\..\..\ports\arm-cm\qv\arm;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls> </VariousControls>
</Cads> </Cads>
<Aads> <Aads>
@ -1569,6 +1581,7 @@
<NoWarn>0</NoWarn> <NoWarn>0</NoWarn>
<uSurpInc>1</uSurpInc> <uSurpInc>1</uSurpInc>
<useXO>0</useXO> <useXO>0</useXO>
<uClangAs>0</uClangAs>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>Stack_Size=1024 Heap_Size=16</Define> <Define>Stack_Size=1024 Heap_Size=16</Define>
@ -1775,4 +1788,10 @@
</Target> </Target>
</Targets> </Targets>
<RTE>
<apis/>
<components/>
<files/>
</RTE>
</Project> </Project>

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, EFM32-SLSTK3401A board, preemptive QK kernel // Product: DPP example, EFM32-SLSTK3401A board, preemptive QK kernel
// Last Updated for Version: 5.9.5 // Last Updated for Version: 5.9.7
// Date of the Last Update: 2017-07-20 // Date of the Last Update: 2017-08-18
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -77,7 +77,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
#define PB1_PIN 7 #define PB1_PIN 7
static uint32_t l_rnd; // random seed static uint32_t l_rnd; // random seed
static QP::QMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -265,20 +264,19 @@ uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the random-seed mutex QP::QSchedStatus lockStat = QP::QK::schedLock(N_PHILO); // protect l_rnd
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the random-seed mutex QP::QK::schedUnlock(lockStat); // sched unlock around l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rnd = seed; l_rnd = seed;
l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority
} }
//............................................................................ //............................................................................

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, EFM32-SLSTK3401A board, preemptive QXK kernel // Product: DPP example, EFM32-SLSTK3401A board, preemptive QXK kernel
// Last Updated for Version: 5.9.5 // Last Updated for Version: 5.9.7
// Date of the Last Update: 2017-07-20 // Date of the Last Update: 2017-08-19
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -77,7 +77,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
#define PB1_PIN 7 #define PB1_PIN 7
static uint32_t l_rnd; // random seed static uint32_t l_rnd; // random seed
static QP::QXMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -89,11 +88,6 @@ static QP::QXMutex l_rndMutex; // to protect the random number generator
static uint8_t const l_GPIO_EVEN_IRQHandler = (uint8_t)0; static uint8_t const l_GPIO_EVEN_IRQHandler = (uint8_t)0;
static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL)); static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL));
#define UART_BAUD_RATE 115200U
#define UART_FR_TXFE (1U << 7)
#define UART_FR_RXFE (1U << 4)
#define UART_TXFIFO_DEPTH 16U
enum AppRecords { // application-specific trace records enum AppRecords { // application-specific trace records
PHILO_STAT = QP::QS_USER, PHILO_STAT = QP::QS_USER,
PAUSED_STAT, PAUSED_STAT,
@ -262,19 +256,18 @@ uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the random-seed mutex QP::QSchedStatus lockStat = QP::QXK::schedLock(N_PHILO); // protect l_rnd
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the random-seed mutex QP::QXK::schedUnlock(lockStat); // sched unlock around l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority
l_rnd = seed; l_rnd = seed;
} }
//............................................................................ //............................................................................
@ -301,7 +294,7 @@ void QF::onStartup(void) {
// set up the SysTick timer to fire at BSP::TICKS_PER_SEC rate // set up the SysTick timer to fire at BSP::TICKS_PER_SEC rate
SysTick_Config(SystemCoreClock / DPP::BSP::TICKS_PER_SEC); SysTick_Config(SystemCoreClock / DPP::BSP::TICKS_PER_SEC);
// assing all priority bits for preemption-prio. and none to sub-prio. // assingn all priority bits for preemption-prio. and none to sub-prio.
NVIC_SetPriorityGrouping(0U); NVIC_SetPriorityGrouping(0U);
// set priorities of ALL ISRs used in the system, see NOTE00 // set priorities of ALL ISRs used in the system, see NOTE00

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.8.3 // Last updated for version 5.9.7
// Last updated on 2017-03-13 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -64,7 +64,8 @@ int main() {
QS_OBJ_DICTIONARY(philoQueueSto[3]); QS_OBJ_DICTIONARY(philoQueueSto[3]);
QS_OBJ_DICTIONARY(philoQueueSto[4]); QS_OBJ_DICTIONARY(philoQueueSto[4]);
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe // init publish-subscribe
QP::QF::psInit(subscrSto, Q_DIM(subscrSto));
// initialize event pools... // initialize event pools...
QP::QF::poolInit(smlPoolSto, QP::QF::poolInit(smlPoolSto,
@ -79,32 +80,39 @@ int main() {
sizeof(test1StackSto), // stack size [bytes] sizeof(test1StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
// NOTE: leave priority 2 free for a mutex
// start the Philo active objects... // start the Philo active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start( DPP::AO_Philo[n]->start(
static_cast<uint_fast8_t>(n + 2), // QP priority of the AO static_cast<uint_fast8_t>(n + 3), // QP priority of the AO
philoQueueSto[n], // event queue storage philoQueueSto[n], // event queue storage
Q_DIM(philoQueueSto[n]), // queue length [events] Q_DIM(philoQueueSto[n]), // queue length [events]
static_cast<void *>(0), // no stack storage static_cast<void *>(0), // no stack storage
static_cast<uint_fast16_t>(0), // stack size [bytes] static_cast<uint_fast16_t>(0), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
} }
// example of prioritizing the Ticker0 active object // example of prioritizing the Ticker0 active object
DPP::the_Ticker0->start((uint_fast8_t)(N_PHILO + 2U), // priority DPP::the_Ticker0->start((uint_fast8_t)(N_PHILO + 3), // priority
0, 0, 0, 0,
0, 0); 0, 0);
// NOTE: leave priority (N_PHILO + 4) free for mutex
// start the extended Test2 thread // start the extended Test2 thread
DPP::XT_Test2->start( DPP::XT_Test2->start(
static_cast<uint_fast8_t>(N_PHILO + 3), // QP prio of the thread static_cast<uint_fast8_t>(N_PHILO + 5), // QP prio of the thread
test2QueueSto, // event queue storage test2QueueSto, // event queue storage
Q_DIM(test2QueueSto), // queue length [events] Q_DIM(test2QueueSto), // queue length [events]
test2StackSto, // stack storage test2StackSto, // stack storage
sizeof(test2StackSto), // stack size [bytes] sizeof(test2StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
// NOTE: leave priority (N_PHILO + 6) free for mutex
DPP::AO_Table->start( DPP::AO_Table->start(
static_cast<uint_fast8_t>(N_PHILO + 4), // QP priority of the AO static_cast<uint_fast8_t>(N_PHILO + 7), // QP priority of the AO
tableQueueSto, // event queue storage tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events] Q_DIM(tableQueueSto), // queue length [events]
static_cast<void *>(0), // no stack storage static_cast<void *>(0), // no stack storage

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.9.6 // Last updated for version 5.9.7
// Last updated on 2017-07-27 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -67,25 +67,30 @@ static void Thread1_run(QP::QXThread * const me) {
me->m_thread = &l_tls1; // initialize the TLS for Thread1 me->m_thread = &l_tls1; // initialize the TLS for Thread1
l_mutex.init(3U);
for (;;) { for (;;) {
l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex
// wait on a semaphore (BLOCK with timeout)
(void)l_sema.wait(BSP::TICKS_PER_SEC, 0U);
BSP::ledOn(); BSP::ledOn();
l_mutex.lock(); // exercise the mutex if (l_mutex.tryLock()) { // exercise the mutex
// some flating point code to exercise the VFP... float volatile x;
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 // some flating point code to exercise the VFP...
x = 1.4142135F;
x = x * 1.4142135F;
(void)l_sema.signal(); // signal Thread2
QP::QXThread::delay(10U); // BLOCK while holding a mutex
l_mutex.unlock();
}
l_mutex.unlock();
BSP::ledOff();
QP::QXThread::delay(BSP::TICKS_PER_SEC/7); // BLOCK
// publish to Thread2 // publish to Thread2
QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), &l_test1); //QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), &l_test1);
// test TLS // test TLS
lib_fun(1U); lib_fun(1U);
@ -95,34 +100,31 @@ static void Thread1_run(QP::QXThread * const me) {
//............................................................................ //............................................................................
static void Thread2_run(QP::QXThread * const me) { static void Thread2_run(QP::QXThread * const me) {
// initialize the semaphore before using it
// NOTE: Here 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, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
// initialize the mutex before using it
// NOTE: Here the semaphore is initialized in the highest-priority thread
// that uses it. Alternatively, the semaphore can be initialized
// before any thread runs.
l_mutex.init(N_PHILO + 6U);
me->m_thread = &l_tls2; // initialize the TLS for Thread2 me->m_thread = &l_tls2; // initialize the TLS for Thread2
// subscribe to the test signal */ // subscribe to the test signal */
me->subscribe(TEST_SIG); me->subscribe(TEST_SIG);
// initialize the semaphore before using it
// 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, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
for (;;) { for (;;) {
// some flating point code to exercise the VFP... // wait on a semaphore (BLOCK indefinitely)
float volatile x = 1.4142135F; l_sema.wait();
x = x * 1.4142135F;
// wait on the internal event queue (BLOCK) with timeout l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex
QP::QEvt const *e = me->queueGet(BSP::TICKS_PER_SEC/2, 0U); QP::QXThread::delay(1U); // wait more (BLOCK)
BSP::ledOff(); l_mutex.unlock();
if (e != static_cast<QP::QEvt *>(0)) { // event actually delivered?
QP::QF::gc(e); // recycle the event manually!
}
else {
QP::QXThread::delay(BSP::TICKS_PER_SEC/2, 0U); // BLOCK
l_sema.signal(); // signal Thread1
}
// test TLS // test TLS
lib_fun(2U); lib_fun(2U);

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// Product: DPP example // Product: DPP example
// Last Updated for Version: 5.6.0 // Last Updated for Version: 5.8.1
// Date of the Last Update: 2015-12-28 // Date of the Last Update: 2016-12-12
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -46,7 +46,7 @@ public:
static void terminate(int16_t const result); static void terminate(int16_t const result);
static void randomSeed(uint32_t const seed); // random seed static void randomSeed(uint32_t const seed); // random seed
static uint32_t random(void); // pseudo-random generator static uint32_t random(void); // pseudo-random generator
// for testing... // for testing...
static void wait4SW1(void); static void wait4SW1(void);
@ -54,6 +54,8 @@ public:
static void ledOff(void); static void ledOff(void);
}; };
extern QP::QActive *the_Ticker0;
} // namespace DPP } // namespace DPP
#endif // bsp_h #endif // bsp_h

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, EK-TM4C123GXL board, preemptive QK kernel // Product: DPP example, EK-TM4C123GXL board, preemptive QK kernel
// Last updated for version 5.9.5 // Last updated for version 5.9.7
// Last updated on 2017-07-20 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -76,7 +76,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
#define BTN_SW2 (1U << 0) #define BTN_SW2 (1U << 0)
static uint32_t l_rnd; // random seed static uint32_t l_rnd; // random seed
static QP::QMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -257,19 +256,19 @@ uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the shared random seed // lock the scheduler around l_rnd up to the (N_PHILO + 1U) ceiling
QP::QSchedStatus lockStat = QP::QK::schedLock(N_PHILO + 1U);
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the shared random seed QP::QK::schedUnlock(lockStat); // unlock sched after accessing l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority
l_rnd = seed; l_rnd = seed;
} }
//............................................................................ //............................................................................

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, EK-TM4C123GXL board, preemptive QXK kernel // Product: DPP example, EK-TM4C123GXL board, preemptive QXK kernel
// Last updated for version 5.9.5 // Last Updated for Version: 5.9.7
// Last updated on 2017-07-20 // Date of the Last Update: 2017-08-19
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -76,7 +76,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
#define BTN_SW2 (1U << 0) #define BTN_SW2 (1U << 0)
static uint32_t l_rnd; // random seed static uint32_t l_rnd; // random seed
static QP::QXMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -241,23 +240,22 @@ void BSP::displayPaused(uint8_t paused) {
} }
//............................................................................ //............................................................................
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
// The flating point code is to exercise the FPU // Some flating point code is to exercise the VFP...
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the shared random seed QP::QSchedStatus lockStat = QP::QXK::schedLock(N_PHILO); // protect l_rnd
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the shared random seed QP::QXK::schedUnlock(lockStat); // sched unlock around l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority
l_rnd = seed; l_rnd = seed;
} }
//............................................................................ //............................................................................
@ -284,7 +282,7 @@ void QF::onStartup(void) {
// set up the SysTick timer to fire at BSP::TICKS_PER_SEC rate // set up the SysTick timer to fire at BSP::TICKS_PER_SEC rate
SysTick_Config(SystemCoreClock / DPP::BSP::TICKS_PER_SEC); SysTick_Config(SystemCoreClock / DPP::BSP::TICKS_PER_SEC);
// assing all priority bits for preemption-prio. and none to sub-prio. // assingn all priority bits for preemption-prio. and none to sub-prio.
NVIC_SetPriorityGrouping(0U); NVIC_SetPriorityGrouping(0U);
// set priorities of ALL ISRs used in the system, see NOTE00 // set priorities of ALL ISRs used in the system, see NOTE00

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.7.2 // Last updated for version 5.9.7
// Last updated on 2016-09-28 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -35,6 +35,9 @@
#include "dpp.h" #include "dpp.h"
#include "bsp.h" #include "bsp.h"
static QP::QTicker l_ticker0(0); // ticker for tick rate 0
QP::QActive *DPP::the_Ticker0 = &l_ticker0;
//............................................................................ //............................................................................
int main() { int main() {
static QP::QEvt const *tableQueueSto[N_PHILO]; static QP::QEvt const *tableQueueSto[N_PHILO];
@ -61,7 +64,8 @@ int main() {
QS_OBJ_DICTIONARY(philoQueueSto[3]); QS_OBJ_DICTIONARY(philoQueueSto[3]);
QS_OBJ_DICTIONARY(philoQueueSto[4]); QS_OBJ_DICTIONARY(philoQueueSto[4]);
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe // init publish-subscribe
QP::QF::psInit(subscrSto, Q_DIM(subscrSto));
// initialize event pools... // initialize event pools...
QP::QF::poolInit(smlPoolSto, QP::QF::poolInit(smlPoolSto,
@ -76,10 +80,12 @@ int main() {
sizeof(test1StackSto), // stack size [bytes] sizeof(test1StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
// NOTE: leave priority 2 free for a mutex
// start the Philo active objects... // start the Philo active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start( DPP::AO_Philo[n]->start(
static_cast<uint_fast8_t>(n + 2), // QP priority of the AO static_cast<uint_fast8_t>(n + 3), // QP priority of the AO
philoQueueSto[n], // event queue storage philoQueueSto[n], // event queue storage
Q_DIM(philoQueueSto[n]), // queue length [events] Q_DIM(philoQueueSto[n]), // queue length [events]
static_cast<void *>(0), // no stack storage static_cast<void *>(0), // no stack storage
@ -87,17 +93,26 @@ int main() {
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
} }
// example of prioritizing the Ticker0 active object
DPP::the_Ticker0->start((uint_fast8_t)(N_PHILO + 3), // priority
0, 0,
0, 0);
// NOTE: leave priority (N_PHILO + 4) free for mutex
// start the extended Test2 thread // start the extended Test2 thread
DPP::XT_Test2->start( DPP::XT_Test2->start(
static_cast<uint_fast8_t>(N_PHILO + 2), // QP prio of the thread static_cast<uint_fast8_t>(N_PHILO + 5), // QP prio of the thread
test2QueueSto, // event queue storage test2QueueSto, // event queue storage
Q_DIM(test2QueueSto), // queue length [events] Q_DIM(test2QueueSto), // queue length [events]
test2StackSto, // stack storage test2StackSto, // stack storage
sizeof(test2StackSto), // stack size [bytes] sizeof(test2StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
// NOTE: leave priority (N_PHILO + 6) free for mutex
DPP::AO_Table->start( DPP::AO_Table->start(
static_cast<uint_fast8_t>(N_PHILO + 3), // QP priority of the AO static_cast<uint_fast8_t>(N_PHILO + 7), // QP priority of the AO
tableQueueSto, // event queue storage tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events] Q_DIM(tableQueueSto), // queue length [events]
static_cast<void *>(0), // no stack storage static_cast<void *>(0), // no stack storage

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.9.6 // Last updated for version 5.9.7
// Last updated on 2017-07-27 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -50,60 +50,84 @@ static QP::QXSemaphore l_sema;
QP::QXThread * const XT_Test1 = &l_test1; QP::QXThread * const XT_Test1 = &l_test1;
QP::QXThread * const XT_Test2 = &l_test2; QP::QXThread * const XT_Test2 = &l_test2;
//............................................................................ // Thread-Local Storage for the "extended" threads ...........................
static void Thread1_run(QP::QXThread * const /*me*/) { struct TLS_test {
uint32_t foo;
uint8_t bar[10];
};
static TLS_test l_tls1;
static TLS_test l_tls2;
l_mutex.init(3U); static void lib_fun(uint32_t x) {
QXK_TLS(TLS_test *)->foo = x;
}
//............................................................................
static void Thread1_run(QP::QXThread * const me) {
me->m_thread = &l_tls1; // initialize the TLS for Thread1
for (;;) { for (;;) {
l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex
// wait on a semaphore (BLOCK with timeout)
(void)l_sema.wait(BSP::TICKS_PER_SEC, 0U);
BSP::ledOn(); BSP::ledOn();
l_mutex.lock(); // exercise the mutex if (l_mutex.tryLock()) { // exercise the mutex
// some flating point code to exercise the VFP... float volatile x;
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 // some flating point code to exercise the VFP...
x = 1.4142135F;
x = x * 1.4142135F;
(void)l_sema.signal(); // signal Thread2
QP::QXThread::delay(10U); // BLOCK while holding a mutex
l_mutex.unlock();
}
l_mutex.unlock();
BSP::ledOff();
QP::QXThread::delay(BSP::TICKS_PER_SEC/7); // BLOCK
// publish to Thread2 // publish to Thread2
QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), &l_test1); //QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), &l_test1);
// test TLS
lib_fun(1U);
} }
} }
//............................................................................ //............................................................................
static void Thread2_run(QP::QXThread * const me) { static void Thread2_run(QP::QXThread * const me) {
// initialize the semaphore before using it
// NOTE: Here 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, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
// initialize the mutex before using it
// NOTE: Here the semaphore is initialized in the highest-priority thread
// that uses it. Alternatively, the semaphore can be initialized
// before any thread runs.
l_mutex.init(N_PHILO + 6U);
me->m_thread = &l_tls2; // initialize the TLS for Thread2
// subscribe to the test signal */ // subscribe to the test signal */
me->subscribe(TEST_SIG); me->subscribe(TEST_SIG);
// initialize the semaphore before using it
// 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, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
for (;;) { for (;;) {
// some flating point code to exercise the VFP... // wait on a semaphore (BLOCK indefinitely)
float volatile x = 1.4142135F; l_sema.wait();
x = x * 1.4142135F;
// wait on the internal event queue (BLOCK) with timeout l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex
QP::QEvt const *e = me->queueGet(BSP::TICKS_PER_SEC/2, 0U); QP::QXThread::delay(1U); // wait more (BLOCK)
BSP::ledOff(); l_mutex.unlock();
if (e != static_cast<QP::QEvt *>(0)) { // event actually delivered? // test TLS
QP::QF::gc(e); // recycle the event manually! lib_fun(2U);
}
else {
QP::QXThread::delay(BSP::TICKS_PER_SEC/2, 0U); // BLOCK
l_sema.signal(); // signal Thread1
}
} }
} }

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// Product: DPP example // Product: DPP example
// Last Updated for Version: 5.6.0 // Last Updated for Version: 5.8.1
// Date of the Last Update: 2015-12-28 // Date of the Last Update: 2016-12-12
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -46,7 +46,7 @@ public:
static void terminate(int16_t const result); static void terminate(int16_t const result);
static void randomSeed(uint32_t const seed); // random seed static void randomSeed(uint32_t const seed); // random seed
static uint32_t random(void); // pseudo-random generator static uint32_t random(void); // pseudo-random generator
// for testing... // for testing...
static void wait4SW1(void); static void wait4SW1(void);
@ -54,6 +54,8 @@ public:
static void ledOff(void); static void ledOff(void);
}; };
extern QP::QActive *the_Ticker0;
} // namespace DPP } // namespace DPP
#endif // bsp_h #endif // bsp_h

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, STM32 NUCLEO-L053R8 board, preemptive QK kernel // Product: DPP example, STM32 NUCLEO-L053R8 board, preemptive QK kernel
// Last updated for version 5.9.5 // Last updated for version 5.9.7
// Last updated on 2016-07-20 // Last updated on 2016-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -71,7 +71,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
#define BTN_B1 (1U << 13) #define BTN_B1 (1U << 13)
static unsigned l_rnd; // random seed static unsigned l_rnd; // random seed
static QP::QMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -212,19 +211,19 @@ void BSP::displayPaused(uint8_t paused) {
} }
//............................................................................ //............................................................................
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
l_rndMutex.lock(); // lock the shared random seed // lock the scheduler around l_rnd up to the (N_PHILO + 1U) ceiling
QP::QSchedStatus lockStat = QP::QK::schedLock(N_PHILO + 1U);
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the shared random seed QP::QK::schedUnlock(lockStat); // unlock sched after accessing l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rndMutex.init(N_PHILO + 1U);
l_rnd = seed; l_rnd = seed;
} }
//............................................................................ //............................................................................

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, STM32 NUCLEO-L053R8 board, preemptive QXK kernel // Product: DPP example, STM32 NUCLEO-L053R8 board, preemptive QXK kernel
// Last updated for version 5.9.5 // Last Updated for Version: 5.9.7
// Last updated on 2017-07-20 // Date of the Last Update: 2017-08-19
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -71,7 +71,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
#define BTN_B1 (1U << 13) #define BTN_B1 (1U << 13)
static unsigned l_rnd; // random seed static unsigned l_rnd; // random seed
static QP::QXMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -111,7 +110,8 @@ void SysTick_Handler(void) {
} }
#endif #endif
QP::QF::TICK_X(0U, &l_SysTick_Handler); // process time events for rate 0 //QP::QF::TICK_X(0U, &l_SysTick_Handler); // process time events for rate 0
the_Ticker0->POST(0, &l_SysTick_Handler); // post to Ticker0 active object
// Perform the debouncing of buttons. The algorithm for debouncing // Perform the debouncing of buttons. The algorithm for debouncing
// adapted from the book "Embedded Systems Dictionary" by Jack Ganssle // adapted from the book "Embedded Systems Dictionary" by Jack Ganssle
@ -212,19 +212,18 @@ void BSP::displayPaused(uint8_t paused) {
} }
//............................................................................ //............................................................................
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
l_rndMutex.lock(); // lock the shared random seed QP::QSchedStatus lockStat = QP::QXK::schedLock(N_PHILO); // protect l_rnd
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the shared random seed QP::QXK::schedUnlock(lockStat); // sched unlock around l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rndMutex.init(N_PHILO + 1U);
l_rnd = seed; l_rnd = seed;
} }
//............................................................................ //............................................................................

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.7.2 // Last updated for version 5.9.7
// Last updated on 2016-09-28 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -35,6 +35,9 @@
#include "dpp.h" #include "dpp.h"
#include "bsp.h" #include "bsp.h"
static QP::QTicker l_ticker0(0); // ticker for tick rate 0
QP::QActive *DPP::the_Ticker0 = &l_ticker0;
//............................................................................ //............................................................................
int main() { int main() {
static QP::QEvt const *tableQueueSto[N_PHILO]; static QP::QEvt const *tableQueueSto[N_PHILO];
@ -61,7 +64,8 @@ int main() {
QS_OBJ_DICTIONARY(philoQueueSto[3]); QS_OBJ_DICTIONARY(philoQueueSto[3]);
QS_OBJ_DICTIONARY(philoQueueSto[4]); QS_OBJ_DICTIONARY(philoQueueSto[4]);
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe // init publish-subscribe
QP::QF::psInit(subscrSto, Q_DIM(subscrSto));
// initialize event pools... // initialize event pools...
QP::QF::poolInit(smlPoolSto, QP::QF::poolInit(smlPoolSto,
@ -76,10 +80,12 @@ int main() {
sizeof(test1StackSto), // stack size [bytes] sizeof(test1StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
// NOTE: leave priority 2 free for a mutex
// start the Philo active objects... // start the Philo active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start( DPP::AO_Philo[n]->start(
static_cast<uint_fast8_t>(n + 2), // QP priority of the AO static_cast<uint_fast8_t>(n + 3), // QP priority of the AO
philoQueueSto[n], // event queue storage philoQueueSto[n], // event queue storage
Q_DIM(philoQueueSto[n]), // queue length [events] Q_DIM(philoQueueSto[n]), // queue length [events]
static_cast<void *>(0), // no stack storage static_cast<void *>(0), // no stack storage
@ -87,17 +93,26 @@ int main() {
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
} }
// example of prioritizing the Ticker0 active object
DPP::the_Ticker0->start((uint_fast8_t)(N_PHILO + 3), // priority
0, 0,
0, 0);
// NOTE: leave priority (N_PHILO + 4) free for mutex
// start the extended Test2 thread // start the extended Test2 thread
DPP::XT_Test2->start( DPP::XT_Test2->start(
static_cast<uint_fast8_t>(N_PHILO + 2), // QP prio of the thread static_cast<uint_fast8_t>(N_PHILO + 5), // QP prio of the thread
test2QueueSto, // event queue storage test2QueueSto, // event queue storage
Q_DIM(test2QueueSto), // queue length [events] Q_DIM(test2QueueSto), // queue length [events]
test2StackSto, // stack storage test2StackSto, // stack storage
sizeof(test2StackSto), // stack size [bytes] sizeof(test2StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
// NOTE: leave priority (N_PHILO + 6) free for mutex
DPP::AO_Table->start( DPP::AO_Table->start(
static_cast<uint_fast8_t>(N_PHILO + 3), // QP priority of the AO static_cast<uint_fast8_t>(N_PHILO + 7), // QP priority of the AO
tableQueueSto, // event queue storage tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events] Q_DIM(tableQueueSto), // queue length [events]
static_cast<void *>(0), // no stack storage static_cast<void *>(0), // no stack storage

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.9.6 // Last updated for version 5.9.7
// Last updated on 2017-07-27 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -50,60 +50,84 @@ static QP::QXSemaphore l_sema;
QP::QXThread * const XT_Test1 = &l_test1; QP::QXThread * const XT_Test1 = &l_test1;
QP::QXThread * const XT_Test2 = &l_test2; QP::QXThread * const XT_Test2 = &l_test2;
//............................................................................ // Thread-Local Storage for the "extended" threads ...........................
static void Thread1_run(QP::QXThread * const /*me*/) { struct TLS_test {
uint32_t foo;
uint8_t bar[10];
};
static TLS_test l_tls1;
static TLS_test l_tls2;
l_mutex.init(3U); static void lib_fun(uint32_t x) {
QXK_TLS(TLS_test *)->foo = x;
}
//............................................................................
static void Thread1_run(QP::QXThread * const me) {
me->m_thread = &l_tls1; // initialize the TLS for Thread1
for (;;) { for (;;) {
l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex
// wait on a semaphore (BLOCK with timeout)
(void)l_sema.wait(BSP::TICKS_PER_SEC, 0U);
BSP::ledOn(); BSP::ledOn();
l_mutex.lock(); // exercise the mutex if (l_mutex.tryLock()) { // exercise the mutex
// some flating point code to exercise the VFP... float volatile x;
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 // some flating point code to exercise the VFP...
x = 1.4142135F;
x = x * 1.4142135F;
(void)l_sema.signal(); // signal Thread2
QP::QXThread::delay(10U); // BLOCK while holding a mutex
l_mutex.unlock();
}
l_mutex.unlock();
BSP::ledOff();
QP::QXThread::delay(BSP::TICKS_PER_SEC/7); // BLOCK
// publish to Thread2 // publish to Thread2
QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), &l_test1); //QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), &l_test1);
// test TLS
lib_fun(1U);
} }
} }
//............................................................................ //............................................................................
static void Thread2_run(QP::QXThread * const me) { static void Thread2_run(QP::QXThread * const me) {
// initialize the semaphore before using it
// NOTE: Here 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, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
// initialize the mutex before using it
// NOTE: Here the semaphore is initialized in the highest-priority thread
// that uses it. Alternatively, the semaphore can be initialized
// before any thread runs.
l_mutex.init(N_PHILO + 6U);
me->m_thread = &l_tls2; // initialize the TLS for Thread2
// subscribe to the test signal */ // subscribe to the test signal */
me->subscribe(TEST_SIG); me->subscribe(TEST_SIG);
// initialize the semaphore before using it
// 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, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
for (;;) { for (;;) {
// some flating point code to exercise the VFP... // wait on a semaphore (BLOCK indefinitely)
float volatile x = 1.4142135F; l_sema.wait();
x = x * 1.4142135F;
// wait on the internal event queue (BLOCK) with timeout l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex
QP::QEvt const *e = me->queueGet(BSP::TICKS_PER_SEC/2, 0U); QP::QXThread::delay(1U); // wait more (BLOCK)
BSP::ledOff(); l_mutex.unlock();
if (e != static_cast<QP::QEvt *>(0)) { // event actually delivered? // test TLS
QP::QF::gc(e); // recycle the event manually! lib_fun(2U);
}
else {
QP::QXThread::delay(BSP::TICKS_PER_SEC/2, 0U); // BLOCK
l_sema.signal(); // signal Thread1
}
} }
} }

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, STM32F4-Discovery board, preemptive QK kernel // Product: DPP example, STM32F4-Discovery board, preemptive QK kernel
// Last Updated for Version: 5.9.5 // Last Updated for Version: 5.9.7
// Date of the Last Update: 2017-07-20 // Date of the Last Update: 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -81,7 +81,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
#define BTN_B1 GPIO_Pin_0 #define BTN_B1 GPIO_Pin_0
static uint32_t l_rnd; // random seed static uint32_t l_rnd; // random seed
static QP::QMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -288,24 +287,24 @@ void BSP::displayPaused(uint8_t paused) {
} }
//............................................................................ //............................................................................
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
// Some flating point code is to exercise the VFP... // The flating point code is to exercise the FPU
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the random-seed mutex // lock the scheduler around l_rnd up to the (N_PHILO + 1U) ceiling
QP::QSchedStatus lockStat = QP::QK::schedLock(N_PHILO + 1U);
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the random-seed mutex QP::QK::schedUnlock(lockStat); // unlock sched after accessing l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rnd = seed; l_rnd = seed;
l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority
} }
//............................................................................ //............................................................................

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, STM32F4-Discovery board, dual-mode QXK kernel // Product: DPP example, STM32F4-Discovery board, dual-mode QXK kernel
// Last Updated for Version: 5.9.5 // Last Updated for Version: 5.9.7
// Date of the Last Update: 2017-07-20 // Date of the Last Update: 2017-08-19
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -81,7 +81,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
#define BTN_B1 GPIO_Pin_0 #define BTN_B1 GPIO_Pin_0
static uint32_t l_rnd; // random seed static uint32_t l_rnd; // random seed
static QP::QXMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -292,22 +291,20 @@ uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the random-seed mutex QP::QSchedStatus lockStat = QP::QXK::schedLock(N_PHILO); // protect l_rnd
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the random-seed mutex QP::QXK::schedUnlock(lockStat); // sched unlock around l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rnd = seed; l_rnd = seed;
l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority
} }
//............................................................................ //............................................................................
void BSP::terminate(int16_t result) { void BSP::terminate(int16_t result) {
(void)result; (void)result;

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.8.3 // Last updated for version 5.9.7
// Last updated on 2017-03-13 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -64,7 +64,8 @@ int main() {
QS_OBJ_DICTIONARY(philoQueueSto[3]); QS_OBJ_DICTIONARY(philoQueueSto[3]);
QS_OBJ_DICTIONARY(philoQueueSto[4]); QS_OBJ_DICTIONARY(philoQueueSto[4]);
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe // init publish-subscribe
QP::QF::psInit(subscrSto, Q_DIM(subscrSto));
// initialize event pools... // initialize event pools...
QP::QF::poolInit(smlPoolSto, QP::QF::poolInit(smlPoolSto,
@ -79,32 +80,39 @@ int main() {
sizeof(test1StackSto), // stack size [bytes] sizeof(test1StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
// NOTE: leave priority 2 free for a mutex
// start the Philo active objects... // start the Philo active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start( DPP::AO_Philo[n]->start(
static_cast<uint_fast8_t>(n + 2), // QP priority of the AO static_cast<uint_fast8_t>(n + 3), // QP priority of the AO
philoQueueSto[n], // event queue storage philoQueueSto[n], // event queue storage
Q_DIM(philoQueueSto[n]), // queue length [events] Q_DIM(philoQueueSto[n]), // queue length [events]
static_cast<void *>(0), // no stack storage static_cast<void *>(0), // no stack storage
static_cast<uint_fast16_t>(0), // stack size [bytes] static_cast<uint_fast16_t>(0), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
} }
// example of prioritizing the Ticker0 active object // example of prioritizing the Ticker0 active object
DPP::the_Ticker0->start((uint_fast8_t)(N_PHILO + 2U), // priority DPP::the_Ticker0->start((uint_fast8_t)(N_PHILO + 3), // priority
0, 0, 0, 0,
0, 0); 0, 0);
// NOTE: leave priority (N_PHILO + 4) free for mutex
// start the extended Test2 thread // start the extended Test2 thread
DPP::XT_Test2->start( DPP::XT_Test2->start(
static_cast<uint_fast8_t>(N_PHILO + 3), // QP prio of the thread static_cast<uint_fast8_t>(N_PHILO + 5), // QP prio of the thread
test2QueueSto, // event queue storage test2QueueSto, // event queue storage
Q_DIM(test2QueueSto), // queue length [events] Q_DIM(test2QueueSto), // queue length [events]
test2StackSto, // stack storage test2StackSto, // stack storage
sizeof(test2StackSto), // stack size [bytes] sizeof(test2StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
// NOTE: leave priority (N_PHILO + 6) free for mutex
DPP::AO_Table->start( DPP::AO_Table->start(
static_cast<uint_fast8_t>(N_PHILO + 4), // QP priority of the AO static_cast<uint_fast8_t>(N_PHILO + 7), // QP priority of the AO
tableQueueSto, // event queue storage tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events] Q_DIM(tableQueueSto), // queue length [events]
static_cast<void *>(0), // no stack storage static_cast<void *>(0), // no stack storage

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.9.6 // Last updated for version 5.9.7
// Last updated on 2017-07-27 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -50,60 +50,84 @@ static QP::QXSemaphore l_sema;
QP::QXThread * const XT_Test1 = &l_test1; QP::QXThread * const XT_Test1 = &l_test1;
QP::QXThread * const XT_Test2 = &l_test2; QP::QXThread * const XT_Test2 = &l_test2;
//............................................................................ // Thread-Local Storage for the "extended" threads ...........................
static void Thread1_run(QP::QXThread * const /*me*/) { struct TLS_test {
uint32_t foo;
uint8_t bar[10];
};
static TLS_test l_tls1;
static TLS_test l_tls2;
l_mutex.init(3U); static void lib_fun(uint32_t x) {
QXK_TLS(TLS_test *)->foo = x;
}
//............................................................................
static void Thread1_run(QP::QXThread * const me) {
me->m_thread = &l_tls1; // initialize the TLS for Thread1
for (;;) { for (;;) {
l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex
// wait on a semaphore (BLOCK with timeout)
(void)l_sema.wait(BSP::TICKS_PER_SEC, 0U);
BSP::ledOn(); BSP::ledOn();
l_mutex.lock(); // exercise the mutex if (l_mutex.tryLock()) { // exercise the mutex
// some flating point code to exercise the VFP... float volatile x;
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 // some flating point code to exercise the VFP...
x = 1.4142135F;
x = x * 1.4142135F;
(void)l_sema.signal(); // signal Thread2
QP::QXThread::delay(10U); // BLOCK while holding a mutex
l_mutex.unlock();
}
l_mutex.unlock();
BSP::ledOff();
QP::QXThread::delay(BSP::TICKS_PER_SEC/7); // BLOCK
// publish to Thread2 // publish to Thread2
QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), &l_test1); //QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), &l_test1);
// test TLS
lib_fun(1U);
} }
} }
//............................................................................ //............................................................................
static void Thread2_run(QP::QXThread * const me) { static void Thread2_run(QP::QXThread * const me) {
// initialize the semaphore before using it
// NOTE: Here 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, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
// initialize the mutex before using it
// NOTE: Here the semaphore is initialized in the highest-priority thread
// that uses it. Alternatively, the semaphore can be initialized
// before any thread runs.
l_mutex.init(N_PHILO + 6U);
me->m_thread = &l_tls2; // initialize the TLS for Thread2
// subscribe to the test signal */ // subscribe to the test signal */
me->subscribe(TEST_SIG); me->subscribe(TEST_SIG);
// initialize the semaphore before using it
// 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, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
for (;;) { for (;;) {
// some flating point code to exercise the VFP... // wait on a semaphore (BLOCK indefinitely)
float volatile x = 1.4142135F; l_sema.wait();
x = x * 1.4142135F;
// wait on the internal event queue (BLOCK) with timeout l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex
QP::QEvt const *e = me->queueGet(BSP::TICKS_PER_SEC/2, 0U); QP::QXThread::delay(1U); // wait more (BLOCK)
BSP::ledOff(); l_mutex.unlock();
if (e != static_cast<QP::QEvt *>(0)) { // event actually delivered? // test TLS
QP::QF::gc(e); // recycle the event manually! lib_fun(2U);
}
else {
QP::QXThread::delay(BSP::TICKS_PER_SEC/2, 0U); // BLOCK
l_sema.signal(); // signal Thread1
}
} }
} }

View File

@ -49,7 +49,6 @@ public:
static uint32_t random(void); // pseudo-random generator static uint32_t random(void); // pseudo-random generator
// for testing... // for testing...
static void wait4SW1(void);
static void ledOn(void); static void ledOn(void);
static void ledOff(void); static void ledOff(void);
}; };

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, STM32746G-Discovery board, preemptive QK kernel // Product: DPP example, STM32746G-Discovery board, preemptive QK kernel
// Last Updated for Version: 5.9.5 // Last Updated for Version: 5.9.7
// Date of the Last Update: 2017-07-20 // Date of the Last Update: 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -68,7 +68,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
// Local-scope objects ------------------------------------------------------- // Local-scope objects -------------------------------------------------------
static uint32_t l_rnd; // random seed static uint32_t l_rnd; // random seed
static QP::QMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -279,24 +278,24 @@ void BSP::displayPaused(uint8_t paused) {
} }
//............................................................................ //............................................................................
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
// Some flating point code is to exercise the VFP... // The flating point code is to exercise the FPU
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the random-seed mutex // lock the scheduler around l_rnd up to the (N_PHILO + 1U) ceiling
QP::QSchedStatus lockStat = QP::QK::schedLock(N_PHILO + 1U);
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the random-seed mutex QP::QK::schedUnlock(lockStat); // unlock sched after accessing l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rnd = seed; l_rnd = seed;
l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority
} }
//............................................................................ //............................................................................

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, STM32746G-Discovery board, dual-mode QXK kernel // Product: DPP example, STM32746G-Discovery board, dual-mode QXK kernel
// Last Updated for Version: 5.9.5 // Last Updated for Version: 5.9.7
// Date of the Last Update: 2017-07-20 // Date of the Last Update: 2017-08-19
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -68,7 +68,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
// Local-scope objects ------------------------------------------------------- // Local-scope objects -------------------------------------------------------
static uint32_t l_rnd; // random seed static uint32_t l_rnd; // random seed
static QP::QXMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -278,27 +277,33 @@ void BSP::displayPaused(uint8_t paused) {
} }
} }
//............................................................................ //............................................................................
void BSP::ledOn(void) {
BSP_LED_On(LED_GREEN);
}
//............................................................................
void BSP::ledOff(void) {
BSP_LED_Off(LED_GREEN);
}
//............................................................................
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
// Some flating point code is to exercise the VFP... // Some flating point code is to exercise the VFP...
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the random-seed mutex QP::QSchedStatus lockStat = QP::QXK::schedLock(N_PHILO); // protect l_rnd
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the random-seed mutex QP::QXK::schedUnlock(lockStat); // sched unlock around l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rnd = seed; l_rnd = seed;
l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority
} }
//............................................................................ //............................................................................
void BSP::terminate(int16_t result) { void BSP::terminate(int16_t result) {
(void)result; (void)result;

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.7.2 // Last updated for version 5.9.7
// Last updated on 2016-09-28 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -35,6 +35,9 @@
#include "dpp.h" #include "dpp.h"
#include "bsp.h" #include "bsp.h"
static QP::QTicker l_ticker0(0); // ticker for tick rate 0
QP::QActive *DPP::the_Ticker0 = &l_ticker0;
//............................................................................ //............................................................................
int main() { int main() {
static QP::QEvt const *tableQueueSto[N_PHILO]; static QP::QEvt const *tableQueueSto[N_PHILO];
@ -61,7 +64,8 @@ int main() {
QS_OBJ_DICTIONARY(philoQueueSto[3]); QS_OBJ_DICTIONARY(philoQueueSto[3]);
QS_OBJ_DICTIONARY(philoQueueSto[4]); QS_OBJ_DICTIONARY(philoQueueSto[4]);
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe // init publish-subscribe
QP::QF::psInit(subscrSto, Q_DIM(subscrSto));
// initialize event pools... // initialize event pools...
QP::QF::poolInit(smlPoolSto, QP::QF::poolInit(smlPoolSto,
@ -76,10 +80,12 @@ int main() {
sizeof(test1StackSto), // stack size [bytes] sizeof(test1StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
// NOTE: leave priority 2 free for a mutex
// start the Philo active objects... // start the Philo active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start( DPP::AO_Philo[n]->start(
static_cast<uint_fast8_t>(n + 2), // QP priority of the AO static_cast<uint_fast8_t>(n + 3), // QP priority of the AO
philoQueueSto[n], // event queue storage philoQueueSto[n], // event queue storage
Q_DIM(philoQueueSto[n]), // queue length [events] Q_DIM(philoQueueSto[n]), // queue length [events]
static_cast<void *>(0), // no stack storage static_cast<void *>(0), // no stack storage
@ -87,17 +93,26 @@ int main() {
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
} }
// example of prioritizing the Ticker0 active object
DPP::the_Ticker0->start((uint_fast8_t)(N_PHILO + 3), // priority
0, 0,
0, 0);
// NOTE: leave priority (N_PHILO + 4) free for mutex
// start the extended Test2 thread // start the extended Test2 thread
DPP::XT_Test2->start( DPP::XT_Test2->start(
static_cast<uint_fast8_t>(N_PHILO + 2), // QP prio of the thread static_cast<uint_fast8_t>(N_PHILO + 5), // QP prio of the thread
test2QueueSto, // event queue storage test2QueueSto, // event queue storage
Q_DIM(test2QueueSto), // queue length [events] Q_DIM(test2QueueSto), // queue length [events]
test2StackSto, // stack storage test2StackSto, // stack storage
sizeof(test2StackSto), // stack size [bytes] sizeof(test2StackSto), // stack size [bytes]
static_cast<QP::QEvt *>(0)); // initialization event static_cast<QP::QEvt *>(0)); // initialization event
// NOTE: leave priority (N_PHILO + 6) free for mutex
DPP::AO_Table->start( DPP::AO_Table->start(
static_cast<uint_fast8_t>(N_PHILO + 3), // QP priority of the AO static_cast<uint_fast8_t>(N_PHILO + 7), // QP priority of the AO
tableQueueSto, // event queue storage tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events] Q_DIM(tableQueueSto), // queue length [events]
static_cast<void *>(0), // no stack storage static_cast<void *>(0), // no stack storage

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.9.6 // Last updated for version 5.9.7
// Last updated on 2017-07-27 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -50,61 +50,84 @@ static QP::QXSemaphore l_sema;
QP::QXThread * const XT_Test1 = &l_test1; QP::QXThread * const XT_Test1 = &l_test1;
QP::QXThread * const XT_Test2 = &l_test2; QP::QXThread * const XT_Test2 = &l_test2;
//............................................................................ // Thread-Local Storage for the "extended" threads ...........................
static void Thread1_run(QP::QXThread * const /*me*/) { struct TLS_test {
uint32_t foo;
uint8_t bar[10];
};
static TLS_test l_tls1;
static TLS_test l_tls2;
l_mutex.init(3U); static void lib_fun(uint32_t x) {
QXK_TLS(TLS_test *)->foo = x;
}
//............................................................................
static void Thread1_run(QP::QXThread * const me) {
me->m_thread = &l_tls1; // initialize the TLS for Thread1
for (;;) { for (;;) {
l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex
BSP::ledOn();
// wait on a semaphore (BLOCK with timeout) if (l_mutex.tryLock()) { // exercise the mutex
(void)l_sema.wait(BSP::TICKS_PER_SEC, 0U); float volatile x;
//BSP::ledOn();
// some flating point code to exercise the VFP...
x = 1.4142135F;
x = x * 1.4142135F;
(void)l_sema.signal(); // signal Thread2
QP::QXThread::delay(10U); // BLOCK while holding a mutex
l_mutex.unlock();
}
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(); l_mutex.unlock();
BSP::ledOff();
QP::QXThread::delay(BSP::TICKS_PER_SEC/7, 0U); // BLOCK QP::QXThread::delay(BSP::TICKS_PER_SEC/7); // BLOCK
// publish to Thread2 // publish to Thread2
QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), &l_test1); //QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), &l_test1);
// test TLS
lib_fun(1U);
} }
} }
//............................................................................ //............................................................................
static void Thread2_run(QP::QXThread * const me) { static void Thread2_run(QP::QXThread * const me) {
// initialize the semaphore before using it
// NOTE: Here 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, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
// initialize the mutex before using it
// NOTE: Here the semaphore is initialized in the highest-priority thread
// that uses it. Alternatively, the semaphore can be initialized
// before any thread runs.
l_mutex.init(N_PHILO + 6U);
me->m_thread = &l_tls2; // initialize the TLS for Thread2
// subscribe to the test signal */ // subscribe to the test signal */
me->subscribe(TEST_SIG); me->subscribe(TEST_SIG);
// initialize the semaphore before using it
// 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, // count==0 (signaling semaphore)
1U); // max_count==1 (binary semaphore)
for (;;) { for (;;) {
// some flating point code to exercise the VFP... // wait on a semaphore (BLOCK indefinitely)
float volatile x = 1.4142135F; l_sema.wait();
x = x * 1.4142135F;
// wait on the internal event queue (BLOCK) with timeout l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex
QP::QEvt const *e = me->queueGet(BSP::TICKS_PER_SEC/2, 0U); QP::QXThread::delay(1U); // wait more (BLOCK)
//BSP::ledOff(); l_mutex.unlock();
if (e != static_cast<QP::QEvt *>(0)) { // event actually delivered? // test TLS
QP::QF::gc(e); // recycle the event manually! lib_fun(2U);
}
else {
QP::QXThread::delay(BSP::TICKS_PER_SEC/2, 0U); // BLOCK
l_sema.signal(); // signal Thread1
}
} }
} }

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: "Fly 'n' Shoot" game example, EFM32-SLSTK3401A board, QK kernel // Product: "Fly 'n' Shoot" game example, EFM32-SLSTK3401A board, QK kernel
// Last Updated for Version: 5.9.5 // Last Updated for Version: 5.9.7
// Date of the Last Update: 2017-07-20 // Date of the Last Update: 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -84,7 +84,6 @@ static uint32_t l_fb[BSP_SCREEN_HEIGHT + 1][BSP_SCREEN_WIDTH / 32U];
static uint32_t l_walls[GAME_TUNNEL_HEIGHT + 1][BSP_SCREEN_WIDTH / 32U]; static uint32_t l_walls[GAME_TUNNEL_HEIGHT + 1][BSP_SCREEN_WIDTH / 32U];
static unsigned l_rnd; /* random seed */ static unsigned l_rnd; /* random seed */
static QP::QMutex l_rndMutex; /* mutex to protect the random seed */
static void paintBits(uint8_t x, uint8_t y, uint8_t const *bits, uint8_t h); static void paintBits(uint8_t x, uint8_t y, uint8_t const *bits, uint8_t h);
static void paintBitsClear(uint8_t x, uint8_t y, static void paintBitsClear(uint8_t x, uint8_t y,
@ -650,24 +649,24 @@ void BSP_displayOff(void) {
} }
//............................................................................ //............................................................................
uint32_t BSP_random(void) { // a very cheap pseudo-random-number generator uint32_t BSP_random(void) { // a very cheap pseudo-random-number generator
// Some flating point code is to exercise the VFP... // The flating point code is to exercise the FPU
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the random-seed mutex // lock the scheduler around l_rnd up to the Tunnel priority
QP::QSchedStatus lockStat = QP::QK::schedLock(GAME::AO_Tunnel->m_prio);
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the random-seed mutex QP::QK::schedUnlock(lockStat); // unlock sched after accessing l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP_randomSeed(uint32_t seed) { void BSP_randomSeed(uint32_t seed) {
l_rnd = seed; l_rnd = seed;
l_rndMutex.init(1U); // ceiling == Tunnel priority
} }
//..........................................................................*/ //..........................................................................*/
static void paintBits(uint8_t x, uint8_t y, uint8_t const *bits, uint8_t h) { static void paintBits(uint8_t x, uint8_t y, uint8_t const *bits, uint8_t h) {

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, LAUCHXL2-TMS570LS12 board, preemptive QK kernel // Product: DPP example, LAUCHXL2-TMS570LS12 board, preemptive QK kernel
// Last Updated for Version: 5.9.5 // Last Updated for Version: 5.9.7
// Date of the Last Update: 2017-07-20 // Date of the Last Update: 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -69,7 +69,6 @@ namespace DPP {
#define VIM_RAM ((t_isrFuncPTR *)0xFFF82000U) #define VIM_RAM ((t_isrFuncPTR *)0xFFF82000U)
static uint32_t l_rnd; // random seed static uint32_t l_rnd; // random seed
static QP::QMutex l_rndMutex; // mutex to protect the random seed
#ifdef Q_SPY #ifdef Q_SPY
@ -205,24 +204,24 @@ void BSP::displayPaused(uint8_t paused) {
} }
//............................................................................ //............................................................................
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
// Some flating point code is to exercise the VFP... // The flating point code is to exercise the FPU
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the random-seed mutex // lock the scheduler around l_rnd up to the (N_PHILO + 1U) ceiling
QP::QSchedStatus lockStat = QP::QK::schedLock(N_PHILO + 1U);
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the random-seed mutex QP::QK::schedUnlock(lockStat); // unlock sched after accessing l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rnd = seed; l_rnd = seed;
l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority
} }
//............................................................................ //............................................................................

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, EFM32-SLSTK3401A board, preemptive QK kernel // Product: DPP example, EFM32-SLSTK3401A board, preemptive QK kernel
// Last Updated for Version: 5.9.5 // Last Updated for Version: 5.9.7
// Date of the Last Update: 2017-07-20 // Date of the Last Update: 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -77,7 +77,6 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
#define PB1_PIN 7 #define PB1_PIN 7
static uint32_t l_rnd; // random seed static uint32_t l_rnd; // random seed
static QP::QMutex l_rndMutex; // to protect the random number generator
#ifdef Q_SPY #ifdef Q_SPY
@ -260,24 +259,24 @@ void BSP::displayPaused(uint8_t paused) {
} }
//............................................................................ //............................................................................
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
// Some flating point code is to exercise the VFP... // The flating point code is to exercise the FPU
float volatile x = 3.1415926F; float volatile x = 3.1415926F;
x = x + 2.7182818F; x = x + 2.7182818F;
l_rndMutex.lock(); // lock the random-seed mutex // lock the scheduler around l_rnd up to the (N_PHILO + 1U) ceiling
QP::QSchedStatus lockStat = QP::QK::schedLock(N_PHILO + 1U);
// "Super-Duper" Linear Congruential Generator (LCG) // "Super-Duper" Linear Congruential Generator (LCG)
// LCG(2^32, 3*7*11*13*23, 0, seed) // LCG(2^32, 3*7*11*13*23, 0, seed)
// //
uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // unlock the random-seed mutex QP::QK::schedUnlock(lockStat); // unlock sched after accessing l_rnd
return (rnd >> 8); return (rnd >> 8);
} }
//............................................................................ //............................................................................
void BSP::randomSeed(uint32_t seed) { void BSP::randomSeed(uint32_t seed) {
l_rnd = seed; l_rnd = seed;
l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority
} }
//............................................................................ //............................................................................

View File

@ -1,7 +1,7 @@
///*************************************************************************** ///***************************************************************************
// Product: DPP example, EFM32-SLSTK3401A board, preemptive QXK kernel // Product: DPP example, EFM32-SLSTK3401A board, preemptive QXK kernel
// Last Updated for Version: 5.9.5 // Last Updated for Version: 5.9.7
// Date of the Last Update: 2017-07-20 // Date of the Last Update: 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
//**************************************************************************** //****************************************************************************
// DPP example for QXK // DPP example for QXK
// Last updated for version 5.9.6 // Last updated for version 5.9.7
// Last updated on 2017-07-27 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -43,9 +43,9 @@ static void thread_function(QP::QXThread * const me) {
(void)me; // unused parameter (void)me; // unused parameter
XT_Sema.init(1U); // 1 count XT_Sema.init(1U); // 1 count
for (;;) { for (;;) {
(void)XT_Sema.wait(0U, 0U); // wait forever (void)XT_Sema.wait(QXTHREAD_NO_TIMEOUT); // wait forever
BSP::ledOn(); BSP::ledOn();
QP::QXThread::delay(1, 0U); // 1 cycle QP::QXThread::delay(1U); // block for 1 clock tick
BSP::ledOff(); BSP::ledOff();
} }
} }

View File

@ -3,8 +3,8 @@
/// @ingroup qep /// @ingroup qep
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-08-01 /// Last updated on 2017-08-18
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -43,15 +43,15 @@
//! The current QP version as a decimal constant XYZ, where X is a 1-digit //! The current QP version as a decimal constant XYZ, where X is a 1-digit
// major version number, Y is a 1-digit minor version number, and Z is // major version number, Y is a 1-digit minor version number, and Z is
// a 1-digit release number. // a 1-digit release number.
#define QP_VERSION 596 #define QP_VERSION 597
//! The current QP version number string of the form X.Y.Z, where X is //! The current QP version number string of the form X.Y.Z, where X is
// a 1-digit major version number, Y is a 1-digit minor version number, // a 1-digit major version number, Y is a 1-digit minor version number,
// and Z is a 1-digit release number. // and Z is a 1-digit release number.
#define QP_VERSION_STR "5.9.6" #define QP_VERSION_STR "5.9.7"
//! Tamperproof current QP release (5.9.6) and date (2017-08-04) //! Tamperproof current QP release (5.9.7) and date (2017-08-18)
#define QP_RELEASE 0x9A315E6BU #define QP_RELEASE 0x9A2F3B8AU
//**************************************************************************** //****************************************************************************
#ifndef Q_SIGNAL_SIZE #ifndef Q_SIGNAL_SIZE
@ -315,9 +315,11 @@ public:
virtual ~QHsm(); virtual ~QHsm();
//! Executes the top-most initial transition in QP::QHsm //! Executes the top-most initial transition in QP::QHsm
virtual void init(QEvt const * const e);
virtual void init(void) { this->init(static_cast<QEvt const *>(0)); } virtual void init(void) { this->init(static_cast<QEvt const *>(0)); }
//! @overload init(void)
virtual void init(QEvt const * const e);
//! Dispatches an event to QHsm //! Dispatches an event to QHsm
virtual void dispatch(QEvt const * const e); virtual void dispatch(QEvt const * const e);

View File

@ -3,8 +3,8 @@
/// @ingroup qf /// @ingroup qf
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.8.0 /// Last updated for version 5.9.7
/// Last updated on 2016-11-19 /// Last updated on 2017-08-18
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -224,6 +224,21 @@ public:
return m_nFree; return m_nFree;
} }
//! "raw" thread-safe QF event queue operation for obtaining the minimum
//! number of free entries ever in the queue (a.k.a. "low-watermark").
///
/// @description
/// This operation needs to be used with caution because the
/// "low-watermark" can change unexpectedly. The main intent for using
/// this operation is to get an idea of queue usage to size the queue
/// adequately.
///
/// @returns the minimum number of free entries ever in the queue
/// since init.
QEQueueCtr getNMin(void) const {
return m_nMin;
}
//! "raw" thread-safe QF event queue operation to find out if the queue //! "raw" thread-safe QF event queue operation to find out if the queue
//! is empty //! is empty
/// @note /// @note

View File

@ -3,8 +3,8 @@
/// @ingroup qf /// @ingroup qf
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-08-01 /// Last updated on 2017-08-20
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -173,9 +173,15 @@ public: // for access from extern "C" functions
QF_THREAD_TYPE m_thread; QF_THREAD_TYPE m_thread;
#endif #endif
//! QF priority associated with the active object. //! QF priority (1..#QF_MAX_ACTIVE) of this active object.
uint_fast8_t m_prio; uint_fast8_t m_prio;
#ifdef qxk_h // QXK kernel used?
//! QF start priority (1..#QF_MAX_ACTIVE) of this active object.
uint_fast8_t m_startPrio;
#endif
protected: protected:
//! protected constructor (abstract class) //! protected constructor (abstract class)
QActive(QStateHandler const initial); QActive(QStateHandler const initial);
@ -353,13 +359,16 @@ private:
/// list, so only armed time events consume CPU cycles. /// list, so only armed time events consume CPU cycles.
/// ///
/// @note /// @note
/// QF manages the time events in the macro TICK_X(), which must be /// QF manages the time events in the macro TICK_X(), which must be called
/// called periodically, eitehr from a clock tick ISR, or from a task level. /// periodically, from the clock tick ISR or from the special QP::QTicker
/// active object.
/// ///
/// @note /// @note
/// In this version of QF QTimeEvt objects should __not__ be allocated /// Even though QP::QTimeEvt is a subclass of QP::QEvt, QP::QTimeEvt instances
/// dynamically from event pools. Currently, QF will not correctly recycle /// can NOT be allocated dynamically from event pools. In other words, it is
/// the dynamically allocated Time Events. /// illegal to allocate QP::QTimeEvt instances with the Q_NEW() or Q_NEW_X()
/// macros.
///
class QTimeEvt : public QEvt { class QTimeEvt : public QEvt {
private: private:
@ -408,6 +417,8 @@ public:
#if (!defined QP_IMPL) && (QP_API_VERSION < 500) #if (!defined QP_IMPL) && (QP_API_VERSION < 500)
//! @deprecated TimeEvt ctor provided for backwards compatibility. //! @deprecated TimeEvt ctor provided for backwards compatibility.
/// @overload QTimeEvt::QTimeEvt(QActive * const, enum_t const,
/// uint_fast8_t const)
QTimeEvt(enum_t const sgnl) : QTimeEvt(enum_t const sgnl) :
#ifdef Q_EVT_CTOR #ifdef Q_EVT_CTOR
QEvt(static_cast<QSignal>(sgnl)), QEvt(static_cast<QSignal>(sgnl)),

View File

@ -3,8 +3,8 @@
/// @ingroup qk /// @ingroup qk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.8.1 /// Last updated for version 5.9.7
/// Last updated on 2016-12-14 /// Last updated on 2017-08-18
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -57,10 +57,10 @@
extern "C" { extern "C" {
struct QK_Attr { struct QK_Attr {
uint_fast8_t volatile actPrio; //!< prio of the active AO uint_fast8_t actPrio; //!< prio of the active AO
uint_fast8_t volatile nextPrio; //!< prio of the next AO to execute uint_fast8_t nextPrio; //!< prio of the next AO to execute
uint_fast8_t volatile lockPrio; //!< lock prio (0 == no-lock) uint_fast8_t lockPrio; //!< lock prio (0 == no-lock)
uint_fast8_t volatile lockHolder; //!< prio of the lock holder uint_fast8_t lockHolder; //!< prio of the lock holder
#ifndef QK_ISR_CONTEXT_ #ifndef QK_ISR_CONTEXT_
uint_fast8_t volatile intNest; //!< ISR nesting level uint_fast8_t volatile intNest; //!< ISR nesting level
#endif // QK_ISR_CONTEXT_ #endif // QK_ISR_CONTEXT_
@ -83,23 +83,28 @@ void QK_activate_(void);
//**************************************************************************** //****************************************************************************
namespace QP { namespace QP {
//! The scheduler lock status
typedef uint_fast16_t QSchedStatus;
//**************************************************************************** //****************************************************************************
//! QK services. //! QK services.
/// @description /// @description
/// This class groups together QK services. It has only static members and /// This class groups together QK services. It has only static members and
/// should not be instantiated. /// should not be instantiated.
/// ///
// @note The QK scheduler, QK priority, QK ready set, etc. belong conceptually /// @note
/// to the QK class (as static class members). However, to avoid C++ potential /// The QK scheduler, QK priority, QK ready set, etc. belong conceptually
/// name-mangling problems in assembly language, these elements are defined /// to the QK class (as static class members). However, to avoid potential
/// outside of the QK class and use the extern "C" linkage specification. /// C++ name-mangling problems in assembly language, these elements are
/// defined outside of the QK class and use the extern "C" linkage.
class QK { class QK {
public: public:
// QK scheduler locking...
//! QK selective scheduler lock
static QSchedStatus schedLock(uint_fast8_t const ceiling);
//! get the current QK version number string of the form X.Y.Z //! QK selective scheduler unlock
static char_t const *getVersion(void) { static void schedUnlock(QSchedStatus const stat);
return versionStr;
}
//! QK idle callback (customized in BSPs for QK) //! QK idle callback (customized in BSPs for QK)
/// @description /// @description
@ -112,20 +117,11 @@ public:
/// ///
/// @sa QP::QF::onIdle() /// @sa QP::QF::onIdle()
static void onIdle(void); static void onIdle(void);
};
/*! Priority-ceiling Mutex the QK preemptive kernel */ //! get the current QK version number string of the form X.Y.Z
class QMutex { static char_t const *getVersion(void) {
public: return versionStr;
void init(uint_fast8_t const prio); }
void lock(void);
void unlock(void);
private:
uint_fast8_t m_lockPrio; //!< lock prio (priority ceiling)
uint_fast8_t m_prevPrio; //!< previoius lock prio
friend class QF;
}; };
} // namespace QP } // namespace QP
@ -149,22 +145,21 @@ private:
//! Internal macro to represent the scheduler lock status //! Internal macro to represent the scheduler lock status
// that needs to be preserved to allow nesting of locks. // that needs to be preserved to allow nesting of locks.
// //
#define QF_SCHED_STAT_ QMutex schedLock_; #define QF_SCHED_STAT_ QSchedStatus lockStat_;
//! Internal macro for selective scheduler locking. //! Internal macro for selective scheduler locking.
#define QF_SCHED_LOCK_(prio_) do { \ #define QF_SCHED_LOCK_(prio_) do { \
if (QK_ISR_CONTEXT_()) { \ if (QK_ISR_CONTEXT_()) { \
schedLock_.m_lockPrio = static_cast<uint_fast8_t>(0); \ lockStat_ = static_cast<QSchedStatus>(0xFF); \
} else { \ } else { \
schedLock_.init((prio_)); \ lockStat_ = QK::schedLock((prio_)); \
schedLock_.lock(); \
} \ } \
} while (false) } while (false)
//! Internal macro for selective scheduler unlocking. //! Internal macro for selective scheduler unlocking.
#define QF_SCHED_UNLOCK_() do { \ #define QF_SCHED_UNLOCK_() do { \
if (schedLock_.m_lockPrio != static_cast<uint_fast8_t>(0)) { \ if (lockStat_ != static_cast<QSchedStatus>(0xFF)) { \
schedLock_.unlock(); \ QK::schedUnlock(lockStat_); \
} \ } \
} while (false) } while (false)

View File

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Product: PC-Lint 9.x option file for linting QP/C++ applications // Product: PC-Lint 9.x option file for linting QP/C++ applications
// Last updated for version 5.9.5 // Last updated for version 5.9.7
// Last updated on 2017-07-19 // Last updated on 2017-08-20
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -168,13 +168,13 @@
*toTimeEvt) *toTimeEvt)
-esym(1927, // 8-5-1 Symbol not in the ctor initializer list -esym(1927, // 8-5-1 Symbol not in the ctor initializer list
QP::QMActive::m_prio, QP::QActive::m_prio,
QP::QMActive::m_eQueue, QP::QActive::m_eQueue,
QP::QMActive::m_osObject, QP::QActive::m_osObject,
QP::QMActive::m_thread) QP::QActive::m_thread)
-esym(1536, // 9-3-1, 9-3-2 Exposing low access member -esym(1536, // 9-3-1, 9-3-2 Exposing low access member
QP::QMActive::m_osObject, QP::QActive::m_osObject,
QP::QMActive::m_thread) QP::QActive::m_thread)
-estring(1960, // 11-0-1(req) non-private data member -estring(1960, // 11-0-1(req) non-private data member
m_eQueue, m_eQueue,
m_thread, m_thread,
@ -244,10 +244,10 @@
-estring(1963, Q_NEW) // 16-3-2(adv) '#/##' used in macro -estring(1963, Q_NEW) // 16-3-2(adv) '#/##' used in macro
-esym(1960, remove) // 17-0-2, Re-use of C++ identifier -esym(1960, remove) // 17-0-2, Re-use of C++ identifier
-esym(1401, // member not initialized by constructor -esym(1401, // member not initialized by constructor
QP::QMActive::m_prio, QP::QActive::m_prio,
QP::QMActive::m_eQueue, QP::QActive::m_eQueue,
QP::QMActive::m_osObject, QP::QActive::m_osObject,
QP::QMActive::m_thread) QP::QActive::m_thread)
-esym(1704, // constructor has private access specification -esym(1704, // constructor has private access specification
QP::QTimeEvt::QTimeEvt, QP::QTimeEvt::QTimeEvt,
QP::QEQueue::QEQueue, QP::QEQueue::QEQueue,
@ -292,6 +292,8 @@
// QXK // QXK
-esym(1960, // 3-2-3(req) type previously declared -esym(1960, // 3-2-3(req) type previously declared
QP::QActive) QP::QActive)
-estring(1960, // 11-0-1(req) non-private data member
m_startPrio)
-estring(1960, // 11-0-1(req) non-private data member -estring(1960, // 11-0-1(req) non-private data member
curr, curr,
next, next,
@ -304,6 +306,8 @@
-esym(1712, // default constructor not defined -esym(1712, // default constructor not defined
QXThread) QXThread)
-esym(1960, signal) // 17-0-2, Re-use of C++ identifier -esym(1960, signal) // 17-0-2, Re-use of C++ identifier
-esym(1927, // 8-5-1 Symbol not in the ctor initializer list
QP::QActive::m_startPrio)
// QS // QS

View File

@ -3,8 +3,8 @@
/// @ingroup qs /// @ingroup qs
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.0 /// Last updated for version 5.9.7
/// Last updated on 2017-05-16 /// Last updated on 2017-08-18
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -125,8 +125,8 @@ enum QSpyRecords {
QS_QF_ACTIVE_POST_ATTEMPT, //!< attempt to post an evt to AO failed QS_QF_ACTIVE_POST_ATTEMPT, //!< attempt to post an evt to AO failed
QS_QF_EQUEUE_POST_ATTEMPT, //!< attempt to post an evt to QEQueue failed QS_QF_EQUEUE_POST_ATTEMPT, //!< attempt to post an evt to QEQueue failed
QS_QF_MPOOL_GET_ATTEMPT, //!< attempt to get a memory block failed QS_QF_MPOOL_GET_ATTEMPT, //!< attempt to get a memory block failed
QS_QF_RESERVED1, QS_MUTEX_LOCK, //!< a mutex was locked
QS_QF_RESERVED0, QS_MUTEX_UNLOCK, //!< a mutex was unlocked
// [50] built-in scheduler records // [50] built-in scheduler records
QS_SCHED_LOCK, //!< scheduler was locked QS_SCHED_LOCK, //!< scheduler was locked

View File

@ -4,8 +4,8 @@
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.4 /// Last updated for version 5.9.7
/// Last updated on 2017-07-06 /// Last updated on 2017-08-18
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -81,11 +81,11 @@ extern "C" {
//! attributes of the QXK kernel //! attributes of the QXK kernel
struct QXK_Attr { struct QXK_Attr {
QP::QActive *curr; //!< currently executing thread QP::QActive *curr; //!< currently executing thread
QP::QActive *next; //!< next thread to execute QP::QActive *next; //!< next thread to execute
uint_fast8_t volatile actPrio; //!< prio of the active basic thread uint_fast8_t actPrio; //!< prio of the active basic thread
uint_fast8_t volatile lockPrio; //!< lock prio (0 == no-lock) uint_fast8_t lockPrio; //!< lock prio (0 == no-lock)
uint_fast8_t volatile lockHolder; //!< prio of the lock holder uint_fast8_t lockHolder; //!< prio of the lock holder
#ifndef QXK_ISR_CONTEXT_ #ifndef QXK_ISR_CONTEXT_
uint_fast8_t volatile intNest; //!< ISR nesting level uint_fast8_t volatile intNest; //!< ISR nesting level
#endif // QXK_ISR_CONTEXT_ #endif // QXK_ISR_CONTEXT_
@ -111,6 +111,9 @@ QP::QActive *QXK_current(void);
//**************************************************************************** //****************************************************************************
namespace QP { namespace QP {
//! The scheduler lock status
typedef uint_fast16_t QSchedStatus;
//**************************************************************************** //****************************************************************************
//! QXK services. //! QXK services.
/// @description /// @description
@ -124,13 +127,11 @@ namespace QP {
/// the extern "C" linkage specification. /// the extern "C" linkage specification.
class QXK { class QXK {
public: public:
//! QXK selective scheduler lock
static QSchedStatus schedLock(uint_fast8_t const ceiling);
//! QXK initialization //! QXK selective scheduler unlock
/// @description static void schedUnlock(QSchedStatus const stat);
/// QP::QXK::init() must be called from the application before
/// QP::QF::run() to initialize the stack for the QXK idle thread.
static void init(void * const idleStkSto,
uint_fast16_t const idleStkSize);
//! QXK idle callback (customized in BSPs for QXK) //! QXK idle callback (customized in BSPs for QXK)
/// @description /// @description
@ -150,28 +151,6 @@ public:
} }
}; };
//****************************************************************************
//! Priority Ceiling Mutex the QXK preemptive kernel
class QXMutex {
public:
//! initialize the QXK priority-ceiling mutex
void init(uint_fast8_t const prio);
//! lock the QXK priority-ceiling mutex
void lock(void);
//! unlock the QXK priority-ceiling mutex
void unlock(void);
private:
uint_fast8_t m_lockPrio; //!< lock prio (priority ceiling)
uint_fast8_t m_prevPrio; //!< previoius lock prio
uint_fast8_t m_prevHolder; //!< priority of the thread holding the lock
friend class QF;
};
} // namespace QP } // namespace QP
@ -193,22 +172,21 @@ private:
//! Internal macro to represent the scheduler lock status //! Internal macro to represent the scheduler lock status
// that needs to be preserved to allow nesting of locks. // that needs to be preserved to allow nesting of locks.
// //
#define QF_SCHED_STAT_ QXMutex schedLock_; #define QF_SCHED_STAT_ QSchedStatus lockStat_;
//! Internal macro for selective scheduler locking. //! Internal macro for selective scheduler locking.
#define QF_SCHED_LOCK_(prio_) do { \ #define QF_SCHED_LOCK_(prio_) do { \
if (QXK_ISR_CONTEXT_()) { \ if (QXK_ISR_CONTEXT_()) { \
schedLock_.m_lockPrio = static_cast<uint_fast8_t>(0); \ lockStat_ = static_cast<QSchedStatus>(0xFF); \
} else { \ } else { \
schedLock_.init((prio_)); \ lockStat_ = QXK::schedLock((prio_)); \
schedLock_.lock(); \
} \ } \
} while (false) } while (false)
//! Internal macro for selective scheduler unlocking. //! Internal macro for selective scheduler unlocking.
#define QF_SCHED_UNLOCK_() do { \ #define QF_SCHED_UNLOCK_() do { \
if (schedLock_.m_lockPrio != static_cast<uint_fast8_t>(0)) { \ if (lockStat_ != static_cast<QSchedStatus>(0xFF)) { \
schedLock_.unlock(); \ QXK::schedUnlock(lockStat_); \
} \ } \
} while (false) } while (false)

View File

@ -3,8 +3,8 @@
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-07-27 /// Last updated on 2017-08-20
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -39,6 +39,9 @@
#ifndef qxthread_h #ifndef qxthread_h
#define qxthread_h #define qxthread_h
//! no-timeout sepcification when blocking on queues or semaphores
#define QXTHREAD_NO_TIMEOUT (static_cast<uint_fast16_t>(0))
namespace QP { namespace QP {
class QXThread; // forward declaration class QXThread; // forward declaration
@ -73,15 +76,14 @@ public:
uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0)); uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0));
//! delay (block) the current extended thread for a specified # ticks //! delay (block) the current extended thread for a specified # ticks
static bool delay(uint_fast16_t const nTicks, static bool delay(uint_fast16_t const nTicks);
uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0));
//! cancel the delay //! cancel the delay
bool delayCancel(void); bool delayCancel(void);
//! obtain a message from the private message queue (block if no messages) //! obtain a message from the private message queue (block if no messages)
static QEvt const *queueGet(uint_fast16_t const nTicks, static QEvt const *queueGet(
uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0)); uint_fast16_t const nTicks = QXTHREAD_NO_TIMEOUT);
// virtual function overrides... // virtual function overrides...
//! Executes the top-most initial transition in QP::QMsm. //! Executes the top-most initial transition in QP::QMsm.
@ -123,8 +125,7 @@ public:
private: private:
void block_(void) const; void block_(void) const;
void unblock_(void) const; void unblock_(void) const;
void teArm_(enum_t const sig, uint_fast16_t const nTicks, void teArm_(enum_t const sig, uint_fast16_t const nTicks);
uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0));
bool teDisarm_(void); bool teDisarm_(void);
// attributes... // attributes...
@ -132,11 +133,9 @@ private:
// friendships... // friendships...
friend class QXSemaphore; friend class QXSemaphore;
friend class QXMutex;
}; };
//! no-timeout sepcification when blocking on queues or semaphores
#define QXTHREAD_NO_TIMEOUT (static_cast<uint_fast16_t>(0))
//**************************************************************************** //****************************************************************************
//! Counting Semaphore of the QXK preemptive kernel //! Counting Semaphore of the QXK preemptive kernel
class QXSemaphore { class QXSemaphore {
@ -146,19 +145,67 @@ public:
uint_fast16_t const max_count uint_fast16_t const max_count
= static_cast<uint_fast16_t>(0xFFFF)); = static_cast<uint_fast16_t>(0xFFFF));
//! wait (block) on the semaphore
bool wait(uint_fast16_t const nTicks = QXTHREAD_NO_TIMEOUT);
//! try wait on the semaphore (non-blocking)
bool tryWait(void);
//! signal (unblock) the semaphore //! signal (unblock) the semaphore
bool signal(void); bool signal(void);
//! wait (block) on the semaphore
bool wait(uint_fast16_t const nTicks,
uint_fast8_t const tickRate = static_cast<uint_fast8_t>(0));
private: private:
QPSet m_waitSet; //!< set of extended threads waiting on this semaphore QPSet m_waitSet; //!< set of extended threads waiting on this semaphore
uint_fast16_t m_count; uint_fast16_t m_count;
uint_fast16_t m_max_count; uint_fast16_t m_max_count;
}; };
//****************************************************************************
//! Priority Ceiling Mutex the QXK preemptive kernel */
///
/// @description
/// QP::QXMutex is a blocking mutual exclusion mechanism. The mutex is
/// initialized with the ceiling QP priority, which must be bigger than any
/// extended thread competing for this mutex. The QP priority level used a the
/// ceiling must be not used for any other active object or thread in the
/// application.
///
/// @note
/// QP::QXMutex should be used in situations when at least one of the extended
/// threads contending for the mutex blocks while holding the mutex (between
/// the QXMutex::lock() and QXMutex::unlock() operations). If no blocking is
/// needed while holding the mutex, the more efficient non-blocking mechanism
/// of @ref QXK::schedLock() "selective QXK scheduler locking" should be used
/// instead. @ref QXK::schedLock() "Selective scheduler locking" is available
/// for both @ref QP::QActive "basic threads" and @ref QP::QXThread extended
/// threads, so it is applicable to situations where resources are shared
/// among all these threads.
///
/// @usage
/// The following example illustrates how to instantiate the mutex
/// in your application.
/// @include qf_mutex.cpp
///
class QXMutex {
public:
//! initialize the QXK priority-ceiling mutex QP::QXMutex
void init(uint_fast8_t ceiling);
//! lock the QXK priority-ceiling mutex QP::QXMutex
bool lock(uint_fast16_t const nTicks = QXTHREAD_NO_TIMEOUT);
//! try to lock the QXK priority-ceiling mutex QP::QXMutex
bool tryLock(void);
//! unlock the QXK priority-ceiling mutex QP::QXMutex
void unlock(void);
private:
QPSet m_waitSet; //!< set of extended-threads waiting on this mutex
uint_fast8_t m_ceiling;
uint_fast8_t m_lockNest;
};
} // namespace QP } // namespace QP
#endif // qxthread_h #endif // qxthread_h

View File

@ -135,6 +135,7 @@ int_t QF::run(void) {
// for events. Instead, the Win32-QV port efficiently waits until // for events. Instead, the Win32-QV port efficiently waits until
// QP events become available. // QP events become available.
QF_INT_ENABLE(); QF_INT_ENABLE();
(void)WaitForSingleObject(QV_win32Event_, (DWORD)INFINITE); (void)WaitForSingleObject(QV_win32Event_, (DWORD)INFINITE);
QF_INT_DISABLE(); QF_INT_DISABLE();

View File

@ -3,8 +3,8 @@
/// @ingroup qk /// @ingroup qk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.0 /// Last updated for version 5.9.7
/// Last updated on 2017-05-04 /// Last updated on 2017-08-18
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -116,26 +116,19 @@ static void initial_events(void) {
// any active objects need to be scheduled before starting event loop? // any active objects need to be scheduled before starting event loop?
if (QK_sched_() != static_cast<uint_fast8_t>(0)) { if (QK_sched_() != static_cast<uint_fast8_t>(0)) {
QK_activate_(); // process all events produced so far QK_activate_(); // activate AOs to process all events posted so far
} }
} }
//**************************************************************************** //****************************************************************************
// @description /// @description
// QP::QF::run() is typically called from your startup code after you ///
// initialize the QF and start at least one active object with /// QP::QF::run() is typically called from your startup code after you
// QP::QActive::start(). /// initialize the QF and start at least one active object with
// /// QP::QActive::start().
// @returns QP::QF::run() typically does not return in embedded applications. ///
// However, when QP runs on top of an operating system, QP::QF::run() might /// @returns In QK, the QP::QF::run() function does not return.
// return and in this case the return represents the error code (0 for ///
// success). Typically the value returned from QP::QF::run() is subsequently
// passed on as return from main().
//
// @note This function is strongly platform-dependent and is not implemented
// in the QF, but either in the QF port or in the Board Support Package (BSP)
// for the given application. All QF ports must implement QP::QF::run().
//
int_t QF::run(void) { int_t QF::run(void) {
QF_INT_DISABLE(); QF_INT_DISABLE();
initial_events(); // process all events posted during initialization initial_events(); // process all events posted during initialization
@ -144,7 +137,7 @@ int_t QF::run(void) {
// the QK idle loop... // the QK idle loop...
for (;;) { for (;;) {
QK::onIdle(); // invoke the QK on-idle callback QK::onIdle(); // application-specific QK on-idle callback
} }
#ifdef __GNUC__ // GNU compiler? #ifdef __GNUC__ // GNU compiler?
return static_cast<int_t>(0); return static_cast<int_t>(0);
@ -177,16 +170,15 @@ void QActive::start(uint_fast8_t const prio,
/// @pre AO cannot be started from an ISR, the priority must be in range /// @pre AO cannot be started from an ISR, the priority must be in range
/// and the stack storage must not be provided, because the QK kernel does /// and the stack storage must not be provided, because the QK kernel does
/// not need per-AO stacks. /// not need per-AO stacks.
/// Q_REQUIRE_ID(300, (!QK_ISR_CONTEXT_())
Q_REQUIRE_ID(500, (!QK_ISR_CONTEXT_())
&& (static_cast<uint_fast8_t>(0) < prio) && (static_cast<uint_fast8_t>(0) < prio)
&& (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE)) && (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE))
&& (stkSto == static_cast<void *>(0))); && (stkSto == static_cast<void *>(0)));
m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO m_eQueue.init(qSto, qLen); // initialize the built-in queue
m_prio = prio; // set the QF priority of this AO
QF::add_(this); // make QF aware of this AO m_prio = prio; // set the QF priority of this AO
QF::add_(this); // make QF aware of this AO
this->init(ie); // take the top-most initial tran. (virtual) this->init(ie); // take the top-most initial tran. (virtual)
QS_FLUSH(); // flush the trace buffer to the host QS_FLUSH(); // flush the trace buffer to the host
@ -201,20 +193,20 @@ void QActive::start(uint_fast8_t const prio,
} }
//**************************************************************************** //****************************************************************************
// @description /// @description
// The preferred way of calling this function is from within the active /// This function must be called from within the AO that needs to stop.
// object that needs to stop. In other words, an active object should stop /// In other words, an AO should stop itself rather than being stopped by
// itself rather than being stopped by someone else. This policy works /// someone else. This policy works best, because only the AO itself "knows"
// best, because only the active object itself "knows" when it has reached /// when it has reached the appropriate state for the shutdown.
// the appropriate state for the shutdown. ///
// /// @note
// @note /// By the time the AO calls QP::QActive::stop(), it should have unsubscribed
// By the time the AO calls QP::QActive::stop(), it should have unsubscribed /// from all events and no more events should be directly-posted to it.
// from all events and no more events should be directly-posted to it. ///
//
void QActive::stop(void) { void QActive::stop(void) {
//! @pre QActive::stop() must be called from the AO that wants to stop.
Q_REQUIRE_ID(600, (this == QF::active_[QK_attr_.actPrio])); //! @pre QP::QActive::stop() must be called from the AO that wants to stop.
Q_REQUIRE_ID(400, (this == QF::active_[QK_attr_.actPrio]));
QF::remove_(this); // remove this active object from the QF QF::remove_(this); // remove this active object from the QF
@ -227,6 +219,115 @@ void QActive::stop(void) {
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
} }
//****************************************************************************
///
/// @description
/// This function locks the QK scheduler to the specified ceiling.
///
/// @param[in] ceiling priority ceiling to which the QK scheduler
/// needs to be locked
///
/// @returns
/// The previous QK Scheduler lock status, which is to be used to unlock
/// the scheduler by restoring its previous lock status in
/// QP::QK::schedUnlock().
///
/// @note
/// QP::QK::schedLock() must be always followed by the corresponding
/// QP::QK::schedUnlock().
///
/// @sa QK_schedUnlock()
///
/// @usage
/// The following example shows how to lock and unlock the QK scheduler:
/// @include qk_lock.cpp
///
QSchedStatus QK::schedLock(uint_fast8_t const ceiling) {
QSchedStatus stat;
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre The QK scheduler lock:
/// - cannot be called from an ISR;
Q_REQUIRE_ID(600, !QK_ISR_CONTEXT_());
// first store the previous lock prio
if (QK_attr_.lockPrio < ceiling) { // raising the lock prio?
stat = static_cast<QSchedStatus>(QK_attr_.lockPrio << 8);
QK_attr_.lockPrio = ceiling;
QS_BEGIN_NOCRIT_(QS_SCHED_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(stat), /* the previous lock prio */
static_cast<uint8_t>(QK_attr_.lockPrio)); // new lock prio
QS_END_NOCRIT_()
// add the previous lock holder priority
stat |= static_cast<QSchedStatus>(QK_attr_.lockHolder);
QK_attr_.lockHolder = QK_attr_.actPrio;
}
else {
stat = static_cast<QSchedStatus>(0xFF);
}
QF_CRIT_EXIT_();
return stat; // return the status to be saved in a stack variable
}
//****************************************************************************
///
/// @description
/// This function unlocks the QK scheduler to the previous status.
///
/// @param[in] stat previous QK Scheduler lock status returned from
/// QP::QK::schedLock()
/// @note
/// QP::QK::schedUnlock() must always follow the corresponding
/// QP::QK::schedLock().
///
/// @sa QP::QK::schedLock()
///
/// @usage
/// The following example shows how to lock and unlock the QK scheduler:
/// @include qk_lock.cpp
///
void QK::schedUnlock(QSchedStatus const stat) {
// has the scheduler been actually locked by the last QK_schedLock()?
if (stat != static_cast<QSchedStatus>(0xFF)) {
uint_fast8_t lockPrio = QK_attr_.lockPrio; // volatilie into tmp
uint_fast8_t prevPrio = static_cast<uint_fast8_t>(stat >> 8);
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre The scheduler cannot be unlocked:
/// - from the ISR context; and
/// - the current lock priority must be greater than the previous
Q_REQUIRE_ID(700, (!QK_ISR_CONTEXT_())
&& (lockPrio > prevPrio));
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(lockPrio),/* prio before unlocking */
static_cast<uint8_t>(prevPrio));// prio after unlocking
QS_END_NOCRIT_()
// restore the previous lock priority and lock holder
QK_attr_.lockPrio = prevPrio;
QK_attr_.lockHolder =
static_cast<uint_fast8_t>(stat & static_cast<QSchedStatus>(0xFF));
// find the highest-prio thread ready to run
if (QK_sched_() != static_cast<uint_fast8_t>(0)) { // priority found?
QK_activate_(); // activate any unlocked basic threads
}
QF_CRIT_EXIT_();
}
}
} // namespace QP } // namespace QP
//============================================================================ //============================================================================
@ -234,16 +335,16 @@ extern "C" {
//**************************************************************************** //****************************************************************************
/// @description /// @description
/// This function finds out the priority of the highest-priority active object /// The QK scheduler finds out the priority of the highest-priority AO
/// that (1) has events to process, and (2) has priority that is above the /// that (1) has events to process and (2) has priority that is above the
/// current priority, and (3) has priority that is above the mutex ceiling, /// current priority.
/// if mutex is configured in the port.
/// ///
/// @returns the 1-based priority of the the active object, or zero if /// @returns the 1-based priority of the the active object, or zero if
/// no eligible active object is ready to run. /// no eligible active object is ready to run.
/// ///
/// @attention QK_sched_() must be always called with interrupts /// @attention
/// __disabled__ and returns with interrupts __disabled__. /// QK_sched_() must be always called with interrupts **disabled** and
/// returns with interrupts **disabled**.
/// ///
uint_fast8_t QK_sched_(void) { uint_fast8_t QK_sched_(void) {
// find the highest-prio AO with non-empty event queue // find the highest-prio AO with non-empty event queue

View File

@ -1,12 +1,11 @@
/// @file /// @file
/// @brief QP::QMutex::init(), QP::QMutex::lock(), and QP::QMutex::unlock() /// @brief QK mutex implementation (obsolete).
/// definitions.
/// @ingroup qk /// @ingroup qk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Product: QK/C++ /// Product: QK/C++
/// Last updated for version 5.9.0 /// Last updated for version 5.9.7
/// Last updated on 2017-05-09 /// Last updated on 2017-08-18
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -37,138 +36,3 @@
/// mailto:info@state-machine.com /// mailto:info@state-machine.com
///*************************************************************************** ///***************************************************************************
/// @endcond /// @endcond
#define QP_IMPL // this is QF/QK implementation
#include "qf_port.h" // QF port
#include "qf_pkg.h" // QF package-scope internal interface
#include "qassert.h" // QP assertions
#ifdef Q_SPY // QS software tracing enabled?
#include "qs_port.h" // include QS port
#else
#include "qs_dummy.h" // disable the QS software tracing
#endif // Q_SPY
// protection against including this source file in a wrong project
#ifndef qk_h
#error "Source file included in a project NOT based on the QK kernel"
#endif // qk_h
namespace QP {
Q_DEFINE_THIS_MODULE("qk_mutex")
enum {
MUTEX_UNUSED = 0xFF
};
//****************************************************************************
/// @description
/// Initializes QK priority-ceiling mutex to the specified ceiling priority.
///
/// @param[in] prio ceiling priority of the mutex
///
/// @note
/// A mutex must be initialized before it can be locked or unlocked.
///
/// @sa QP::QMutex::lock(), QP::QMutex::unlock()
///
/// @usage
/// The following example shows how to initialize, lock and unlock QK mutex:
/// @include qk_mux.cpp
///
void QMutex::init(uint_fast8_t const prio) {
m_lockPrio = prio;
m_prevPrio = static_cast<uint_fast8_t>(MUTEX_UNUSED);
}
//****************************************************************************
/// @description
/// This function locks the QK mutex.
///
/// @note
/// A mutex must be initialized before it can be locked or unlocked.
///
/// @note
/// QP::QMutex::lock() must be always followed by the corresponding
/// QP::QMutex::unlock().
///
/// @sa QP::QMutex::init(), QP::QMutex::unlock()
///
/// @usage
/// The following example shows how to initialize, lock and unlock QK mutex:
/// @include qk_mux.cpp
///
void QMutex::lock(void) {
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre scheduler cannot be locked from the ISR context
/// and the mutex must be unused
Q_REQUIRE_ID(700, (!QK_ISR_CONTEXT_())
&& (m_prevPrio == static_cast<uint_fast8_t>(MUTEX_UNUSED)));
m_prevPrio = QK_attr_.lockPrio; // save the previous prio
if (QK_attr_.lockPrio < m_lockPrio) { // raising the lock prio?
QK_attr_.lockPrio = m_lockPrio;
}
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), /* previous lock prio */
static_cast<uint8_t>(QK_attr_.lockPrio)); // the new lock prio
QS_END_NOCRIT_()
QF_CRIT_EXIT_();
}
//****************************************************************************
/// @description
/// This function unlocks the QK mutex.
///
/// @note
/// A mutex must be initialized before it can be locked or unlocked.
///
/// @note
/// QP::QMutex::unlock() must always follow the corresponding
/// QP::QMutex::lock().
///
/// @sa QP::QMutex::init(), QP::QMutex::lock()
///
/// @usage
/// The following example shows how to initialize, lock and unlock QK mutex:
/// @include qk_mux.cpp
///
void QMutex::unlock(void) {
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre scheduler cannot be unlocked from the ISR context
/// and the mutex must not be unused
Q_REQUIRE_ID(800, (!QK_ISR_CONTEXT_())
&& (m_prevPrio != static_cast<uint_fast8_t>(MUTEX_UNUSED)));
uint_fast8_t p = m_prevPrio;
m_prevPrio = static_cast<uint_fast8_t>(MUTEX_UNUSED);
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(QK_attr_.lockPrio), /* prev lock prio */
(QK_attr_.lockPrio > p) /* the new lock prio */
? static_cast<uint8_t>(p)
: static_cast<uint8_t>(QK_attr_.lockPrio));
QS_END_NOCRIT_()
if (QK_attr_.lockPrio > p) {
QK_attr_.lockPrio = p; // restore the previous lock prio
if (QK_sched_() != static_cast<uint_fast8_t>(0)) { // priority found?
QK_activate_(); // activate any unlocked AOs
}
}
QF_CRIT_EXIT_();
}
} // namespace QP

View File

@ -4,8 +4,8 @@
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-07-27 /// Last updated on 2017-08-20
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -67,19 +67,20 @@ public:
QXKIdleThread() : QActive(Q_STATE_CAST(0)) QXKIdleThread() : QActive(Q_STATE_CAST(0))
{} {}
}; };
static QXKIdleThread l_idleThread;
//**************************************************************************** //****************************************************************************
/// @description /// @description
/// Initializes QF and must be called exactly once before any other QF /// Initializes QF and must be called exactly once before any other QF
/// function. Typically, QF_init() is called from main() even before /// function. Typically, QF::init() is called from main() even before
/// initializing the Board Support Package (BSP). /// initializing the Board Support Package (BSP).
/// ///
/// @note QF::init() clears the internal QF variables, so that the framework /// @note QF::init() clears the internal QF variables, so that the framework
/// can start correctly even if the startup code fails to clear the /// can start correctly even if the startup code fails to clear the
/// uninitialized data (as is required by the C+ Standard). /// uninitialized data (as is required by the C++ Standard).
/// ///
void QF::init(void) { void QF::init(void) {
static QXKIdleThread s_idleThread;
QF_maxPool_ = static_cast<uint_fast8_t>(0); QF_maxPool_ = static_cast<uint_fast8_t>(0);
QF_subscrList_ = static_cast<QSubscrList *>(0); QF_subscrList_ = static_cast<QSubscrList *>(0);
QF_maxPubSignal_ = static_cast<enum_t>(0); QF_maxPubSignal_ = static_cast<enum_t>(0);
@ -87,13 +88,13 @@ void QF::init(void) {
bzero(&timeEvtHead_[0], static_cast<uint_fast16_t>(sizeof(timeEvtHead_))); bzero(&timeEvtHead_[0], static_cast<uint_fast16_t>(sizeof(timeEvtHead_)));
bzero(&active_[0], static_cast<uint_fast16_t>(sizeof(active_))); bzero(&active_[0], static_cast<uint_fast16_t>(sizeof(active_)));
bzero(&QXK_attr_, static_cast<uint_fast16_t>(sizeof(QXK_attr_))); bzero(&QXK_attr_, static_cast<uint_fast16_t>(sizeof(QXK_attr_)));
bzero(&l_idleThread, static_cast<uint_fast16_t>(sizeof(l_idleThread))); bzero(&s_idleThread, static_cast<uint_fast16_t>(sizeof(s_idleThread)));
// setup the QXK scheduler as initially locked and not running // setup the QXK scheduler as initially locked and not running
QXK_attr_.lockPrio = static_cast<uint_fast8_t>(QF_MAX_ACTIVE + 1); QXK_attr_.lockPrio = static_cast<uint_fast8_t>(QF_MAX_ACTIVE + 1);
// setup the QXK idle loop... // setup the QXK idle loop...
active_[0] = &l_idleThread; // register the idle thread with QF active_[0] = &s_idleThread; // register the idle thread with QF
QXK_attr_.actPrio = static_cast<uint_fast8_t>(0); // set idle thread prio QXK_attr_.actPrio = static_cast<uint_fast8_t>(0); // set idle thread prio
#ifdef QXK_INIT #ifdef QXK_INIT
@ -131,9 +132,8 @@ static void initial_events(void) {
//**************************************************************************** //****************************************************************************
/// @description /// @description
/// QP::QF::run() is typically called from your startup code after you /// QF::run() is typically called from main() after you initialize
/// initialize the QF and start at least one basic- or extended-thread /// the QF and start at least one active object with QActive::start().
/// (with QP::QActive::start() or QP::QXThread::start(), respectively).
/// ///
/// @returns In QXK, the QF::run() function does not return. /// @returns In QXK, the QF::run() function does not return.
/// ///
@ -174,30 +174,28 @@ void QActive::start(uint_fast8_t const prio,
void * const stkSto, uint_fast16_t const stkSize, void * const stkSto, uint_fast16_t const stkSize,
QEvt const * const ie) QEvt const * const ie)
{ {
/// @pre AO cannot be started from an ISR, the priority must be in range /// @pre AO cannot be started:
/// and the stack storage must not be provided, because the QK kernel /// - from an ISR;
/// does not need per-AO stacks. /// - the priority must be in range;
/// /// - the stack storage must NOT be provided (because the QXK kernel does
Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) /// not need per-AO stacks).
&& (static_cast<uint_fast8_t>(0) < prio) Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_())
&& (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE)) && (static_cast<uint_fast8_t>(0) < prio)
&& (stkSto == static_cast<void *>(0)) && (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE))
&& (stkSize == static_cast<uint_fast16_t>(0))); && (stkSto == static_cast<void *>(0))
&& (stkSize == static_cast<uint_fast16_t>(0)));
m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO
m_osObject = static_cast<void *>(0); // no private stack for AO m_osObject = static_cast<void *>(0); // no private stack for AO
m_prio = prio; // set the QF priority of this AO m_prio = prio; // set the QF priority of this AO
m_startPrio = prio; // set the start QF priority of this AO
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
QF::add_(this); // make QF aware of this AO QF::add_(this); // make QF aware of this AO
QF_CRIT_EXIT_();
this->init(ie); // take the top-most initial tran. (virtual) this->init(ie); // take the top-most initial tran. (virtual)
QS_FLUSH(); // flush the trace buffer to the host QS_FLUSH(); // flush the trace buffer to the host
// see if this AO needs to be scheduled in case QXK is running // see if this AO needs to be scheduled in case QXK is running
QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
if (QXK_sched_() != static_cast<uint_fast8_t>(0)) { // activation needed? if (QXK_sched_() != static_cast<uint_fast8_t>(0)) { // activation needed?
QXK_activate_(); QXK_activate_();
@ -217,9 +215,8 @@ void QActive::start(uint_fast8_t const prio,
// from all events and no more events should be directly-posted to it. // from all events and no more events should be directly-posted to it.
// //
void QActive::stop(void) { void QActive::stop(void) {
/// @pre QActive_stop() must be called from the AO that wants to stop. /// @pre QActive::stop() must be called from the AO that wants to stop.
Q_REQUIRE_ID(600, (!QXK_ISR_CONTEXT_()) /* don't stop AO's from an ISR! */ Q_REQUIRE_ID(300, (this == QF::active_[QXK_attr_.actPrio]));
&& (this == QXK_attr_.curr));
QF::remove_(this); // remove this active object from the QF QF::remove_(this); // remove this active object from the QF
@ -232,6 +229,115 @@ void QActive::stop(void) {
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
} }
//****************************************************************************
/// @description
/// This function locks the QXK scheduler to the specified ceiling.
///
/// @param[in] ceiling priority ceiling to which the QXK scheduler
/// needs to be locked
///
/// @returns
/// The previous QXK Scheduler lock status, which is to be used to unlock
/// the scheduler by restoring its previous lock status in QXK::schedUnlock().
///
/// @note
/// QXK::schedLock() must be always followed by the corresponding
/// QXK::schedUnlock().
///
/// @sa QXK::schedUnlock()
///
/// @usage
/// The following example shows how to lock and unlock the QXK scheduler:
/// @include qxk_lock.cpp
///
QSchedStatus QXK::schedLock(uint_fast8_t const ceiling) {
QSchedStatus stat;
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre The QXK scheduler lock:
/// - cannot be called from an ISR;
Q_REQUIRE_ID(400, !QXK_ISR_CONTEXT_());
// first store the previous lock prio
if (QXK_attr_.lockPrio < ceiling) { // raising the lock prio?
stat = static_cast<QSchedStatus>(QXK_attr_.lockPrio << 8);
QXK_attr_.lockPrio = ceiling;
QS_BEGIN_NOCRIT_(QS_SCHED_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(stat), /* the previous lock prio */
static_cast<uint8_t>(QXK_attr_.lockPrio)); // new lock prio
QS_END_NOCRIT_()
// add the previous lock holder priority
stat |= static_cast<QSchedStatus>(QXK_attr_.lockHolder);
QXK_attr_.lockHolder =
(QXK_attr_.curr != static_cast<QActive *>(0))
? QXK_attr_.curr->m_prio
: static_cast<uint_fast8_t>(0);
}
else {
stat = static_cast<QSchedStatus>(0xFF);
}
QF_CRIT_EXIT_();
return stat; // return the status to be saved in a stack variable
}
//****************************************************************************
///
/// @description
/// This function unlocks the QXK scheduler to the previous status.
///
/// @param[in] stat previous QXK Scheduler lock status returned from
/// QXK::schedLock()
/// @note
/// QXK::schedUnlock() must always follow the corresponding
/// QXK::schedLock().
///
/// @sa QXK::schedLock()
///
/// @usage
/// The following example shows how to lock and unlock the QXK scheduler:
/// @include qxk_lock.cpp
///
void QXK::schedUnlock(QSchedStatus const stat) {
// has the scheduler been actually locked by the last QXK_schedLock()?
if (stat != static_cast<QSchedStatus>(0xFF)) {
uint_fast8_t lockPrio = QXK_attr_.lockPrio; // volatilie into tmp
uint_fast8_t prevPrio = static_cast<uint_fast8_t>(stat >> 8);
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre The scheduler cannot be unlocked:
/// - from the ISR context; and
/// - the current lock priority must be greater than the previous
Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_())
&& (lockPrio > prevPrio));
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(lockPrio),/* prio before unlocking */
static_cast<uint8_t>(prevPrio));// prio after unlocking
QS_END_NOCRIT_()
// restore the previous lock priority and lock holder
QXK_attr_.lockPrio = prevPrio;
QXK_attr_.lockHolder =
static_cast<uint_fast8_t>(stat & static_cast<QSchedStatus>(0xFF));
// 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
}
QF_CRIT_EXIT_();
}
}
} // namespace QP } // namespace QP
@ -261,7 +367,7 @@ uint_fast8_t QXK_sched_(void) {
QP::QActive *next = QP::QF::active_[p]; QP::QActive *next = QP::QF::active_[p];
// the thread found must be registered in QF // the thread found must be registered in QF
//Q_ASSERT_ID(610, next != static_cast<QP::QActive *>(0)); Q_ASSERT_ID(610, next != static_cast<QP::QActive *>(0));
// is the current thread a basic-thread? // is the current thread a basic-thread?
if (QXK_attr_.curr == static_cast<QP::QActive *>(0)) { if (QXK_attr_.curr == static_cast<QP::QActive *>(0)) {
@ -296,6 +402,7 @@ uint_fast8_t QXK_sched_(void) {
// is the new prio different from the current prio? // is the new prio different from the current prio?
if (p != QXK_attr_.curr->m_prio) { if (p != QXK_attr_.curr->m_prio) {
QS_BEGIN_NOCRIT_(QP::QS_SCHED_NEXT, QS_BEGIN_NOCRIT_(QP::QS_SCHED_NEXT,
QP::QS::priv_.locFilter[QP::QS::AO_OBJ], QP::QS::priv_.locFilter[QP::QS::AO_OBJ],
QXK_attr_.next) QXK_attr_.next)
@ -326,8 +433,8 @@ uint_fast8_t QXK_sched_(void) {
/// returns with interrupts **disabled**. /// returns with interrupts **disabled**.
/// ///
void QXK_activate_(void) { void QXK_activate_(void) {
uint_fast8_t p = QXK_attr_.next->m_prio;
uint_fast8_t pin = QXK_attr_.actPrio; // save the initial active prio uint_fast8_t pin = QXK_attr_.actPrio; // save the initial active prio
uint_fast8_t p = QXK_attr_.next->m_prio;
QP::QActive *a; QP::QActive *a;
// QS tracing or thread-local storage? // QS tracing or thread-local storage?
@ -377,12 +484,12 @@ void QXK_activate_(void) {
p = QXK_attr_.readySet.findMax(); p = QXK_attr_.readySet.findMax();
if (p <= QXK_attr_.lockPrio) { // is it below the lock prio? if (p <= QXK_attr_.lockPrio) { // is it below the lock prio?
p = QXK_attr_.lockHolder; // prio of the thread holding the lock p = QXK_attr_.lockHolder; // prio of the thread holding lock
} }
a = QP::QF::active_[p]; a = QP::QF::active_[p];
// the AO must be registered in QF // the AO must be registered in QF
//Q_ASSERT_ID(710, a != static_cast<QP::QActive *>(0)); Q_ASSERT_ID(710, a != static_cast<QP::QActive *>(0));
// is the next an AO-thread? // is the next an AO-thread?
if (a->m_osObject == static_cast<void *>(0)) { if (a->m_osObject == static_cast<void *>(0)) {
@ -400,8 +507,8 @@ void QXK_activate_(void) {
QP::QS::priv_.locFilter[QP::QS::AO_OBJ], QP::QS::priv_.locFilter[QP::QS::AO_OBJ],
QXK_attr_.next) QXK_attr_.next)
QS_TIME_(); // timestamp QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(p), // prio of the next thread QS_2U8_(static_cast<uint8_t>(p), /* prio of the next thr */
static_cast<uint8_t>( // prio of the curent thread static_cast<uint8_t>( /* prio of the curent thr */
QXK_attr_.actPrio)); QXK_attr_.actPrio));
QS_END_NOCRIT_() QS_END_NOCRIT_()
@ -440,6 +547,11 @@ QP::QActive *QXK_current(void) {
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
/// @pre the QXK kernel must be running
Q_REQUIRE_ID(800,
QXK_attr_.lockPrio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE));
curr = QXK_attr_.curr; curr = QXK_attr_.curr;
if (curr == static_cast<QP::QActive *>(0)) { // basic thread? if (curr == static_cast<QP::QActive *>(0)) { // basic thread?
curr = QP::QF::active_[QXK_attr_.actPrio]; curr = QP::QF::active_[QXK_attr_.actPrio];
@ -447,7 +559,7 @@ QP::QActive *QXK_current(void) {
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
//! @post the current thread must be valid //! @post the current thread must be valid
Q_ENSURE_ID(900, curr != static_cast<QP::QActive *>(0)); Q_ENSURE_ID(890, curr != static_cast<QP::QActive *>(0));
return curr; return curr;
} }

View File

@ -1,12 +1,11 @@
/// @file /// @file
/// @brief QP::QXMutex::init(), QP::QXMutex::lock(), and QP::QXMutex::unlock() /// @brief Priority-ceiling blocking mutex QP::QXMutex class definition
/// definitions.
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Product: QK/C++ /// Product: QK/C++
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-07-27 /// Last updated on 2017-08-19
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -57,147 +56,331 @@ namespace QP {
Q_DEFINE_THIS_MODULE("qxk_mutex") Q_DEFINE_THIS_MODULE("qxk_mutex")
enum { //****************************************************************************/
MUTEX_UNUSED = 0xFF
};
//****************************************************************************
/// @description /// @description
/// Initializes QXK priority-ceiling mutex to the specified ceiling priority. /// Initialize the QXK priority ceiling mutex.
/// ///
/// @param[in] prio ceiling priority of the mutex /// @param[in] ceiling ceiling priotity of the mutex
/// ///
/// @note /// @note
/// A mutex must be initialized before it can be locked or unlocked. /// The ceiling priority must be unused by any thread. The ceiling
/// /// priority must be higher than priority of any thread that uses the
/// @sa QP::QXMutex::lock(), QP::QXMutex::unlock() /// protected resource.
/// ///
/// @usage /// @usage
/// The following example shows how to initialize, lock and unlock QXK mutex:
/// @include qxk_mux.cpp /// @include qxk_mux.cpp
/// ///
void QXMutex::init(uint_fast8_t const prio) { void QXMutex::init(uint_fast8_t ceiling) {
m_lockPrio = prio;
m_prevPrio = static_cast<uint_fast8_t>(MUTEX_UNUSED);
}
//****************************************************************************
/// @description
/// This function locks the QXK mutex.
///
/// @note
/// A mutex must be initialized before it can be locked or unlocked.
///
/// @note
/// QP::QXMutex::lock() must be always followed by the corresponding
/// QP::QXMutex::unlock().
///
/// @attention
/// A thread holding a mutex __cannot block__.
///
/// @sa QP::QXMutex::init(), QP::QXMutex::unlock()
///
/// @usage
/// The following example shows how to initialize, lock and unlock QXK mutex:
/// @include qxk_mux.cpp
///
void QXMutex::lock(void) {
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
/// @pre the celiling priority of the mutex must:
/// - not be zero;
/// - cannot exceed the maximum #QF_MAX_ACTIVE;
/// - the ceiling priority of the mutex must not be already in use;
/// (QF requires priority to be **unique**).
Q_REQUIRE_ID(100, (static_cast<uint_fast8_t>(0) < ceiling)
&& (ceiling <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE))
&& (QF::active_[ceiling] == static_cast<QActive *>(0)));
/// @pre The mutex cannot be locked from the ISR context m_ceiling = ceiling;
/// and the mutex must be unused m_lockNest = static_cast<uint_fast8_t>(0);
Q_REQUIRE_ID(700, (!QXK_ISR_CONTEXT_()) QF::bzero(&m_waitSet, static_cast<uint_fast16_t>(sizeof(m_waitSet)));
&& (m_prevPrio == static_cast<uint_fast8_t>(MUTEX_UNUSED)));
m_prevPrio = QXK_attr_.lockPrio; // save previous lock prio // reserve the ceiling priority level for this mutex
m_prevHolder = QXK_attr_.lockHolder; // save previous lock holder QF::active_[ceiling] = reinterpret_cast<QActive *>(this);
if (QXK_attr_.lockPrio < m_lockPrio) { // raising the lock prio?
QXK_attr_.lockPrio = m_lockPrio;
}
QXK_attr_.lockHolder =
(QXK_attr_.curr != static_cast<QActive *>(0))
? QXK_attr_.curr->m_prio
: static_cast<uint_fast8_t>(0);
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), /* previous lock prio */
static_cast<uint8_t>(QXK_attr_.lockPrio)); // new lock prio
QS_END_NOCRIT_()
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
} }
//**************************************************************************** //****************************************************************************
///
/// @description /// @description
/// This function unlocks the QXK mutex. /// Lock the QXK priority ceiling mutex QP::QXMutex.
///
/// @param[in] nTicks number of clock ticks (at the associated rate)
/// to wait for the semaphore. The value of
/// #QXTHREAD_NO_TIMEOUT indicates that no timeout will
/// occur and the semaphore will wait indefinitely.
/// @returns
/// 'true' if the mutex has been acquired and 'false' if a timeout occured.
/// ///
/// @note /// @note
/// A mutex must be initialized before it can be locked or unlocked. /// The mutex locks are allowed to nest, meaning that the same extended thread
/// /// can lock the same mutex multiple times (<= 225). However, each call to
/// @note /// QXMutex::lock() must be ballanced by the matching call to
/// QP::QXMutex::unlock() must always follow the corresponding /// QXMutex::unlock().
/// QP::QXMutex::lock(). ///
/// /// @usage
/// @sa QP::QXMutex::init(), QP::QXMutex::lock() /// @include qxk_mux.cpp
///
bool QXMutex::lock(uint_fast16_t const nTicks) {
QXThread *thr;
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
thr = static_cast<QXThread *>(QXK_attr_.curr);
/// @pre this function must:
/// - NOT be called from an ISR;
/// - be called from an extended thread;
/// - the thread priority must be below the ceiling of the mutex;
/// - the thread must NOT be holding a scheduler lock;
/// - the thread must NOT be already blocked on any object.
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
&& (thr != static_cast<QXThread *>(0)) /* thr must be extended */
&& (thr->m_startPrio < m_ceiling) /* prio below the ceiling */
&& (QXK_attr_.lockHolder != thr->m_prio) /* not holding a lock */
&& (thr->m_temp.obj == static_cast<QMState *>(0))); // not blocked
// is the mutex available?
if (m_lockNest == static_cast<uint_fast8_t>(0)) {
m_lockNest = static_cast<uint_fast8_t>(1);
// the priority slot must be set to this mutex */
Q_ASSERT_ID(210,
QF::active_[m_ceiling] == reinterpret_cast<QActive *>(this));
// switch the priority of this thread to the mutex ceiling
thr->m_prio = m_ceiling;
QF::active_[m_ceiling] = thr;
QXK_attr_.readySet.remove(thr->m_startPrio);
QXK_attr_.readySet.insert(thr->m_prio);
QS_BEGIN_NOCRIT_(QS_MUTEX_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(thr->m_startPrio), /* start prio */
static_cast<uint8_t>(thr->m_prio)); // current ceiling
QS_END_NOCRIT_()
}
// is the mutex locked by this thread already (nested locking)?
else if (QF::active_[m_ceiling] == thr) {
// the nesting level must not exceed 0xFF
Q_ASSERT_ID(220, m_lockNest < static_cast<uint_fast8_t>(0xFF));
++m_lockNest;
}
else { // the mutex is alredy locked by a different thread
// the prio slot must be claimed by the thread holding the mutex
Q_ASSERT_ID(230, QF::active_[m_ceiling] != static_cast<QActive *>(0));
// remove this thr prio from the ready set (block)
// and insert to the waiting set on this mutex
QXK_attr_.readySet.remove(thr->m_prio);
m_waitSet.insert(thr->m_prio);
// store the blocking object (this mutex)
thr->m_temp.obj = reinterpret_cast<QMState *>(this);
thr->teArm_(static_cast<enum_t>(QXK_SEMA_SIG), nTicks);
// schedule the next thread if multitasking started
(void)QXK_sched_();
QF_CRIT_EXIT_();
QF_CRIT_EXIT_NOP(); // BLOCK here
QF_CRIT_ENTRY_();
// the blocking object must be this mutex
Q_ASSERT_ID(240, thr->m_temp.obj == reinterpret_cast<QMState *>(this));
thr->m_temp.obj = static_cast<QMState *>(0); // clear
}
QF_CRIT_EXIT_();
// signal of non-zero means that the time event has not expired
return thr->m_timeEvt.sig != static_cast<QSignal>(0);
}
//****************************************************************************
///
/// @description
/// Try to lock the QXK priority ceiling mutex QP::QXMutex.
///
/// @returns
/// 'true' if the mutex was successfully locked and 'false' if the mutex was
/// unavailable and was NOT locked.
///
/// @note
/// This function **can** be called from both basic threads (active objects)
/// and extended threads.
///
/// @note
/// The mutex locks are allowed to nest, meaning that the same extended thread
/// can lock the same mutex multiple times (<= 225). However, each successful
/// call to QXMutex_tryLock() must be ballanced by the matching call to
/// QXMutex::unlock().
///
bool QXMutex::tryLock(void) {
QActive *curr;
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
curr = QXK_attr_.curr;
if (curr == static_cast<QActive *>(0)) { // called from a basic thread?
curr = QF::active_[QXK_attr_.actPrio];
}
/// @pre this function must:
/// - NOT be called from an ISR;
/// - the QXK kernel must be running;
/// - the calling thread must be valid;
/// - the thread priority must be below the ceiling of the mutex;
/// - the thread must NOT be holding a scheduler lock;
Q_REQUIRE_ID(300, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
&& (QXK_attr_.lockPrio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE))
&& (curr != static_cast<QActive *>(0)) /* curr thread must be valid */
&& (curr->m_startPrio < m_ceiling) /* prio below the ceiling */
&& (curr->m_prio != QXK_attr_.lockHolder)); // not holding a lock
// is the mutex available?
if (m_lockNest == static_cast<uint_fast8_t>(0)) {
m_lockNest = static_cast<uint_fast8_t>(1);
// the priority slot must be set to this mutex
Q_ASSERT_ID(310,
QF::active_[m_ceiling] == reinterpret_cast<QActive *>(this));
// switch the priority of this thread to the mutex ceiling
curr->m_prio = m_ceiling;
QF::active_[m_ceiling] = curr;
QXK_attr_.readySet.remove(curr->m_startPrio);
QXK_attr_.readySet.insert(curr->m_prio);
QS_BEGIN_NOCRIT_(QS_MUTEX_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(curr->m_startPrio), /* start prio */
static_cast<uint8_t>(curr->m_prio)); // current ceiling
QS_END_NOCRIT_()
}
// is the mutex locked by this thread already (nested locking)?
else if (QF::active_[m_ceiling] == curr) {
// the nesting level must not exceed 0xFF
Q_ASSERT_ID(320, m_lockNest < static_cast<uint_fast8_t>(0xFF));
++m_lockNest;
}
else { // the mutex is alredy locked by a different thread
// the prio slot must be claimed by the thread holding the mutex
Q_ASSERT_ID(330, QF::active_[m_ceiling] != static_cast<QActive *>(0));
curr = static_cast<QActive *>(0); // means that mutex is NOT available
}
QF_CRIT_EXIT_();
return curr != static_cast<QActive *>(0);
}
//****************************************************************************
/// @description
/// Unlock the QXK priority ceiling mutex.
///
/// @note
/// This function **can** be called from both basic threads (active objects)
/// and extended threads.
///
/// @note
/// The mutex locks are allowed to nest, meaning that the same extended thread
/// can lock the same mutex multiple times (<= 225). However, each call to
/// QXMutex::lock() or a _successfull_ call to QXMutex_tryLock() must be
/// ballanced by the matching call to QXMutex::unlock().
/// ///
/// @usage /// @usage
/// The following example shows how to initialize, lock and unlock QXK mutex:
/// @include qxk_mux.cpp /// @include qxk_mux.cpp
/// ///
void QXMutex::unlock(void) { void QXMutex::unlock(void) {
QActive *curr;
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
curr = static_cast<QActive *>(QXK_attr_.curr);
if (curr == static_cast<QActive *>(0)) { // called from a basic thread?
curr = QF::active_[QXK_attr_.actPrio];
}
/// @pre The mutex cannot be unlocked from the ISR context /// @pre this function must:
/// and the mutex must NOT be unused /// - NOT be called from an ISR;
Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_()) /// - the calling thread must be valid;
&& (m_prevPrio != static_cast<uint_fast8_t>(MUTEX_UNUSED))); /// - the mutex must be held by this thread;
/// - the holding thread must have priority equal to the mutex ceiling;
/// - the mutex must be already locked at least once.
Q_REQUIRE_ID(400, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
&& (curr != static_cast<QActive *>(0)) /* curr must be valid */
&& (curr == QF::active_[m_ceiling]) /* held by this thr */
&& (curr->m_prio == m_ceiling) /* thr prio at the ceiling */
&& (m_lockNest > static_cast<uint_fast8_t>(0)));//locked at least once
uint_fast8_t p = m_prevPrio; // the previouis lock prio // is this the last nesting level?
m_prevPrio = static_cast<uint_fast8_t>(MUTEX_UNUSED); if (m_lockNest == static_cast<uint_fast8_t>(1)) {
QXK_attr_.lockHolder = m_prevHolder; // restore previous lock holder
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, // restore the holding thread's priority to the original
static_cast<void *>(0), static_cast<void *>(0)) curr->m_prio = curr->m_startPrio;
QS_TIME_(); // timestamp
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) { // remove the boosted priority and insert the original priority
QXK_attr_.readySet.remove(m_ceiling);
QXK_attr_.readySet.insert(curr->m_startPrio);
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, QS_BEGIN_NOCRIT_(QS_MUTEX_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0)) static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(QXK_attr_.lockPrio), /* prev lock */ QS_2U8_(static_cast<uint8_t>(curr->m_startPrio), /* start prio */
static_cast<uint8_t>(p)); // new lock prio static_cast<uint8_t>(m_ceiling)); // the mutex ceiling
QS_END_NOCRIT_() QS_END_NOCRIT_()
QXK_attr_.lockPrio = p; // restore the previous lock prio // are any other threads waiting for this mutex?
// find the highest-prio thread ready to run if (m_waitSet.notEmpty()) {
if (QXK_sched_() != static_cast<uint_fast8_t>(0)) { // priority found?
QXK_activate_(); // activate any unlocked basic threads // find the highest-priority waiting thread
uint_fast8_t p = m_waitSet.findMax();
QXThread *thr = static_cast<QXThread *>(QF::active_[p]);
// the waiting thread must:
// (1) have priority below the ceiling
// (2) be extended
// (3) not be redy to run
// (4) have still the start priority
// (5) be blocked on this mutex
Q_ASSERT_ID(410, (p < m_ceiling)
&& (thr != static_cast<QXThread *>(0)) /* extended thread */
&& (!QXK_attr_.readySet.hasElement(p))
&& (thr->m_prio == thr->m_startPrio)
&& (thr->m_temp.obj == reinterpret_cast<QMState *>(this)));
// disarm the internal time event
(void)thr->teDisarm_();
// this thread is no longer waiting for the mutex
m_waitSet.remove(p);
// switch the priority of this thread to the mutex ceiling
thr->m_prio = m_ceiling;
QF::active_[m_ceiling] = thr;
// make the thread ready to run (at the ceiling prio)
QXK_attr_.readySet.insert(thr->m_prio);
QS_BEGIN_NOCRIT_(QS_MUTEX_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(thr->m_startPrio),/*start prio*/
static_cast<uint8_t>(thr->m_prio)); // ceiling prio
QS_END_NOCRIT_()
}
else { // no threads are waiting for this mutex
m_lockNest = static_cast<uint_fast8_t>(0);
// put the mutex at the priority ceiling slot
QF::active_[m_ceiling] = reinterpret_cast<QActive *>(this);
}
// schedule the next thread if multitasking started
if (QXK_sched_() != static_cast<uint_fast8_t>(0)) {
QXK_activate_(); // activate a basic thread
} }
} }
else { else { // releasing the mutex
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, --m_lockNest; // release one level
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_(); QF_CRIT_EXIT_();
} }

View File

@ -3,8 +3,8 @@
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.7.2 /// Last updated for version 5.9.7
/// Last updated on 2016-09-28 /// Last updated on 2017-08-19
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -54,7 +54,7 @@ enum QXK_Timeouts {
extern "C" { extern "C" {
//! initialize the private stack of a given AO //! initialize the private stack of a given AO
void QXK_stackInit_(void *act, QP::QXThreadHandler handler, void QXK_stackInit_(void *thr, QP::QXThreadHandler handler,
void *stkSto, uint_fast16_t stkSize); void *stkSto, uint_fast16_t stkSize);
//! called when a thread function returns //! called when a thread function returns

View File

@ -3,8 +3,8 @@
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
////************************************************************************** ////**************************************************************************
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-07-27 /// Last updated on 2017-08-20
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -98,17 +98,13 @@ void QXSemaphore::init(uint_fast16_t const count,
/// to wait for the semaphore. The value of /// to wait for the semaphore. The value of
/// QXTHREAD_NO_TIMEOUT indicates that no timeout will /// QXTHREAD_NO_TIMEOUT indicates that no timeout will
/// occur and the semaphore will wait indefinitely. /// occur and the semaphore will wait indefinitely.
/// @param[in] tickRate system clock tick rate serviced in this call.
///
/// @returns /// @returns
/// true if the semaphore has been signaled, and false if the timeout occured. /// true if the semaphore has been signaled, and false if the timeout occured.
/// ///
/// @note /// @note
/// Multiple extended threads can wait for a given semahpre. /// Multiple extended threads can wait for a given semahpre.
/// ///
bool QXSemaphore::wait(uint_fast16_t const nTicks, bool QXSemaphore::wait(uint_fast16_t const nTicks) {
uint_fast8_t const tickRate)
{
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
@ -122,7 +118,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */ && (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* no lock */ && (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* no lock */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked && (thr->m_temp.obj == static_cast<QMState *>(0))); // !blocked
if (m_count > static_cast<uint_fast16_t>(0)) { if (m_count > static_cast<uint_fast16_t>(0)) {
--m_count; --m_count;
@ -131,7 +127,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
else { else {
// remember the blocking object // remember the blocking object
thr->m_temp.obj = reinterpret_cast<QMState const *>(this); thr->m_temp.obj = reinterpret_cast<QMState const *>(this);
thr->teArm_(static_cast<enum_t>(QXK_SEMA_SIG), nTicks, tickRate); thr->teArm_(static_cast<enum_t>(QXK_SEMA_SIG), nTicks);
m_waitSet.insert(thr->m_prio); m_waitSet.insert(thr->m_prio);
QXK_attr_.readySet.remove(thr->m_prio); QXK_attr_.readySet.remove(thr->m_prio);
(void)QXK_sched_(); (void)QXK_sched_();
@ -142,7 +138,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
// the blocking object must be this semaphore // the blocking object must be this semaphore
Q_ASSERT_ID(210, thr->m_temp.obj Q_ASSERT_ID(210, thr->m_temp.obj
== reinterpret_cast<QMState const *>(this)); == reinterpret_cast<QMState const *>(this));
thr->m_temp.obj = static_cast<QMState const *>(0); // clear thr->m_temp.obj = static_cast<QMState *>(0); // clear
} }
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
@ -150,6 +146,40 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
return (thr->m_timeEvt.sig != static_cast<QSignal>(0)); return (thr->m_timeEvt.sig != static_cast<QSignal>(0));
} }
//****************************************************************************
///
/// @description
/// This operation checks if the semaphore counter is greater than 0,
/// in which case the counter is decremented.
///
/// @returns
/// 'true' if the semaphore has count available and 'false' NOT available.
///
/// @note
/// This function can be called from any context, including ISRs and basic
/// threds (active objects).
///
bool QXSemaphore::tryWait(void) {
bool isAvailable;
QF_CRIT_STAT_
/// @pre the semaphore must be initialized
Q_REQUIRE_ID(300, (m_max_count > static_cast<uint_fast16_t>(0)));
QF_CRIT_ENTRY_();
// is the semaphore available?
if (m_count > static_cast<uint_fast16_t>(0)) {
--m_count;
isAvailable = true;
}
else { // the semaphore is NOT available (would block)
isAvailable = false;
}
QF_CRIT_EXIT_();
return isAvailable;
}
//**************************************************************************** //****************************************************************************
/// @description /// @description
/// If the semaphore counter value is 0 or more, it is incremented, and this /// If the semaphore counter value is 0 or more, it is incremented, and this
@ -171,6 +201,9 @@ bool QXSemaphore::signal(void) {
bool signaled = true; // assume that the semaphore will be signaled bool signaled = true; // assume that the semaphore will be signaled
QF_CRIT_STAT_ QF_CRIT_STAT_
/// @pre the semaphore must be initialized
Q_REQUIRE_ID(400, (m_max_count > (uint_fast16_t)0));
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
if (m_waitSet.notEmpty()) { if (m_waitSet.notEmpty()) {
uint_fast8_t p = m_waitSet.findMax(); uint_fast8_t p = m_waitSet.findMax();
@ -180,7 +213,7 @@ bool QXSemaphore::signal(void) {
QXThread *thr = static_cast<QXThread *>(QF::active_[p]); QXThread *thr = static_cast<QXThread *>(QF::active_[p]);
// the thread must be extended and the semaphore count must be zero // the thread must be extended and the semaphore count must be zero
Q_ASSERT_ID(210, (thr != static_cast<QXThread *>(0)) /* registered */ Q_ASSERT_ID(410, (thr != static_cast<QXThread *>(0)) /* registered */
&& (thr->m_osObject != static_cast<void *>(0)) /* extended */ && (thr->m_osObject != static_cast<void *>(0)) /* extended */
&& (m_count == static_cast<uint_fast16_t>(0))); // not signaled && (m_count == static_cast<uint_fast16_t>(0))); // not signaled

View File

@ -3,8 +3,8 @@
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-07-27 /// Last updated on 2017-08-19
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -69,7 +69,7 @@ Q_DEFINE_THIS_MODULE("qxk_xthr")
/// @usage /// @usage
/// The following example illustrates how to invoke the QXThread ctor in the /// The following example illustrates how to invoke the QXThread ctor in the
/// main() function /// main() function
/// @include qxk_xthread_ctor.cpp /// @include qxk_xctor.cpp
/// ///
QXThread::QXThread(QXThreadHandler const handler, uint_fast8_t const tickRate) QXThread::QXThread(QXThreadHandler const handler, uint_fast8_t const tickRate)
: QActive(Q_STATE_CAST(handler)), : QActive(Q_STATE_CAST(handler)),
@ -107,18 +107,21 @@ void QXThread::dispatch(QEvt const * const /*e*/) {
/// @param[in] stkSize stack size [in bytes] (must not be zero) /// @param[in] stkSize stack size [in bytes] (must not be zero)
/// @param[in] ie pointer to the initial event (not used). /// @param[in] ie pointer to the initial event (not used).
/// ///
/// @note This function should be called via the macro QXTHREAD_START().
///
/// @usage /// @usage
/// The following example shows starting an extended thread: /// The following example shows starting an extended thread:
/// @include qxk_xthread_start.cpp /// @include qxk_xstart.cpp
/// ///
void QXThread::start(uint_fast8_t const prio, void QXThread::start(uint_fast8_t const prio,
QEvt const *qSto[], uint_fast16_t const qLen, QEvt const *qSto[], uint_fast16_t const qLen,
void * const stkSto, uint_fast16_t const stkSize, void * const stkSto, uint_fast16_t const stkSize,
QEvt const * const /*ie*/) QEvt const * const /*ie*/)
{ {
Q_REQUIRE_ID(300, (!QXK_ISR_CONTEXT_()) /* don't start AO's in an ISR! */ /// @pre this function must:
/// - NOT be called from an ISR;
/// - the thread priority cannot exceed #QF_MAX_ACTIVE;
/// - the stack storage must be provided;
/// - the thread must be instantiated (see QP::QXThread::QXThread()).
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* don't start AO's in an ISR! */
&& (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE)) && (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE))
&& (stkSto != static_cast<void *>(0)) && (stkSto != static_cast<void *>(0))
&& (stkSize != static_cast<uint_fast16_t>(0)) && (stkSize != static_cast<uint_fast16_t>(0))
@ -135,6 +138,7 @@ void QXThread::start(uint_fast8_t const prio,
stkSto, stkSize); stkSto, stkSize);
m_prio = prio; m_prio = prio;
m_startPrio = prio;
QF::add_(this); // make QF aware of this extended thread QF::add_(this); // make QF aware of this extended thread
@ -166,12 +170,14 @@ void QXThread::start(uint_fast8_t const prio,
/// @param[in] margin number of required free slots in the queue /// @param[in] margin number of required free slots in the queue
/// after posting the event. /// after posting the event.
/// ///
/// @note this function should be called only via the macro QXTHREAD_POST_X(). /// @note
/// This function should be called only via the macro POST() or POST_X().
/// ///
/// @note The zero value of the @p margin parameter is special and denotes /// @note
/// situation when the post() operation is assumed to succeed (event delivery /// The zero value of the @p margin parameter is special and denotes
/// guarantee). An assertion fires, when the event cannot be delivered in /// situation when the QXThread::post_() operation is assumed to succeed
/// this case. /// (event delivery guarantee). An assertion fires, when the event cannot be
/// delivered in this case.
/// ///
#ifndef Q_SPY #ifndef Q_SPY
bool QXThread::post_(QEvt const * const e, uint_fast16_t const margin) bool QXThread::post_(QEvt const * const e, uint_fast16_t const margin)
@ -210,12 +216,12 @@ bool QXThread::post_(QEvt const * const e, uint_fast16_t const margin,
QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO, QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO,
QS::priv_.QS::priv_.locFilter[QS::AO_OBJ], this) QS::priv_.QS::priv_.locFilter[QS::AO_OBJ], this)
QS_TIME_(); // timestamp QS_TIME_(); // timestamp
QS_OBJ_(sender); // the sender object QS_OBJ_(sender); // the sender object
QS_SIG_(e->sig); // the signal of the event QS_SIG_(e->sig); // the signal of the event
QS_OBJ_(this); // this active object QS_OBJ_(this); // this active object
QS_2U8_(e->poolId_, e->refCtr_); // poolID & refCtr of the evt QS_2U8_(e->poolId_, e->refCtr_); // poolID & refCtr of the evt
QS_EQC_(nFree); // number of free entries QS_EQC_(nFree); // number of free entries
QS_EQC_(m_eQueue.m_nMin); // min number of free entries QS_EQC_(m_eQueue.m_nMin); // min number of free entries
QS_END_NOCRIT_() QS_END_NOCRIT_()
@ -318,16 +324,12 @@ void QXThread::postLIFO(QEvt const * const /*e*/) {
/// to wait for the event to arrive. The value of /// to wait for the event to arrive. The value of
/// QXTHREAD_NO_TIMEOUT indicates that no timeout will /// QXTHREAD_NO_TIMEOUT indicates that no timeout will
/// occur and the queue will block indefinitely. /// occur and the queue will block indefinitely.
/// @param[in] tickRate system clock tick rate serviced in this call.
///
/// @returns /// @returns
/// Returns pointer to the event. If the pointer is not NULL, the event /// Returns pointer to the event. If the pointer is not NULL, the event
/// was delivered. Otherwise the event pointer of NULL indicates that the /// was delivered. Otherwise the event pointer of NULL indicates that the
/// queue has timed out. /// queue has timed out.
/// ///
QEvt const *QXThread::queueGet(uint_fast16_t const nTicks, QEvt const *QXThread::queueGet(uint_fast16_t const nTicks) {
uint_fast8_t const tickRate)
{
QEQueueCtr nFree; QEQueueCtr nFree;
QEvt const *e; QEvt const *e;
QF_CRIT_STAT_ QF_CRIT_STAT_
@ -336,13 +338,13 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks,
QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr); QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr);
/// @pre this function must: /// @pre this function must:
/// (1) NOT be called from an ISR; (2) be called from an extended thread; /// - NOT be called from an ISR;
/// (3) the thread must NOT be holding a mutex and /// - be called from an extended thread;
/// (4) the thread must NOT be already blocked on any object. /// - the thread must NOT be holding a scheduler lock;
/// /// - the thread must NOT be already blocked on any object.
Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */ && (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* !locked */ && (QXK_attr_.lockHolder != thr->m_prio) /* not holding a lock */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked && (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked
// is the queue empty? -- block and wait for event(s) // is the queue empty? -- block and wait for event(s)
@ -351,7 +353,7 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks,
// remember the blocking object (the thread's queue) // remember the blocking object (the thread's queue)
thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_eQueue); thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_eQueue);
thr->teArm_(static_cast<enum_t>(QXK_QUEUE_SIG), nTicks, tickRate); thr->teArm_(static_cast<enum_t>(QXK_QUEUE_SIG), nTicks);
QXK_attr_.readySet.remove(thr->m_prio); QXK_attr_.readySet.remove(thr->m_prio);
(void)QXK_sched_(); (void)QXK_sched_();
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
@ -425,7 +427,7 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks,
/// ///
void QXThread::block_(void) const { void QXThread::block_(void) const {
/// @pre the thread holding the lock cannot block! /// @pre the thread holding the lock cannot block!
Q_REQUIRE_ID(600, m_prio != QXK_attr_.lockPrio); Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != m_prio));
QXK_attr_.readySet.remove(m_prio); QXK_attr_.readySet.remove(m_prio);
(void)QXK_sched_(); (void)QXK_sched_();
} }
@ -455,10 +457,7 @@ void QXThread::unblock_(void) const {
/// @note /// @note
/// must be called from within a critical section /// must be called from within a critical section
/// ///
void QXThread::teArm_(enum_t const sig, void QXThread::teArm_(enum_t const sig, uint_fast16_t const nTicks) {
uint_fast16_t const nTicks,
uint_fast8_t const tickRate)
{
/// @pre 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)); Q_REQUIRE_ID(700, m_timeEvt.m_ctr == static_cast<QTimeEvtCtr>(0));
@ -471,11 +470,12 @@ void QXThread::teArm_(enum_t const sig,
// is the time event unlinked? // is the time event unlinked?
// NOTE: For the duration of a single clock tick of the specified tick // NOTE: For the duration of a single clock tick of the specified tick
// rate a time event can be disarmed and yet still linked in the list, // rate a time event can be disarmed and yet still linked in the list,
// because un-linking is performed exclusively in QF_tickX(). // because un-linking is performed exclusively in QF::tickX().
//
if ((m_timeEvt.refCtr_ & static_cast<uint8_t>(0x80)) if ((m_timeEvt.refCtr_ & static_cast<uint8_t>(0x80))
== static_cast<uint8_t>(0)) == static_cast<uint8_t>(0))
{ {
uint_fast8_t tickRate =
static_cast<uint_fast8_t>(m_timeEvt.refCtr_);
m_timeEvt.refCtr_ |= static_cast<uint8_t>(0x80); // mark as linked m_timeEvt.refCtr_ |= static_cast<uint8_t>(0x80); // mark as linked
// The time event is initially inserted into the separate // The time event is initially inserted into the separate
@ -515,35 +515,32 @@ bool QXThread::teDisarm_(void) {
//**************************************************************************** //****************************************************************************
//! delay (timed block) the current extended thread //! delay (timed block) the current extended thread
bool QXThread::delay(uint_fast16_t const nTicks, bool QXThread::delay(uint_fast16_t const nTicks) {
uint_fast8_t const tickRate)
{
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr); QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr);
/// @pre this function must: /// @pre this function must:
/// (1) NOT be called from an ISR; (2) be called from an extended thread; /// - NOT be called from an ISR;
/// (3) the thread must NOT be holding a mutex and /// - be called from an extended thread;
/// (4) the thread must NOT be already blocked on any object. /// - the thread must NOT be holding a scheduler lock and;
/// /// - the thread must NOT be already blocked on any object.
Q_REQUIRE_ID(900, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */ && (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* !locked */ && (QXK_attr_.lockHolder != thr->m_prio) /* not holding a lock */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked && (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked
// remember the blocking object // remember the blocking object
thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_timeEvt); thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_timeEvt);
thr->teArm_(static_cast<enum_t>(QXK_DELAY_SIG), nTicks, tickRate); thr->teArm_(static_cast<enum_t>(QXK_DELAY_SIG), nTicks);
thr->block_(); thr->block_();
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
QF_CRIT_EXIT_NOP(); // BLOCK here QF_CRIT_EXIT_NOP(); // BLOCK here
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
// the blocking object must be the time event // the blocking object must be the time event
Q_ENSURE_ID(990, thr->m_temp.obj == Q_ENSURE_ID(890, thr->m_temp.obj ==
reinterpret_cast<QMState const *>(&thr->m_timeEvt)); reinterpret_cast<QMState const *>(&thr->m_timeEvt));
thr->m_temp.obj = static_cast<QMState const *>(0); // clear thr->m_temp.obj = static_cast<QMState const *>(0); // clear
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();

View File

@ -3,8 +3,8 @@
/// @ingroup qk /// @ingroup qk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.0 /// Last updated for version 5.9.7
/// Last updated on 2017-05-04 /// Last updated on 2017-08-18
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -116,26 +116,19 @@ static void initial_events(void) {
// any active objects need to be scheduled before starting event loop? // any active objects need to be scheduled before starting event loop?
if (QK_sched_() != static_cast<uint_fast8_t>(0)) { if (QK_sched_() != static_cast<uint_fast8_t>(0)) {
QK_activate_(); // process all events produced so far QK_activate_(); // activate AOs to process all events posted so far
} }
} }
//**************************************************************************** //****************************************************************************
// @description /// @description
// QP::QF::run() is typically called from your startup code after you ///
// initialize the QF and start at least one active object with /// QP::QF::run() is typically called from your startup code after you
// QP::QActive::start(). /// initialize the QF and start at least one active object with
// /// QP::QActive::start().
// @returns QP::QF::run() typically does not return in embedded applications. ///
// However, when QP runs on top of an operating system, QP::QF::run() might /// @returns In QK, the QP::QF::run() function does not return.
// return and in this case the return represents the error code (0 for ///
// success). Typically the value returned from QP::QF::run() is subsequently
// passed on as return from main().
//
// @note This function is strongly platform-dependent and is not implemented
// in the QF, but either in the QF port or in the Board Support Package (BSP)
// for the given application. All QF ports must implement QP::QF::run().
//
int_t QF::run(void) { int_t QF::run(void) {
QF_INT_DISABLE(); QF_INT_DISABLE();
initial_events(); // process all events posted during initialization initial_events(); // process all events posted during initialization
@ -144,7 +137,7 @@ int_t QF::run(void) {
// the QK idle loop... // the QK idle loop...
for (;;) { for (;;) {
QK::onIdle(); // invoke the QK on-idle callback QK::onIdle(); // application-specific QK on-idle callback
} }
#ifdef __GNUC__ // GNU compiler? #ifdef __GNUC__ // GNU compiler?
return static_cast<int_t>(0); return static_cast<int_t>(0);
@ -177,16 +170,15 @@ void QActive::start(uint_fast8_t const prio,
/// @pre AO cannot be started from an ISR, the priority must be in range /// @pre AO cannot be started from an ISR, the priority must be in range
/// and the stack storage must not be provided, because the QK kernel does /// and the stack storage must not be provided, because the QK kernel does
/// not need per-AO stacks. /// not need per-AO stacks.
/// Q_REQUIRE_ID(300, (!QK_ISR_CONTEXT_())
Q_REQUIRE_ID(500, (!QK_ISR_CONTEXT_())
&& (static_cast<uint_fast8_t>(0) < prio) && (static_cast<uint_fast8_t>(0) < prio)
&& (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE)) && (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE))
&& (stkSto == static_cast<void *>(0))); && (stkSto == static_cast<void *>(0)));
m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO m_eQueue.init(qSto, qLen); // initialize the built-in queue
m_prio = prio; // set the QF priority of this AO
QF::add_(this); // make QF aware of this AO m_prio = prio; // set the QF priority of this AO
QF::add_(this); // make QF aware of this AO
this->init(ie); // take the top-most initial tran. (virtual) this->init(ie); // take the top-most initial tran. (virtual)
QS_FLUSH(); // flush the trace buffer to the host QS_FLUSH(); // flush the trace buffer to the host
@ -201,20 +193,20 @@ void QActive::start(uint_fast8_t const prio,
} }
//**************************************************************************** //****************************************************************************
// @description /// @description
// The preferred way of calling this function is from within the active /// This function must be called from within the AO that needs to stop.
// object that needs to stop. In other words, an active object should stop /// In other words, an AO should stop itself rather than being stopped by
// itself rather than being stopped by someone else. This policy works /// someone else. This policy works best, because only the AO itself "knows"
// best, because only the active object itself "knows" when it has reached /// when it has reached the appropriate state for the shutdown.
// the appropriate state for the shutdown. ///
// /// @note
// @note /// By the time the AO calls QP::QActive::stop(), it should have unsubscribed
// By the time the AO calls QP::QActive::stop(), it should have unsubscribed /// from all events and no more events should be directly-posted to it.
// from all events and no more events should be directly-posted to it. ///
//
void QActive::stop(void) { void QActive::stop(void) {
//! @pre QActive::stop() must be called from the AO that wants to stop.
Q_REQUIRE_ID(600, (this == QF::active_[QK_attr_.actPrio])); //! @pre QP::QActive::stop() must be called from the AO that wants to stop.
Q_REQUIRE_ID(400, (this == QF::active_[QK_attr_.actPrio]));
QF::remove_(this); // remove this active object from the QF QF::remove_(this); // remove this active object from the QF
@ -227,6 +219,115 @@ void QActive::stop(void) {
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
} }
//****************************************************************************
///
/// @description
/// This function locks the QK scheduler to the specified ceiling.
///
/// @param[in] ceiling priority ceiling to which the QK scheduler
/// needs to be locked
///
/// @returns
/// The previous QK Scheduler lock status, which is to be used to unlock
/// the scheduler by restoring its previous lock status in
/// QP::QK::schedUnlock().
///
/// @note
/// QP::QK::schedLock() must be always followed by the corresponding
/// QP::QK::schedUnlock().
///
/// @sa QK_schedUnlock()
///
/// @usage
/// The following example shows how to lock and unlock the QK scheduler:
/// @include qk_lock.cpp
///
QSchedStatus QK::schedLock(uint_fast8_t const ceiling) {
QSchedStatus stat;
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre The QK scheduler lock:
/// - cannot be called from an ISR;
Q_REQUIRE_ID(600, !QK_ISR_CONTEXT_());
// first store the previous lock prio
if (QK_attr_.lockPrio < ceiling) { // raising the lock prio?
stat = static_cast<QSchedStatus>(QK_attr_.lockPrio << 8);
QK_attr_.lockPrio = ceiling;
QS_BEGIN_NOCRIT_(QS_SCHED_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(stat), /* the previous lock prio */
static_cast<uint8_t>(QK_attr_.lockPrio)); // new lock prio
QS_END_NOCRIT_()
// add the previous lock holder priority
stat |= static_cast<QSchedStatus>(QK_attr_.lockHolder);
QK_attr_.lockHolder = QK_attr_.actPrio;
}
else {
stat = static_cast<QSchedStatus>(0xFF);
}
QF_CRIT_EXIT_();
return stat; // return the status to be saved in a stack variable
}
//****************************************************************************
///
/// @description
/// This function unlocks the QK scheduler to the previous status.
///
/// @param[in] stat previous QK Scheduler lock status returned from
/// QP::QK::schedLock()
/// @note
/// QP::QK::schedUnlock() must always follow the corresponding
/// QP::QK::schedLock().
///
/// @sa QP::QK::schedLock()
///
/// @usage
/// The following example shows how to lock and unlock the QK scheduler:
/// @include qk_lock.cpp
///
void QK::schedUnlock(QSchedStatus const stat) {
// has the scheduler been actually locked by the last QK_schedLock()?
if (stat != static_cast<QSchedStatus>(0xFF)) {
uint_fast8_t lockPrio = QK_attr_.lockPrio; // volatilie into tmp
uint_fast8_t prevPrio = static_cast<uint_fast8_t>(stat >> 8);
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre The scheduler cannot be unlocked:
/// - from the ISR context; and
/// - the current lock priority must be greater than the previous
Q_REQUIRE_ID(700, (!QK_ISR_CONTEXT_())
&& (lockPrio > prevPrio));
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(lockPrio),/* prio before unlocking */
static_cast<uint8_t>(prevPrio));// prio after unlocking
QS_END_NOCRIT_()
// restore the previous lock priority and lock holder
QK_attr_.lockPrio = prevPrio;
QK_attr_.lockHolder =
static_cast<uint_fast8_t>(stat & static_cast<QSchedStatus>(0xFF));
// find the highest-prio thread ready to run
if (QK_sched_() != static_cast<uint_fast8_t>(0)) { // priority found?
QK_activate_(); // activate any unlocked basic threads
}
QF_CRIT_EXIT_();
}
}
} // namespace QP } // namespace QP
//============================================================================ //============================================================================
@ -234,16 +335,16 @@ extern "C" {
//**************************************************************************** //****************************************************************************
/// @description /// @description
/// This function finds out the priority of the highest-priority active object /// The QK scheduler finds out the priority of the highest-priority AO
/// that (1) has events to process, and (2) has priority that is above the /// that (1) has events to process and (2) has priority that is above the
/// current priority, and (3) has priority that is above the mutex ceiling, /// current priority.
/// if mutex is configured in the port.
/// ///
/// @returns the 1-based priority of the the active object, or zero if /// @returns the 1-based priority of the the active object, or zero if
/// no eligible active object is ready to run. /// no eligible active object is ready to run.
/// ///
/// @attention QK_sched_() must be always called with interrupts /// @attention
/// __disabled__ and returns with interrupts __disabled__. /// QK_sched_() must be always called with interrupts **disabled** and
/// returns with interrupts **disabled**.
/// ///
uint_fast8_t QK_sched_(void) { uint_fast8_t QK_sched_(void) {
// find the highest-prio AO with non-empty event queue // find the highest-prio AO with non-empty event queue

View File

@ -1,12 +1,11 @@
/// @file /// @file
/// @brief QP::QMutex::init(), QP::QMutex::lock(), and QP::QMutex::unlock() /// @brief QK mutex implementation (obsolete).
/// definitions.
/// @ingroup qk /// @ingroup qk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Product: QK/C++ /// Product: QK/C++
/// Last updated for version 5.9.0 /// Last updated for version 5.9.7
/// Last updated on 2017-05-09 /// Last updated on 2017-08-18
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -37,138 +36,3 @@
/// mailto:info@state-machine.com /// mailto:info@state-machine.com
///*************************************************************************** ///***************************************************************************
/// @endcond /// @endcond
#define QP_IMPL // this is QF/QK implementation
#include "qf_port.h" // QF port
#include "qf_pkg.h" // QF package-scope internal interface
#include "qassert.h" // QP assertions
#ifdef Q_SPY // QS software tracing enabled?
#include "qs_port.h" // include QS port
#else
#include "qs_dummy.h" // disable the QS software tracing
#endif // Q_SPY
// protection against including this source file in a wrong project
#ifndef qk_h
#error "Source file included in a project NOT based on the QK kernel"
#endif // qk_h
namespace QP {
Q_DEFINE_THIS_MODULE("qk_mutex")
enum {
MUTEX_UNUSED = 0xFF
};
//****************************************************************************
/// @description
/// Initializes QK priority-ceiling mutex to the specified ceiling priority.
///
/// @param[in] prio ceiling priority of the mutex
///
/// @note
/// A mutex must be initialized before it can be locked or unlocked.
///
/// @sa QP::QMutex::lock(), QP::QMutex::unlock()
///
/// @usage
/// The following example shows how to initialize, lock and unlock QK mutex:
/// @include qk_mux.cpp
///
void QMutex::init(uint_fast8_t const prio) {
m_lockPrio = prio;
m_prevPrio = static_cast<uint_fast8_t>(MUTEX_UNUSED);
}
//****************************************************************************
/// @description
/// This function locks the QK mutex.
///
/// @note
/// A mutex must be initialized before it can be locked or unlocked.
///
/// @note
/// QP::QMutex::lock() must be always followed by the corresponding
/// QP::QMutex::unlock().
///
/// @sa QP::QMutex::init(), QP::QMutex::unlock()
///
/// @usage
/// The following example shows how to initialize, lock and unlock QK mutex:
/// @include qk_mux.cpp
///
void QMutex::lock(void) {
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre scheduler cannot be locked from the ISR context
/// and the mutex must be unused
Q_REQUIRE_ID(700, (!QK_ISR_CONTEXT_())
&& (m_prevPrio == static_cast<uint_fast8_t>(MUTEX_UNUSED)));
m_prevPrio = QK_attr_.lockPrio; // save the previous prio
if (QK_attr_.lockPrio < m_lockPrio) { // raising the lock prio?
QK_attr_.lockPrio = m_lockPrio;
}
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), /* previous lock prio */
static_cast<uint8_t>(QK_attr_.lockPrio)); // the new lock prio
QS_END_NOCRIT_()
QF_CRIT_EXIT_();
}
//****************************************************************************
/// @description
/// This function unlocks the QK mutex.
///
/// @note
/// A mutex must be initialized before it can be locked or unlocked.
///
/// @note
/// QP::QMutex::unlock() must always follow the corresponding
/// QP::QMutex::lock().
///
/// @sa QP::QMutex::init(), QP::QMutex::lock()
///
/// @usage
/// The following example shows how to initialize, lock and unlock QK mutex:
/// @include qk_mux.cpp
///
void QMutex::unlock(void) {
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre scheduler cannot be unlocked from the ISR context
/// and the mutex must not be unused
Q_REQUIRE_ID(800, (!QK_ISR_CONTEXT_())
&& (m_prevPrio != static_cast<uint_fast8_t>(MUTEX_UNUSED)));
uint_fast8_t p = m_prevPrio;
m_prevPrio = static_cast<uint_fast8_t>(MUTEX_UNUSED);
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(QK_attr_.lockPrio), /* prev lock prio */
(QK_attr_.lockPrio > p) /* the new lock prio */
? static_cast<uint8_t>(p)
: static_cast<uint8_t>(QK_attr_.lockPrio));
QS_END_NOCRIT_()
if (QK_attr_.lockPrio > p) {
QK_attr_.lockPrio = p; // restore the previous lock prio
if (QK_sched_() != static_cast<uint_fast8_t>(0)) { // priority found?
QK_activate_(); // activate any unlocked AOs
}
}
QF_CRIT_EXIT_();
}
} // namespace QP

View File

@ -4,8 +4,8 @@
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-07-27 /// Last updated on 2017-08-20
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -67,19 +67,20 @@ public:
QXKIdleThread() : QActive(Q_STATE_CAST(0)) QXKIdleThread() : QActive(Q_STATE_CAST(0))
{} {}
}; };
static QXKIdleThread l_idleThread;
//**************************************************************************** //****************************************************************************
/// @description /// @description
/// Initializes QF and must be called exactly once before any other QF /// Initializes QF and must be called exactly once before any other QF
/// function. Typically, QF_init() is called from main() even before /// function. Typically, QF::init() is called from main() even before
/// initializing the Board Support Package (BSP). /// initializing the Board Support Package (BSP).
/// ///
/// @note QF::init() clears the internal QF variables, so that the framework /// @note QF::init() clears the internal QF variables, so that the framework
/// can start correctly even if the startup code fails to clear the /// can start correctly even if the startup code fails to clear the
/// uninitialized data (as is required by the C+ Standard). /// uninitialized data (as is required by the C++ Standard).
/// ///
void QF::init(void) { void QF::init(void) {
static QXKIdleThread s_idleThread;
QF_maxPool_ = static_cast<uint_fast8_t>(0); QF_maxPool_ = static_cast<uint_fast8_t>(0);
QF_subscrList_ = static_cast<QSubscrList *>(0); QF_subscrList_ = static_cast<QSubscrList *>(0);
QF_maxPubSignal_ = static_cast<enum_t>(0); QF_maxPubSignal_ = static_cast<enum_t>(0);
@ -87,13 +88,13 @@ void QF::init(void) {
bzero(&timeEvtHead_[0], static_cast<uint_fast16_t>(sizeof(timeEvtHead_))); bzero(&timeEvtHead_[0], static_cast<uint_fast16_t>(sizeof(timeEvtHead_)));
bzero(&active_[0], static_cast<uint_fast16_t>(sizeof(active_))); bzero(&active_[0], static_cast<uint_fast16_t>(sizeof(active_)));
bzero(&QXK_attr_, static_cast<uint_fast16_t>(sizeof(QXK_attr_))); bzero(&QXK_attr_, static_cast<uint_fast16_t>(sizeof(QXK_attr_)));
bzero(&l_idleThread, static_cast<uint_fast16_t>(sizeof(l_idleThread))); bzero(&s_idleThread, static_cast<uint_fast16_t>(sizeof(s_idleThread)));
// setup the QXK scheduler as initially locked and not running // setup the QXK scheduler as initially locked and not running
QXK_attr_.lockPrio = static_cast<uint_fast8_t>(QF_MAX_ACTIVE + 1); QXK_attr_.lockPrio = static_cast<uint_fast8_t>(QF_MAX_ACTIVE + 1);
// setup the QXK idle loop... // setup the QXK idle loop...
active_[0] = &l_idleThread; // register the idle thread with QF active_[0] = &s_idleThread; // register the idle thread with QF
QXK_attr_.actPrio = static_cast<uint_fast8_t>(0); // set idle thread prio QXK_attr_.actPrio = static_cast<uint_fast8_t>(0); // set idle thread prio
#ifdef QXK_INIT #ifdef QXK_INIT
@ -131,9 +132,8 @@ static void initial_events(void) {
//**************************************************************************** //****************************************************************************
/// @description /// @description
/// QP::QF::run() is typically called from your startup code after you /// QF::run() is typically called from main() after you initialize
/// initialize the QF and start at least one basic- or extended-thread /// the QF and start at least one active object with QActive::start().
/// (with QP::QActive::start() or QP::QXThread::start(), respectively).
/// ///
/// @returns In QXK, the QF::run() function does not return. /// @returns In QXK, the QF::run() function does not return.
/// ///
@ -174,30 +174,28 @@ void QActive::start(uint_fast8_t const prio,
void * const stkSto, uint_fast16_t const stkSize, void * const stkSto, uint_fast16_t const stkSize,
QEvt const * const ie) QEvt const * const ie)
{ {
/// @pre AO cannot be started from an ISR, the priority must be in range /// @pre AO cannot be started:
/// and the stack storage must not be provided, because the QK kernel /// - from an ISR;
/// does not need per-AO stacks. /// - the priority must be in range;
/// /// - the stack storage must NOT be provided (because the QXK kernel does
Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) /// not need per-AO stacks).
&& (static_cast<uint_fast8_t>(0) < prio) Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_())
&& (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE)) && (static_cast<uint_fast8_t>(0) < prio)
&& (stkSto == static_cast<void *>(0)) && (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE))
&& (stkSize == static_cast<uint_fast16_t>(0))); && (stkSto == static_cast<void *>(0))
&& (stkSize == static_cast<uint_fast16_t>(0)));
m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO
m_osObject = static_cast<void *>(0); // no private stack for AO m_osObject = static_cast<void *>(0); // no private stack for AO
m_prio = prio; // set the QF priority of this AO m_prio = prio; // set the QF priority of this AO
m_startPrio = prio; // set the start QF priority of this AO
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
QF::add_(this); // make QF aware of this AO QF::add_(this); // make QF aware of this AO
QF_CRIT_EXIT_();
this->init(ie); // take the top-most initial tran. (virtual) this->init(ie); // take the top-most initial tran. (virtual)
QS_FLUSH(); // flush the trace buffer to the host QS_FLUSH(); // flush the trace buffer to the host
// see if this AO needs to be scheduled in case QXK is running // see if this AO needs to be scheduled in case QXK is running
QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
if (QXK_sched_() != static_cast<uint_fast8_t>(0)) { // activation needed? if (QXK_sched_() != static_cast<uint_fast8_t>(0)) { // activation needed?
QXK_activate_(); QXK_activate_();
@ -217,9 +215,8 @@ void QActive::start(uint_fast8_t const prio,
// from all events and no more events should be directly-posted to it. // from all events and no more events should be directly-posted to it.
// //
void QActive::stop(void) { void QActive::stop(void) {
/// @pre QActive_stop() must be called from the AO that wants to stop. /// @pre QActive::stop() must be called from the AO that wants to stop.
Q_REQUIRE_ID(600, (!QXK_ISR_CONTEXT_()) /* don't stop AO's from an ISR! */ Q_REQUIRE_ID(300, (this == QF::active_[QXK_attr_.actPrio]));
&& (this == QXK_attr_.curr));
QF::remove_(this); // remove this active object from the QF QF::remove_(this); // remove this active object from the QF
@ -232,6 +229,115 @@ void QActive::stop(void) {
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
} }
//****************************************************************************
/// @description
/// This function locks the QXK scheduler to the specified ceiling.
///
/// @param[in] ceiling priority ceiling to which the QXK scheduler
/// needs to be locked
///
/// @returns
/// The previous QXK Scheduler lock status, which is to be used to unlock
/// the scheduler by restoring its previous lock status in QXK::schedUnlock().
///
/// @note
/// QXK::schedLock() must be always followed by the corresponding
/// QXK::schedUnlock().
///
/// @sa QXK::schedUnlock()
///
/// @usage
/// The following example shows how to lock and unlock the QXK scheduler:
/// @include qxk_lock.cpp
///
QSchedStatus QXK::schedLock(uint_fast8_t const ceiling) {
QSchedStatus stat;
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre The QXK scheduler lock:
/// - cannot be called from an ISR;
Q_REQUIRE_ID(400, !QXK_ISR_CONTEXT_());
// first store the previous lock prio
if (QXK_attr_.lockPrio < ceiling) { // raising the lock prio?
stat = static_cast<QSchedStatus>(QXK_attr_.lockPrio << 8);
QXK_attr_.lockPrio = ceiling;
QS_BEGIN_NOCRIT_(QS_SCHED_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(stat), /* the previous lock prio */
static_cast<uint8_t>(QXK_attr_.lockPrio)); // new lock prio
QS_END_NOCRIT_()
// add the previous lock holder priority
stat |= static_cast<QSchedStatus>(QXK_attr_.lockHolder);
QXK_attr_.lockHolder =
(QXK_attr_.curr != static_cast<QActive *>(0))
? QXK_attr_.curr->m_prio
: static_cast<uint_fast8_t>(0);
}
else {
stat = static_cast<QSchedStatus>(0xFF);
}
QF_CRIT_EXIT_();
return stat; // return the status to be saved in a stack variable
}
//****************************************************************************
///
/// @description
/// This function unlocks the QXK scheduler to the previous status.
///
/// @param[in] stat previous QXK Scheduler lock status returned from
/// QXK::schedLock()
/// @note
/// QXK::schedUnlock() must always follow the corresponding
/// QXK::schedLock().
///
/// @sa QXK::schedLock()
///
/// @usage
/// The following example shows how to lock and unlock the QXK scheduler:
/// @include qxk_lock.cpp
///
void QXK::schedUnlock(QSchedStatus const stat) {
// has the scheduler been actually locked by the last QXK_schedLock()?
if (stat != static_cast<QSchedStatus>(0xFF)) {
uint_fast8_t lockPrio = QXK_attr_.lockPrio; // volatilie into tmp
uint_fast8_t prevPrio = static_cast<uint_fast8_t>(stat >> 8);
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
/// @pre The scheduler cannot be unlocked:
/// - from the ISR context; and
/// - the current lock priority must be greater than the previous
Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_())
&& (lockPrio > prevPrio));
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(lockPrio),/* prio before unlocking */
static_cast<uint8_t>(prevPrio));// prio after unlocking
QS_END_NOCRIT_()
// restore the previous lock priority and lock holder
QXK_attr_.lockPrio = prevPrio;
QXK_attr_.lockHolder =
static_cast<uint_fast8_t>(stat & static_cast<QSchedStatus>(0xFF));
// 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
}
QF_CRIT_EXIT_();
}
}
} // namespace QP } // namespace QP
@ -261,7 +367,7 @@ uint_fast8_t QXK_sched_(void) {
QP::QActive *next = QP::QF::active_[p]; QP::QActive *next = QP::QF::active_[p];
// the thread found must be registered in QF // the thread found must be registered in QF
//Q_ASSERT_ID(610, next != static_cast<QP::QActive *>(0)); Q_ASSERT_ID(610, next != static_cast<QP::QActive *>(0));
// is the current thread a basic-thread? // is the current thread a basic-thread?
if (QXK_attr_.curr == static_cast<QP::QActive *>(0)) { if (QXK_attr_.curr == static_cast<QP::QActive *>(0)) {
@ -296,6 +402,7 @@ uint_fast8_t QXK_sched_(void) {
// is the new prio different from the current prio? // is the new prio different from the current prio?
if (p != QXK_attr_.curr->m_prio) { if (p != QXK_attr_.curr->m_prio) {
QS_BEGIN_NOCRIT_(QP::QS_SCHED_NEXT, QS_BEGIN_NOCRIT_(QP::QS_SCHED_NEXT,
QP::QS::priv_.locFilter[QP::QS::AO_OBJ], QP::QS::priv_.locFilter[QP::QS::AO_OBJ],
QXK_attr_.next) QXK_attr_.next)
@ -326,8 +433,8 @@ uint_fast8_t QXK_sched_(void) {
/// returns with interrupts **disabled**. /// returns with interrupts **disabled**.
/// ///
void QXK_activate_(void) { void QXK_activate_(void) {
uint_fast8_t p = QXK_attr_.next->m_prio;
uint_fast8_t pin = QXK_attr_.actPrio; // save the initial active prio uint_fast8_t pin = QXK_attr_.actPrio; // save the initial active prio
uint_fast8_t p = QXK_attr_.next->m_prio;
QP::QActive *a; QP::QActive *a;
// QS tracing or thread-local storage? // QS tracing or thread-local storage?
@ -377,12 +484,12 @@ void QXK_activate_(void) {
p = QXK_attr_.readySet.findMax(); p = QXK_attr_.readySet.findMax();
if (p <= QXK_attr_.lockPrio) { // is it below the lock prio? if (p <= QXK_attr_.lockPrio) { // is it below the lock prio?
p = QXK_attr_.lockHolder; // prio of the thread holding the lock p = QXK_attr_.lockHolder; // prio of the thread holding lock
} }
a = QP::QF::active_[p]; a = QP::QF::active_[p];
// the AO must be registered in QF // the AO must be registered in QF
//Q_ASSERT_ID(710, a != static_cast<QP::QActive *>(0)); Q_ASSERT_ID(710, a != static_cast<QP::QActive *>(0));
// is the next an AO-thread? // is the next an AO-thread?
if (a->m_osObject == static_cast<void *>(0)) { if (a->m_osObject == static_cast<void *>(0)) {
@ -400,8 +507,8 @@ void QXK_activate_(void) {
QP::QS::priv_.locFilter[QP::QS::AO_OBJ], QP::QS::priv_.locFilter[QP::QS::AO_OBJ],
QXK_attr_.next) QXK_attr_.next)
QS_TIME_(); // timestamp QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(p), // prio of the next thread QS_2U8_(static_cast<uint8_t>(p), /* prio of the next thr */
static_cast<uint8_t>( // prio of the curent thread static_cast<uint8_t>( /* prio of the curent thr */
QXK_attr_.actPrio)); QXK_attr_.actPrio));
QS_END_NOCRIT_() QS_END_NOCRIT_()
@ -440,6 +547,11 @@ QP::QActive *QXK_current(void) {
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
/// @pre the QXK kernel must be running
Q_REQUIRE_ID(800,
QXK_attr_.lockPrio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE));
curr = QXK_attr_.curr; curr = QXK_attr_.curr;
if (curr == static_cast<QP::QActive *>(0)) { // basic thread? if (curr == static_cast<QP::QActive *>(0)) { // basic thread?
curr = QP::QF::active_[QXK_attr_.actPrio]; curr = QP::QF::active_[QXK_attr_.actPrio];
@ -447,7 +559,7 @@ QP::QActive *QXK_current(void) {
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
//! @post the current thread must be valid //! @post the current thread must be valid
Q_ENSURE_ID(900, curr != static_cast<QP::QActive *>(0)); Q_ENSURE_ID(890, curr != static_cast<QP::QActive *>(0));
return curr; return curr;
} }

View File

@ -1,12 +1,11 @@
/// @file /// @file
/// @brief QP::QXMutex::init(), QP::QXMutex::lock(), and QP::QXMutex::unlock() /// @brief Priority-ceiling blocking mutex QP::QXMutex class definition
/// definitions.
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Product: QK/C++ /// Product: QK/C++
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-07-27 /// Last updated on 2017-08-19
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -57,147 +56,331 @@ namespace QP {
Q_DEFINE_THIS_MODULE("qxk_mutex") Q_DEFINE_THIS_MODULE("qxk_mutex")
enum { //****************************************************************************/
MUTEX_UNUSED = 0xFF
};
//****************************************************************************
/// @description /// @description
/// Initializes QXK priority-ceiling mutex to the specified ceiling priority. /// Initialize the QXK priority ceiling mutex.
/// ///
/// @param[in] prio ceiling priority of the mutex /// @param[in] ceiling ceiling priotity of the mutex
/// ///
/// @note /// @note
/// A mutex must be initialized before it can be locked or unlocked. /// The ceiling priority must be unused by any thread. The ceiling
/// /// priority must be higher than priority of any thread that uses the
/// @sa QP::QXMutex::lock(), QP::QXMutex::unlock() /// protected resource.
/// ///
/// @usage /// @usage
/// The following example shows how to initialize, lock and unlock QXK mutex:
/// @include qxk_mux.cpp /// @include qxk_mux.cpp
/// ///
void QXMutex::init(uint_fast8_t const prio) { void QXMutex::init(uint_fast8_t ceiling) {
m_lockPrio = prio;
m_prevPrio = static_cast<uint_fast8_t>(MUTEX_UNUSED);
}
//****************************************************************************
/// @description
/// This function locks the QXK mutex.
///
/// @note
/// A mutex must be initialized before it can be locked or unlocked.
///
/// @note
/// QP::QXMutex::lock() must be always followed by the corresponding
/// QP::QXMutex::unlock().
///
/// @attention
/// A thread holding a mutex __cannot block__.
///
/// @sa QP::QXMutex::init(), QP::QXMutex::unlock()
///
/// @usage
/// The following example shows how to initialize, lock and unlock QXK mutex:
/// @include qxk_mux.cpp
///
void QXMutex::lock(void) {
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
/// @pre the celiling priority of the mutex must:
/// - not be zero;
/// - cannot exceed the maximum #QF_MAX_ACTIVE;
/// - the ceiling priority of the mutex must not be already in use;
/// (QF requires priority to be **unique**).
Q_REQUIRE_ID(100, (static_cast<uint_fast8_t>(0) < ceiling)
&& (ceiling <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE))
&& (QF::active_[ceiling] == static_cast<QActive *>(0)));
/// @pre The mutex cannot be locked from the ISR context m_ceiling = ceiling;
/// and the mutex must be unused m_lockNest = static_cast<uint_fast8_t>(0);
Q_REQUIRE_ID(700, (!QXK_ISR_CONTEXT_()) QF::bzero(&m_waitSet, static_cast<uint_fast16_t>(sizeof(m_waitSet)));
&& (m_prevPrio == static_cast<uint_fast8_t>(MUTEX_UNUSED)));
m_prevPrio = QXK_attr_.lockPrio; // save previous lock prio // reserve the ceiling priority level for this mutex
m_prevHolder = QXK_attr_.lockHolder; // save previous lock holder QF::active_[ceiling] = reinterpret_cast<QActive *>(this);
if (QXK_attr_.lockPrio < m_lockPrio) { // raising the lock prio?
QXK_attr_.lockPrio = m_lockPrio;
}
QXK_attr_.lockHolder =
(QXK_attr_.curr != static_cast<QActive *>(0))
? QXK_attr_.curr->m_prio
: static_cast<uint_fast8_t>(0);
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), /* previous lock prio */
static_cast<uint8_t>(QXK_attr_.lockPrio)); // new lock prio
QS_END_NOCRIT_()
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
} }
//**************************************************************************** //****************************************************************************
///
/// @description /// @description
/// This function unlocks the QXK mutex. /// Lock the QXK priority ceiling mutex QP::QXMutex.
///
/// @param[in] nTicks number of clock ticks (at the associated rate)
/// to wait for the semaphore. The value of
/// #QXTHREAD_NO_TIMEOUT indicates that no timeout will
/// occur and the semaphore will wait indefinitely.
/// @returns
/// 'true' if the mutex has been acquired and 'false' if a timeout occured.
/// ///
/// @note /// @note
/// A mutex must be initialized before it can be locked or unlocked. /// The mutex locks are allowed to nest, meaning that the same extended thread
/// /// can lock the same mutex multiple times (<= 225). However, each call to
/// @note /// QXMutex::lock() must be ballanced by the matching call to
/// QP::QXMutex::unlock() must always follow the corresponding /// QXMutex::unlock().
/// QP::QXMutex::lock(). ///
/// /// @usage
/// @sa QP::QXMutex::init(), QP::QXMutex::lock() /// @include qxk_mux.cpp
///
bool QXMutex::lock(uint_fast16_t const nTicks) {
QXThread *thr;
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
thr = static_cast<QXThread *>(QXK_attr_.curr);
/// @pre this function must:
/// - NOT be called from an ISR;
/// - be called from an extended thread;
/// - the thread priority must be below the ceiling of the mutex;
/// - the thread must NOT be holding a scheduler lock;
/// - the thread must NOT be already blocked on any object.
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
&& (thr != static_cast<QXThread *>(0)) /* thr must be extended */
&& (thr->m_startPrio < m_ceiling) /* prio below the ceiling */
&& (QXK_attr_.lockHolder != thr->m_prio) /* not holding a lock */
&& (thr->m_temp.obj == static_cast<QMState *>(0))); // not blocked
// is the mutex available?
if (m_lockNest == static_cast<uint_fast8_t>(0)) {
m_lockNest = static_cast<uint_fast8_t>(1);
// the priority slot must be set to this mutex */
Q_ASSERT_ID(210,
QF::active_[m_ceiling] == reinterpret_cast<QActive *>(this));
// switch the priority of this thread to the mutex ceiling
thr->m_prio = m_ceiling;
QF::active_[m_ceiling] = thr;
QXK_attr_.readySet.remove(thr->m_startPrio);
QXK_attr_.readySet.insert(thr->m_prio);
QS_BEGIN_NOCRIT_(QS_MUTEX_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(thr->m_startPrio), /* start prio */
static_cast<uint8_t>(thr->m_prio)); // current ceiling
QS_END_NOCRIT_()
}
// is the mutex locked by this thread already (nested locking)?
else if (QF::active_[m_ceiling] == thr) {
// the nesting level must not exceed 0xFF
Q_ASSERT_ID(220, m_lockNest < static_cast<uint_fast8_t>(0xFF));
++m_lockNest;
}
else { // the mutex is alredy locked by a different thread
// the prio slot must be claimed by the thread holding the mutex
Q_ASSERT_ID(230, QF::active_[m_ceiling] != static_cast<QActive *>(0));
// remove this thr prio from the ready set (block)
// and insert to the waiting set on this mutex
QXK_attr_.readySet.remove(thr->m_prio);
m_waitSet.insert(thr->m_prio);
// store the blocking object (this mutex)
thr->m_temp.obj = reinterpret_cast<QMState *>(this);
thr->teArm_(static_cast<enum_t>(QXK_SEMA_SIG), nTicks);
// schedule the next thread if multitasking started
(void)QXK_sched_();
QF_CRIT_EXIT_();
QF_CRIT_EXIT_NOP(); // BLOCK here
QF_CRIT_ENTRY_();
// the blocking object must be this mutex
Q_ASSERT_ID(240, thr->m_temp.obj == reinterpret_cast<QMState *>(this));
thr->m_temp.obj = static_cast<QMState *>(0); // clear
}
QF_CRIT_EXIT_();
// signal of non-zero means that the time event has not expired
return thr->m_timeEvt.sig != static_cast<QSignal>(0);
}
//****************************************************************************
///
/// @description
/// Try to lock the QXK priority ceiling mutex QP::QXMutex.
///
/// @returns
/// 'true' if the mutex was successfully locked and 'false' if the mutex was
/// unavailable and was NOT locked.
///
/// @note
/// This function **can** be called from both basic threads (active objects)
/// and extended threads.
///
/// @note
/// The mutex locks are allowed to nest, meaning that the same extended thread
/// can lock the same mutex multiple times (<= 225). However, each successful
/// call to QXMutex_tryLock() must be ballanced by the matching call to
/// QXMutex::unlock().
///
bool QXMutex::tryLock(void) {
QActive *curr;
QF_CRIT_STAT_
QF_CRIT_ENTRY_();
curr = QXK_attr_.curr;
if (curr == static_cast<QActive *>(0)) { // called from a basic thread?
curr = QF::active_[QXK_attr_.actPrio];
}
/// @pre this function must:
/// - NOT be called from an ISR;
/// - the QXK kernel must be running;
/// - the calling thread must be valid;
/// - the thread priority must be below the ceiling of the mutex;
/// - the thread must NOT be holding a scheduler lock;
Q_REQUIRE_ID(300, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
&& (QXK_attr_.lockPrio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE))
&& (curr != static_cast<QActive *>(0)) /* curr thread must be valid */
&& (curr->m_startPrio < m_ceiling) /* prio below the ceiling */
&& (curr->m_prio != QXK_attr_.lockHolder)); // not holding a lock
// is the mutex available?
if (m_lockNest == static_cast<uint_fast8_t>(0)) {
m_lockNest = static_cast<uint_fast8_t>(1);
// the priority slot must be set to this mutex
Q_ASSERT_ID(310,
QF::active_[m_ceiling] == reinterpret_cast<QActive *>(this));
// switch the priority of this thread to the mutex ceiling
curr->m_prio = m_ceiling;
QF::active_[m_ceiling] = curr;
QXK_attr_.readySet.remove(curr->m_startPrio);
QXK_attr_.readySet.insert(curr->m_prio);
QS_BEGIN_NOCRIT_(QS_MUTEX_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(curr->m_startPrio), /* start prio */
static_cast<uint8_t>(curr->m_prio)); // current ceiling
QS_END_NOCRIT_()
}
// is the mutex locked by this thread already (nested locking)?
else if (QF::active_[m_ceiling] == curr) {
// the nesting level must not exceed 0xFF
Q_ASSERT_ID(320, m_lockNest < static_cast<uint_fast8_t>(0xFF));
++m_lockNest;
}
else { // the mutex is alredy locked by a different thread
// the prio slot must be claimed by the thread holding the mutex
Q_ASSERT_ID(330, QF::active_[m_ceiling] != static_cast<QActive *>(0));
curr = static_cast<QActive *>(0); // means that mutex is NOT available
}
QF_CRIT_EXIT_();
return curr != static_cast<QActive *>(0);
}
//****************************************************************************
/// @description
/// Unlock the QXK priority ceiling mutex.
///
/// @note
/// This function **can** be called from both basic threads (active objects)
/// and extended threads.
///
/// @note
/// The mutex locks are allowed to nest, meaning that the same extended thread
/// can lock the same mutex multiple times (<= 225). However, each call to
/// QXMutex::lock() or a _successfull_ call to QXMutex_tryLock() must be
/// ballanced by the matching call to QXMutex::unlock().
/// ///
/// @usage /// @usage
/// The following example shows how to initialize, lock and unlock QXK mutex:
/// @include qxk_mux.cpp /// @include qxk_mux.cpp
/// ///
void QXMutex::unlock(void) { void QXMutex::unlock(void) {
QActive *curr;
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
curr = static_cast<QActive *>(QXK_attr_.curr);
if (curr == static_cast<QActive *>(0)) { // called from a basic thread?
curr = QF::active_[QXK_attr_.actPrio];
}
/// @pre The mutex cannot be unlocked from the ISR context /// @pre this function must:
/// and the mutex must NOT be unused /// - NOT be called from an ISR;
Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_()) /// - the calling thread must be valid;
&& (m_prevPrio != static_cast<uint_fast8_t>(MUTEX_UNUSED))); /// - the mutex must be held by this thread;
/// - the holding thread must have priority equal to the mutex ceiling;
/// - the mutex must be already locked at least once.
Q_REQUIRE_ID(400, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
&& (curr != static_cast<QActive *>(0)) /* curr must be valid */
&& (curr == QF::active_[m_ceiling]) /* held by this thr */
&& (curr->m_prio == m_ceiling) /* thr prio at the ceiling */
&& (m_lockNest > static_cast<uint_fast8_t>(0)));//locked at least once
uint_fast8_t p = m_prevPrio; // the previouis lock prio // is this the last nesting level?
m_prevPrio = static_cast<uint_fast8_t>(MUTEX_UNUSED); if (m_lockNest == static_cast<uint_fast8_t>(1)) {
QXK_attr_.lockHolder = m_prevHolder; // restore previous lock holder
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, // restore the holding thread's priority to the original
static_cast<void *>(0), static_cast<void *>(0)) curr->m_prio = curr->m_startPrio;
QS_TIME_(); // timestamp
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) { // remove the boosted priority and insert the original priority
QXK_attr_.readySet.remove(m_ceiling);
QXK_attr_.readySet.insert(curr->m_startPrio);
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, QS_BEGIN_NOCRIT_(QS_MUTEX_UNLOCK,
static_cast<void *>(0), static_cast<void *>(0)) static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(QXK_attr_.lockPrio), /* prev lock */ QS_2U8_(static_cast<uint8_t>(curr->m_startPrio), /* start prio */
static_cast<uint8_t>(p)); // new lock prio static_cast<uint8_t>(m_ceiling)); // the mutex ceiling
QS_END_NOCRIT_() QS_END_NOCRIT_()
QXK_attr_.lockPrio = p; // restore the previous lock prio // are any other threads waiting for this mutex?
// find the highest-prio thread ready to run if (m_waitSet.notEmpty()) {
if (QXK_sched_() != static_cast<uint_fast8_t>(0)) { // priority found?
QXK_activate_(); // activate any unlocked basic threads // find the highest-priority waiting thread
uint_fast8_t p = m_waitSet.findMax();
QXThread *thr = static_cast<QXThread *>(QF::active_[p]);
// the waiting thread must:
// (1) have priority below the ceiling
// (2) be extended
// (3) not be redy to run
// (4) have still the start priority
// (5) be blocked on this mutex
Q_ASSERT_ID(410, (p < m_ceiling)
&& (thr != static_cast<QXThread *>(0)) /* extended thread */
&& (!QXK_attr_.readySet.hasElement(p))
&& (thr->m_prio == thr->m_startPrio)
&& (thr->m_temp.obj == reinterpret_cast<QMState *>(this)));
// disarm the internal time event
(void)thr->teDisarm_();
// this thread is no longer waiting for the mutex
m_waitSet.remove(p);
// switch the priority of this thread to the mutex ceiling
thr->m_prio = m_ceiling;
QF::active_[m_ceiling] = thr;
// make the thread ready to run (at the ceiling prio)
QXK_attr_.readySet.insert(thr->m_prio);
QS_BEGIN_NOCRIT_(QS_MUTEX_LOCK,
static_cast<void *>(0), static_cast<void *>(0))
QS_TIME_(); // timestamp
QS_2U8_(static_cast<uint8_t>(thr->m_startPrio),/*start prio*/
static_cast<uint8_t>(thr->m_prio)); // ceiling prio
QS_END_NOCRIT_()
}
else { // no threads are waiting for this mutex
m_lockNest = static_cast<uint_fast8_t>(0);
// put the mutex at the priority ceiling slot
QF::active_[m_ceiling] = reinterpret_cast<QActive *>(this);
}
// schedule the next thread if multitasking started
if (QXK_sched_() != static_cast<uint_fast8_t>(0)) {
QXK_activate_(); // activate a basic thread
} }
} }
else { else { // releasing the mutex
QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, --m_lockNest; // release one level
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_(); QF_CRIT_EXIT_();
} }

View File

@ -3,8 +3,8 @@
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
////************************************************************************** ////**************************************************************************
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-07-27 /// Last updated on 2017-08-20
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -98,17 +98,13 @@ void QXSemaphore::init(uint_fast16_t const count,
/// to wait for the semaphore. The value of /// to wait for the semaphore. The value of
/// QXTHREAD_NO_TIMEOUT indicates that no timeout will /// QXTHREAD_NO_TIMEOUT indicates that no timeout will
/// occur and the semaphore will wait indefinitely. /// occur and the semaphore will wait indefinitely.
/// @param[in] tickRate system clock tick rate serviced in this call.
///
/// @returns /// @returns
/// true if the semaphore has been signaled, and false if the timeout occured. /// true if the semaphore has been signaled, and false if the timeout occured.
/// ///
/// @note /// @note
/// Multiple extended threads can wait for a given semahpre. /// Multiple extended threads can wait for a given semahpre.
/// ///
bool QXSemaphore::wait(uint_fast16_t const nTicks, bool QXSemaphore::wait(uint_fast16_t const nTicks) {
uint_fast8_t const tickRate)
{
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
@ -122,7 +118,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */ && (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* no lock */ && (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* no lock */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked && (thr->m_temp.obj == static_cast<QMState *>(0))); // !blocked
if (m_count > static_cast<uint_fast16_t>(0)) { if (m_count > static_cast<uint_fast16_t>(0)) {
--m_count; --m_count;
@ -131,7 +127,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
else { else {
// remember the blocking object // remember the blocking object
thr->m_temp.obj = reinterpret_cast<QMState const *>(this); thr->m_temp.obj = reinterpret_cast<QMState const *>(this);
thr->teArm_(static_cast<enum_t>(QXK_SEMA_SIG), nTicks, tickRate); thr->teArm_(static_cast<enum_t>(QXK_SEMA_SIG), nTicks);
m_waitSet.insert(thr->m_prio); m_waitSet.insert(thr->m_prio);
QXK_attr_.readySet.remove(thr->m_prio); QXK_attr_.readySet.remove(thr->m_prio);
(void)QXK_sched_(); (void)QXK_sched_();
@ -142,7 +138,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
// the blocking object must be this semaphore // the blocking object must be this semaphore
Q_ASSERT_ID(210, thr->m_temp.obj Q_ASSERT_ID(210, thr->m_temp.obj
== reinterpret_cast<QMState const *>(this)); == reinterpret_cast<QMState const *>(this));
thr->m_temp.obj = static_cast<QMState const *>(0); // clear thr->m_temp.obj = static_cast<QMState *>(0); // clear
} }
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
@ -150,6 +146,40 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks,
return (thr->m_timeEvt.sig != static_cast<QSignal>(0)); return (thr->m_timeEvt.sig != static_cast<QSignal>(0));
} }
//****************************************************************************
///
/// @description
/// This operation checks if the semaphore counter is greater than 0,
/// in which case the counter is decremented.
///
/// @returns
/// 'true' if the semaphore has count available and 'false' NOT available.
///
/// @note
/// This function can be called from any context, including ISRs and basic
/// threds (active objects).
///
bool QXSemaphore::tryWait(void) {
bool isAvailable;
QF_CRIT_STAT_
/// @pre the semaphore must be initialized
Q_REQUIRE_ID(300, (m_max_count > static_cast<uint_fast16_t>(0)));
QF_CRIT_ENTRY_();
// is the semaphore available?
if (m_count > static_cast<uint_fast16_t>(0)) {
--m_count;
isAvailable = true;
}
else { // the semaphore is NOT available (would block)
isAvailable = false;
}
QF_CRIT_EXIT_();
return isAvailable;
}
//**************************************************************************** //****************************************************************************
/// @description /// @description
/// If the semaphore counter value is 0 or more, it is incremented, and this /// If the semaphore counter value is 0 or more, it is incremented, and this
@ -171,6 +201,9 @@ bool QXSemaphore::signal(void) {
bool signaled = true; // assume that the semaphore will be signaled bool signaled = true; // assume that the semaphore will be signaled
QF_CRIT_STAT_ QF_CRIT_STAT_
/// @pre the semaphore must be initialized
Q_REQUIRE_ID(400, (m_max_count > (uint_fast16_t)0));
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
if (m_waitSet.notEmpty()) { if (m_waitSet.notEmpty()) {
uint_fast8_t p = m_waitSet.findMax(); uint_fast8_t p = m_waitSet.findMax();
@ -180,7 +213,7 @@ bool QXSemaphore::signal(void) {
QXThread *thr = static_cast<QXThread *>(QF::active_[p]); QXThread *thr = static_cast<QXThread *>(QF::active_[p]);
// the thread must be extended and the semaphore count must be zero // the thread must be extended and the semaphore count must be zero
Q_ASSERT_ID(210, (thr != static_cast<QXThread *>(0)) /* registered */ Q_ASSERT_ID(410, (thr != static_cast<QXThread *>(0)) /* registered */
&& (thr->m_osObject != static_cast<void *>(0)) /* extended */ && (thr->m_osObject != static_cast<void *>(0)) /* extended */
&& (m_count == static_cast<uint_fast16_t>(0))); // not signaled && (m_count == static_cast<uint_fast16_t>(0))); // not signaled

View File

@ -3,8 +3,8 @@
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.9.6 /// Last updated for version 5.9.7
/// Last updated on 2017-07-27 /// Last updated on 2017-08-19
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -69,7 +69,7 @@ Q_DEFINE_THIS_MODULE("qxk_xthr")
/// @usage /// @usage
/// The following example illustrates how to invoke the QXThread ctor in the /// The following example illustrates how to invoke the QXThread ctor in the
/// main() function /// main() function
/// @include qxk_xthread_ctor.cpp /// @include qxk_xctor.cpp
/// ///
QXThread::QXThread(QXThreadHandler const handler, uint_fast8_t const tickRate) QXThread::QXThread(QXThreadHandler const handler, uint_fast8_t const tickRate)
: QActive(Q_STATE_CAST(handler)), : QActive(Q_STATE_CAST(handler)),
@ -107,18 +107,21 @@ void QXThread::dispatch(QEvt const * const /*e*/) {
/// @param[in] stkSize stack size [in bytes] (must not be zero) /// @param[in] stkSize stack size [in bytes] (must not be zero)
/// @param[in] ie pointer to the initial event (not used). /// @param[in] ie pointer to the initial event (not used).
/// ///
/// @note This function should be called via the macro QXTHREAD_START().
///
/// @usage /// @usage
/// The following example shows starting an extended thread: /// The following example shows starting an extended thread:
/// @include qxk_xthread_start.cpp /// @include qxk_xstart.cpp
/// ///
void QXThread::start(uint_fast8_t const prio, void QXThread::start(uint_fast8_t const prio,
QEvt const *qSto[], uint_fast16_t const qLen, QEvt const *qSto[], uint_fast16_t const qLen,
void * const stkSto, uint_fast16_t const stkSize, void * const stkSto, uint_fast16_t const stkSize,
QEvt const * const /*ie*/) QEvt const * const /*ie*/)
{ {
Q_REQUIRE_ID(300, (!QXK_ISR_CONTEXT_()) /* don't start AO's in an ISR! */ /// @pre this function must:
/// - NOT be called from an ISR;
/// - the thread priority cannot exceed #QF_MAX_ACTIVE;
/// - the stack storage must be provided;
/// - the thread must be instantiated (see QP::QXThread::QXThread()).
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* don't start AO's in an ISR! */
&& (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE)) && (prio <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE))
&& (stkSto != static_cast<void *>(0)) && (stkSto != static_cast<void *>(0))
&& (stkSize != static_cast<uint_fast16_t>(0)) && (stkSize != static_cast<uint_fast16_t>(0))
@ -135,6 +138,7 @@ void QXThread::start(uint_fast8_t const prio,
stkSto, stkSize); stkSto, stkSize);
m_prio = prio; m_prio = prio;
m_startPrio = prio;
QF::add_(this); // make QF aware of this extended thread QF::add_(this); // make QF aware of this extended thread
@ -166,12 +170,14 @@ void QXThread::start(uint_fast8_t const prio,
/// @param[in] margin number of required free slots in the queue /// @param[in] margin number of required free slots in the queue
/// after posting the event. /// after posting the event.
/// ///
/// @note this function should be called only via the macro QXTHREAD_POST_X(). /// @note
/// This function should be called only via the macro POST() or POST_X().
/// ///
/// @note The zero value of the @p margin parameter is special and denotes /// @note
/// situation when the post() operation is assumed to succeed (event delivery /// The zero value of the @p margin parameter is special and denotes
/// guarantee). An assertion fires, when the event cannot be delivered in /// situation when the QXThread::post_() operation is assumed to succeed
/// this case. /// (event delivery guarantee). An assertion fires, when the event cannot be
/// delivered in this case.
/// ///
#ifndef Q_SPY #ifndef Q_SPY
bool QXThread::post_(QEvt const * const e, uint_fast16_t const margin) bool QXThread::post_(QEvt const * const e, uint_fast16_t const margin)
@ -210,12 +216,12 @@ bool QXThread::post_(QEvt const * const e, uint_fast16_t const margin,
QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO, QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO,
QS::priv_.QS::priv_.locFilter[QS::AO_OBJ], this) QS::priv_.QS::priv_.locFilter[QS::AO_OBJ], this)
QS_TIME_(); // timestamp QS_TIME_(); // timestamp
QS_OBJ_(sender); // the sender object QS_OBJ_(sender); // the sender object
QS_SIG_(e->sig); // the signal of the event QS_SIG_(e->sig); // the signal of the event
QS_OBJ_(this); // this active object QS_OBJ_(this); // this active object
QS_2U8_(e->poolId_, e->refCtr_); // poolID & refCtr of the evt QS_2U8_(e->poolId_, e->refCtr_); // poolID & refCtr of the evt
QS_EQC_(nFree); // number of free entries QS_EQC_(nFree); // number of free entries
QS_EQC_(m_eQueue.m_nMin); // min number of free entries QS_EQC_(m_eQueue.m_nMin); // min number of free entries
QS_END_NOCRIT_() QS_END_NOCRIT_()
@ -318,16 +324,12 @@ void QXThread::postLIFO(QEvt const * const /*e*/) {
/// to wait for the event to arrive. The value of /// to wait for the event to arrive. The value of
/// QXTHREAD_NO_TIMEOUT indicates that no timeout will /// QXTHREAD_NO_TIMEOUT indicates that no timeout will
/// occur and the queue will block indefinitely. /// occur and the queue will block indefinitely.
/// @param[in] tickRate system clock tick rate serviced in this call.
///
/// @returns /// @returns
/// Returns pointer to the event. If the pointer is not NULL, the event /// Returns pointer to the event. If the pointer is not NULL, the event
/// was delivered. Otherwise the event pointer of NULL indicates that the /// was delivered. Otherwise the event pointer of NULL indicates that the
/// queue has timed out. /// queue has timed out.
/// ///
QEvt const *QXThread::queueGet(uint_fast16_t const nTicks, QEvt const *QXThread::queueGet(uint_fast16_t const nTicks) {
uint_fast8_t const tickRate)
{
QEQueueCtr nFree; QEQueueCtr nFree;
QEvt const *e; QEvt const *e;
QF_CRIT_STAT_ QF_CRIT_STAT_
@ -336,13 +338,13 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks,
QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr); QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr);
/// @pre this function must: /// @pre this function must:
/// (1) NOT be called from an ISR; (2) be called from an extended thread; /// - NOT be called from an ISR;
/// (3) the thread must NOT be holding a mutex and /// - be called from an extended thread;
/// (4) the thread must NOT be already blocked on any object. /// - the thread must NOT be holding a scheduler lock;
/// /// - the thread must NOT be already blocked on any object.
Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */ && (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* !locked */ && (QXK_attr_.lockHolder != thr->m_prio) /* not holding a lock */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked && (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked
// is the queue empty? -- block and wait for event(s) // is the queue empty? -- block and wait for event(s)
@ -351,7 +353,7 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks,
// remember the blocking object (the thread's queue) // remember the blocking object (the thread's queue)
thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_eQueue); thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_eQueue);
thr->teArm_(static_cast<enum_t>(QXK_QUEUE_SIG), nTicks, tickRate); thr->teArm_(static_cast<enum_t>(QXK_QUEUE_SIG), nTicks);
QXK_attr_.readySet.remove(thr->m_prio); QXK_attr_.readySet.remove(thr->m_prio);
(void)QXK_sched_(); (void)QXK_sched_();
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
@ -425,7 +427,7 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks,
/// ///
void QXThread::block_(void) const { void QXThread::block_(void) const {
/// @pre the thread holding the lock cannot block! /// @pre the thread holding the lock cannot block!
Q_REQUIRE_ID(600, m_prio != QXK_attr_.lockPrio); Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != m_prio));
QXK_attr_.readySet.remove(m_prio); QXK_attr_.readySet.remove(m_prio);
(void)QXK_sched_(); (void)QXK_sched_();
} }
@ -455,10 +457,7 @@ void QXThread::unblock_(void) const {
/// @note /// @note
/// must be called from within a critical section /// must be called from within a critical section
/// ///
void QXThread::teArm_(enum_t const sig, void QXThread::teArm_(enum_t const sig, uint_fast16_t const nTicks) {
uint_fast16_t const nTicks,
uint_fast8_t const tickRate)
{
/// @pre 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)); Q_REQUIRE_ID(700, m_timeEvt.m_ctr == static_cast<QTimeEvtCtr>(0));
@ -471,11 +470,12 @@ void QXThread::teArm_(enum_t const sig,
// is the time event unlinked? // is the time event unlinked?
// NOTE: For the duration of a single clock tick of the specified tick // NOTE: For the duration of a single clock tick of the specified tick
// rate a time event can be disarmed and yet still linked in the list, // rate a time event can be disarmed and yet still linked in the list,
// because un-linking is performed exclusively in QF_tickX(). // because un-linking is performed exclusively in QF::tickX().
//
if ((m_timeEvt.refCtr_ & static_cast<uint8_t>(0x80)) if ((m_timeEvt.refCtr_ & static_cast<uint8_t>(0x80))
== static_cast<uint8_t>(0)) == static_cast<uint8_t>(0))
{ {
uint_fast8_t tickRate =
static_cast<uint_fast8_t>(m_timeEvt.refCtr_);
m_timeEvt.refCtr_ |= static_cast<uint8_t>(0x80); // mark as linked m_timeEvt.refCtr_ |= static_cast<uint8_t>(0x80); // mark as linked
// The time event is initially inserted into the separate // The time event is initially inserted into the separate
@ -515,35 +515,32 @@ bool QXThread::teDisarm_(void) {
//**************************************************************************** //****************************************************************************
//! delay (timed block) the current extended thread //! delay (timed block) the current extended thread
bool QXThread::delay(uint_fast16_t const nTicks, bool QXThread::delay(uint_fast16_t const nTicks) {
uint_fast8_t const tickRate)
{
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr); QXThread *thr = static_cast<QXThread *>(QXK_attr_.curr);
/// @pre this function must: /// @pre this function must:
/// (1) NOT be called from an ISR; (2) be called from an extended thread; /// - NOT be called from an ISR;
/// (3) the thread must NOT be holding a mutex and /// - be called from an extended thread;
/// (4) the thread must NOT be already blocked on any object. /// - the thread must NOT be holding a scheduler lock and;
/// /// - the thread must NOT be already blocked on any object.
Q_REQUIRE_ID(900, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
&& (thr != static_cast<QXThread *>(0)) /* current must be extended */ && (thr != static_cast<QXThread *>(0)) /* current must be extended */
&& (QXK_attr_.lockPrio == static_cast<uint_fast8_t>(0)) /* !locked */ && (QXK_attr_.lockHolder != thr->m_prio) /* not holding a lock */
&& (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked && (thr->m_temp.obj == static_cast<QMState const *>(0))); // !blocked
// remember the blocking object // remember the blocking object
thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_timeEvt); thr->m_temp.obj = reinterpret_cast<QMState const *>(&thr->m_timeEvt);
thr->teArm_(static_cast<enum_t>(QXK_DELAY_SIG), nTicks, tickRate); thr->teArm_(static_cast<enum_t>(QXK_DELAY_SIG), nTicks);
thr->block_(); thr->block_();
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();
QF_CRIT_EXIT_NOP(); // BLOCK here QF_CRIT_EXIT_NOP(); // BLOCK here
QF_CRIT_ENTRY_(); QF_CRIT_ENTRY_();
// the blocking object must be the time event // the blocking object must be the time event
Q_ENSURE_ID(990, thr->m_temp.obj == Q_ENSURE_ID(890, thr->m_temp.obj ==
reinterpret_cast<QMState const *>(&thr->m_timeEvt)); reinterpret_cast<QMState const *>(&thr->m_timeEvt));
thr->m_temp.obj = static_cast<QMState const *>(0); // clear thr->m_temp.obj = static_cast<QMState const *>(0); // clear
QF_CRIT_EXIT_(); QF_CRIT_EXIT_();

View File

@ -3,8 +3,8 @@
/// @ingroup qxk /// @ingroup qxk
/// @cond /// @cond
///*************************************************************************** ///***************************************************************************
/// Last updated for version 5.7.2 /// Last updated for version 5.9.7
/// Last updated on 2016-09-28 /// Last updated on 2017-08-19
/// ///
/// Q u a n t u m L e a P s /// Q u a n t u m L e a P s
/// --------------------------- /// ---------------------------
@ -54,7 +54,7 @@ enum QXK_Timeouts {
extern "C" { extern "C" {
//! initialize the private stack of a given AO //! initialize the private stack of a given AO
void QXK_stackInit_(void *act, QP::QXThreadHandler handler, void QXK_stackInit_(void *thr, QP::QXThreadHandler handler,
void *stkSto, uint_fast16_t stkSize); void *stkSto, uint_fast16_t stkSize);
//! called when a thread function returns //! called when a thread function returns

View File

@ -1,2 +0,0 @@
QP/C++ 5.9.6
2017-08-04

2
version-5.9.7 Normal file
View File

@ -0,0 +1,2 @@
QP/C++ 5.9.7
2017-08-18