mirror of
https://github.com/QuantumLeaps/qpcpp.git
synced 2025-01-28 06:02:56 +08:00
5.9.7
This commit is contained in:
parent
4098f977b3
commit
f94afe12dc
121
3rd_party/CMSIS/Include/arm_common_tables.h
vendored
Normal file
121
3rd_party/CMSIS/Include/arm_common_tables.h
vendored
Normal 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 */
|
66
3rd_party/CMSIS/Include/arm_const_structs.h
vendored
Normal file
66
3rd_party/CMSIS/Include/arm_const_structs.h
vendored
Normal 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
7257
3rd_party/CMSIS/Include/arm_math.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
3rd_party/CMSIS/Include/cmsis_armcc.h
vendored
7
3rd_party/CMSIS/Include/cmsis_armcc.h
vendored
@ -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
|
||||||
|
17
3rd_party/CMSIS/Include/cmsis_armclang.h
vendored
17
3rd_party/CMSIS/Include/cmsis_armclang.h
vendored
@ -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 ########################### */
|
||||||
|
126
3rd_party/CMSIS/Include/cmsis_ccs.h
vendored
126
3rd_party/CMSIS/Include/cmsis_ccs.h
vendored
@ -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__*/
|
||||||
|
|
||||||
|
66
3rd_party/CMSIS/Include/cmsis_compiler.h
vendored
66
3rd_party/CMSIS/Include/cmsis_compiler.h
vendored
@ -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
|
||||||
|
23
3rd_party/CMSIS/Include/cmsis_gcc.h
vendored
23
3rd_party/CMSIS/Include/cmsis_gcc.h
vendored
@ -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
39
3rd_party/CMSIS/Include/cmsis_version.h
vendored
Normal 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
|
12
3rd_party/CMSIS/Include/core_armv8mbl.h
vendored
12
3rd_party/CMSIS/Include/core_armv8mbl.h
vendored
@ -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 */
|
||||||
|
|
||||||
|
12
3rd_party/CMSIS/Include/core_armv8mml.h
vendored
12
3rd_party/CMSIS/Include/core_armv8mml.h
vendored
@ -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];
|
||||||
|
10
3rd_party/CMSIS/Include/core_cm0.h
vendored
10
3rd_party/CMSIS/Include/core_cm0.h
vendored
@ -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 */
|
||||||
|
|
||||||
|
17
3rd_party/CMSIS/Include/core_cm0plus.h
vendored
17
3rd_party/CMSIS/Include/core_cm0plus.h
vendored
@ -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 #################################### */
|
||||||
/**
|
/**
|
||||||
|
12
3rd_party/CMSIS/Include/core_cm23.h
vendored
12
3rd_party/CMSIS/Include/core_cm23.h
vendored
@ -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 */
|
||||||
|
|
||||||
|
17
3rd_party/CMSIS/Include/core_cm3.h
vendored
17
3rd_party/CMSIS/Include/core_cm3.h
vendored
@ -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 #################################### */
|
||||||
/**
|
/**
|
||||||
|
12
3rd_party/CMSIS/Include/core_cm33.h
vendored
12
3rd_party/CMSIS/Include/core_cm33.h
vendored
@ -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];
|
||||||
|
20
3rd_party/CMSIS/Include/core_cm4.h
vendored
20
3rd_party/CMSIS/Include/core_cm4.h
vendored
@ -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 #################################### */
|
||||||
/**
|
/**
|
||||||
|
19
3rd_party/CMSIS/Include/core_cm7.h
vendored
19
3rd_party/CMSIS/Include/core_cm7.h
vendored
@ -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 #################################### */
|
||||||
/**
|
/**
|
||||||
|
10
3rd_party/CMSIS/Include/core_sc000.h
vendored
10
3rd_party/CMSIS/Include/core_sc000.h
vendored
@ -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 */
|
||||||
|
|
||||||
|
10
3rd_party/CMSIS/Include/core_sc300.h
vendored
10
3rd_party/CMSIS/Include/core_sc300.h
vendored
@ -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
182
3rd_party/CMSIS/Include/mpu_armv7.h
vendored
Normal 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
|
2
3rd_party/CMSIS/README.txt
vendored
2
3rd_party/CMSIS/README.txt
vendored
@ -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.
|
||||||
|
|
||||||
|
2
3rd_party/efm32pg1b/gnu/startup_efm32pg1b.c
vendored
2
3rd_party/efm32pg1b/gnu/startup_efm32pg1b.c
vendored
@ -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 --------------------------------------*/
|
||||||
|
2
3rd_party/ek-lm3s6965/gnu/startup_LM3S6965.c
vendored
2
3rd_party/ek-lm3s6965/gnu/startup_LM3S6965.c
vendored
@ -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 --------------------------------------*/
|
||||||
|
@ -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 --------------------------------------*/
|
||||||
|
2
3rd_party/mbed-lpc1768/gnu/startup_LPC17xx.c
vendored
2
3rd_party/mbed-lpc1768/gnu/startup_LPC17xx.c
vendored
@ -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 --------------------------------------*/
|
||||||
|
@ -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 --------------------------------------*/
|
||||||
|
@ -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 --------------------------------------*/
|
||||||
|
@ -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 --------------------------------------*/
|
||||||
|
@ -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 --------------------------------------*/
|
||||||
|
@ -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 \
|
||||||
|
@ -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
263
doxygen/api.dox
Normal 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 don’t 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
|
@ -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
BIN
doxygen/images/car_mud.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 136 KiB |
@ -51,6 +51,9 @@ The most unique characteristic of the QP/C++™ 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™ 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™ 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
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
8
doxygen/snippets/qf_xctor.cpp
Normal file
8
doxygen/snippets/qf_xctor.cpp
Normal 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
|
21
doxygen/snippets/qf_xstart.cpp
Normal file
21
doxygen/snippets/qf_xstart.cpp
Normal 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
|
||||||
|
. . .
|
||||||
|
}
|
@ -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>
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
//............................................................................
|
//............................................................................
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
//............................................................................
|
//............................................................................
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
//............................................................................
|
//............................................................................
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//............................................................................
|
//............................................................................
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//............................................................................
|
//............................................................................
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//............................................................................
|
//............................................................................
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//............................................................................
|
//............................................................................
|
||||||
|
@ -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
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
27
include/qf.h
27
include/qf.h
@ -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)),
|
||||||
|
61
include/qk.h
61
include/qk.h
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
187
source/qk.cpp
187
source/qk.cpp
@ -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
|
||||||
|
@ -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
|
|
||||||
|
182
source/qxk.cpp
182
source/qxk.cpp
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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_();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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_();
|
||||||
|
187
src/qk/qk.cpp
187
src/qk/qk.cpp
@ -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
|
||||||
|
@ -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
|
|
||||||
|
182
src/qxk/qxk.cpp
182
src/qxk/qxk.cpp
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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_();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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_();
|
||||||
|
@ -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
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
QP/C++ 5.9.6
|
|
||||||
2017-08-04
|
|
2
version-5.9.7
Normal file
2
version-5.9.7
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
QP/C++ 5.9.7
|
||||||
|
2017-08-18
|
Loading…
x
Reference in New Issue
Block a user