diff --git a/3rd_party/CMSIS/Include/arm_common_tables.h b/3rd_party/CMSIS/Include/arm_common_tables.h new file mode 100644 index 00000000..dfea7460 --- /dev/null +++ b/3rd_party/CMSIS/Include/arm_common_tables.h @@ -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 */ diff --git a/3rd_party/CMSIS/Include/arm_const_structs.h b/3rd_party/CMSIS/Include/arm_const_structs.h new file mode 100644 index 00000000..80a3e8bb --- /dev/null +++ b/3rd_party/CMSIS/Include/arm_const_structs.h @@ -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 diff --git a/3rd_party/CMSIS/Include/arm_math.h b/3rd_party/CMSIS/Include/arm_math.h new file mode 100644 index 00000000..5f51f1b9 --- /dev/null +++ b/3rd_party/CMSIS/Include/arm_math.h @@ -0,0 +1,7257 @@ +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_math.h + * Description: Public header file for CMSIS DSP Library + * + * $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. + */ + +/** + \mainpage CMSIS DSP Software Library + * + * Introduction + * ------------ + * + * This user manual describes the CMSIS DSP software library, + * a suite of common signal processing functions for use on Cortex-M processor based devices. + * + * The library is divided into a number of functions each covering a specific category: + * - Basic math functions + * - Fast math functions + * - Complex math functions + * - Filters + * - Matrix functions + * - Transforms + * - Motor control functions + * - Statistical functions + * - Support functions + * - Interpolation functions + * + * The library has separate functions for operating on 8-bit integers, 16-bit integers, + * 32-bit integer and 32-bit floating-point values. + * + * Using the Library + * ------------ + * + * The library installer contains prebuilt versions of the libraries in the Lib folder. + * - arm_cortexM7lfdp_math.lib (Cortex-M7, Little endian, Double Precision Floating Point Unit) + * - arm_cortexM7bfdp_math.lib (Cortex-M7, Big endian, Double Precision Floating Point Unit) + * - arm_cortexM7lfsp_math.lib (Cortex-M7, Little endian, Single Precision Floating Point Unit) + * - arm_cortexM7bfsp_math.lib (Cortex-M7, Big endian and Single Precision Floating Point Unit on) + * - arm_cortexM7l_math.lib (Cortex-M7, Little endian) + * - arm_cortexM7b_math.lib (Cortex-M7, Big endian) + * - arm_cortexM4lf_math.lib (Cortex-M4, Little endian, Floating Point Unit) + * - arm_cortexM4bf_math.lib (Cortex-M4, Big endian, Floating Point Unit) + * - arm_cortexM4l_math.lib (Cortex-M4, Little endian) + * - arm_cortexM4b_math.lib (Cortex-M4, Big endian) + * - arm_cortexM3l_math.lib (Cortex-M3, Little endian) + * - arm_cortexM3b_math.lib (Cortex-M3, Big endian) + * - arm_cortexM0l_math.lib (Cortex-M0 / Cortex-M0+, Little endian) + * - arm_cortexM0b_math.lib (Cortex-M0 / Cortex-M0+, Big endian) + * - arm_ARMv8MBLl_math.lib (ARMv8M Baseline, Little endian) + * - arm_ARMv8MMLl_math.lib (ARMv8M Mainline, Little endian) + * - arm_ARMv8MMLlfsp_math.lib (ARMv8M Mainline, Little endian, Single Precision Floating Point Unit) + * - arm_ARMv8MMLld_math.lib (ARMv8M Mainline, Little endian, DSP instructions) + * - arm_ARMv8MMLldfsp_math.lib (ARMv8M Mainline, Little endian, DSP instructions, Single Precision Floating Point Unit) + * + * The library functions are declared in the public file arm_math.h which is placed in the Include folder. + * Simply include this file and link the appropriate library in the application and begin calling the library functions. The Library supports single + * public header file arm_math.h for Cortex-M cores with little endian and big endian. Same header file will be used for floating point unit(FPU) variants. + * Define the appropriate pre processor MACRO ARM_MATH_CM7 or ARM_MATH_CM4 or ARM_MATH_CM3 or + * ARM_MATH_CM0 or ARM_MATH_CM0PLUS depending on the target processor in the application. + * For ARMv8M cores define pre processor MACRO ARM_MATH_ARMV8MBL or ARM_MATH_ARMV8MML. + * Set Pre processor MACRO __DSP_PRESENT if ARMv8M Mainline core supports DSP instructions. + * + * + * Examples + * -------- + * + * The library ships with a number of examples which demonstrate how to use the library functions. + * + * Toolchain Support + * ------------ + * + * The library has been developed and tested with MDK-ARM version 5.14.0.0 + * The library is being tested in GCC and IAR toolchains and updates on this activity will be made available shortly. + * + * Building the Library + * ------------ + * + * The library installer contains a project file to re build libraries on MDK-ARM Tool chain in the CMSIS\\DSP_Lib\\Source\\ARM folder. + * - arm_cortexM_math.uvprojx + * + * + * The libraries can be built by opening the arm_cortexM_math.uvprojx project in MDK-ARM, selecting a specific target, and defining the optional pre processor MACROs detailed above. + * + * Pre-processor Macros + * ------------ + * + * Each library project have differant pre-processor macros. + * + * - UNALIGNED_SUPPORT_DISABLE: + * + * Define macro UNALIGNED_SUPPORT_DISABLE, If the silicon does not support unaligned memory access + * + * - ARM_MATH_BIG_ENDIAN: + * + * Define macro ARM_MATH_BIG_ENDIAN to build the library for big endian targets. By default library builds for little endian targets. + * + * - ARM_MATH_MATRIX_CHECK: + * + * Define macro ARM_MATH_MATRIX_CHECK for checking on the input and output sizes of matrices + * + * - ARM_MATH_ROUNDING: + * + * Define macro ARM_MATH_ROUNDING for rounding on support functions + * + * - ARM_MATH_CMx: + * + * Define macro ARM_MATH_CM4 for building the library on Cortex-M4 target, ARM_MATH_CM3 for building library on Cortex-M3 target + * and ARM_MATH_CM0 for building library on Cortex-M0 target, ARM_MATH_CM0PLUS for building library on Cortex-M0+ target, and + * ARM_MATH_CM7 for building the library on cortex-M7. + * + * - ARM_MATH_ARMV8MxL: + * + * Define macro ARM_MATH_ARMV8MBL for building the library on ARMv8M Baseline target, ARM_MATH_ARMV8MBL for building library + * on ARMv8M Mainline target. + * + * - __FPU_PRESENT: + * + * Initialize macro __FPU_PRESENT = 1 when building on FPU supported Targets. Enable this macro for floating point libraries. + * + * - __DSP_PRESENT: + * + * Initialize macro __DSP_PRESENT = 1 when ARMv8M Mainline core supports DSP instructions. + * + *
+ * CMSIS-DSP in ARM::CMSIS Pack + * ----------------------------- + * + * The following files relevant to CMSIS-DSP are present in the ARM::CMSIS Pack directories: + * |File/Folder |Content | + * |------------------------------|------------------------------------------------------------------------| + * |\b CMSIS\\Documentation\\DSP | This documentation | + * |\b CMSIS\\DSP_Lib | Software license agreement (license.txt) | + * |\b CMSIS\\DSP_Lib\\Examples | Example projects demonstrating the usage of the library functions | + * |\b CMSIS\\DSP_Lib\\Source | Source files for rebuilding the library | + * + *
+ * Revision History of CMSIS-DSP + * ------------ + * Please refer to \ref ChangeLog_pg. + * + * Copyright Notice + * ------------ + * + * Copyright (C) 2010-2015 ARM Limited. All rights reserved. + */ + + +/** + * @defgroup groupMath Basic Math Functions + */ + +/** + * @defgroup groupFastMath Fast Math Functions + * This set of functions provides a fast approximation to sine, cosine, and square root. + * As compared to most of the other functions in the CMSIS math library, the fast math functions + * operate on individual values and not arrays. + * There are separate functions for Q15, Q31, and floating-point data. + * + */ + +/** + * @defgroup groupCmplxMath Complex Math Functions + * This set of functions operates on complex data vectors. + * The data in the complex arrays is stored in an interleaved fashion + * (real, imag, real, imag, ...). + * In the API functions, the number of samples in a complex array refers + * to the number of complex values; the array contains twice this number of + * real values. + */ + +/** + * @defgroup groupFilters Filtering Functions + */ + +/** + * @defgroup groupMatrix Matrix Functions + * + * This set of functions provides basic matrix math operations. + * The functions operate on matrix data structures. For example, + * the type + * definition for the floating-point matrix structure is shown + * below: + *
+ *     typedef struct
+ *     {
+ *       uint16_t numRows;     // number of rows of the matrix.
+ *       uint16_t numCols;     // number of columns of the matrix.
+ *       float32_t *pData;     // points to the data of the matrix.
+ *     } arm_matrix_instance_f32;
+ * 
+ * There are similar definitions for Q15 and Q31 data types. + * + * The structure specifies the size of the matrix and then points to + * an array of data. The array is of size numRows X numCols + * and the values are arranged in row order. That is, the + * matrix element (i, j) is stored at: + *
+ *     pData[i*numCols + j]
+ * 
+ * + * \par Init Functions + * There is an associated initialization function for each type of matrix + * data structure. + * The initialization function sets the values of the internal structure fields. + * Refer to the function arm_mat_init_f32(), arm_mat_init_q31() + * and arm_mat_init_q15() for floating-point, Q31 and Q15 types, respectively. + * + * \par + * Use of the initialization function is optional. However, if initialization function is used + * then the instance structure cannot be placed into a const data section. + * To place the instance structure in a const data + * section, manually initialize the data structure. For example: + *
+ * arm_matrix_instance_f32 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q31 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q15 S = {nRows, nColumns, pData};
+ * 
+ * where nRows specifies the number of rows, nColumns + * specifies the number of columns, and pData points to the + * data array. + * + * \par Size Checking + * By default all of the matrix functions perform size checking on the input and + * output matrices. For example, the matrix addition function verifies that the + * two input matrices and the output matrix all have the same number of rows and + * columns. If the size check fails the functions return: + *
+ *     ARM_MATH_SIZE_MISMATCH
+ * 
+ * Otherwise the functions return + *
+ *     ARM_MATH_SUCCESS
+ * 
+ * There is some overhead associated with this matrix size checking. + * The matrix size checking is enabled via the \#define + *
+ *     ARM_MATH_MATRIX_CHECK
+ * 
+ * within the library project settings. By default this macro is defined + * and size checking is enabled. By changing the project settings and + * undefining this macro size checking is eliminated and the functions + * run a bit faster. With size checking disabled the functions always + * return ARM_MATH_SUCCESS. + */ + +/** + * @defgroup groupTransforms Transform Functions + */ + +/** + * @defgroup groupController Controller Functions + */ + +/** + * @defgroup groupStats Statistics Functions + */ +/** + * @defgroup groupSupport Support Functions + */ + +/** + * @defgroup groupInterpolation Interpolation Functions + * These functions perform 1- and 2-dimensional interpolation of data. + * Linear interpolation is used for 1-dimensional data and + * bilinear interpolation is used for 2-dimensional data. + */ + +/** + * @defgroup groupExamples Examples + */ +#ifndef _ARM_MATH_H +#define _ARM_MATH_H + +/* Compiler specific diagnostic adjustment */ +#if defined ( __CC_ARM ) + +#elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + +#elif defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +#elif defined ( __ICCARM__ ) + +#elif defined ( __TI_ARM__ ) + +#elif defined ( __CSMC__ ) + +#elif defined ( __TASKING__ ) + +#else + #error Unknown compiler +#endif + + +#define __CMSIS_GENERIC /* disable NVIC and Systick functions */ + +#if defined(ARM_MATH_CM7) + #include "core_cm7.h" + #define ARM_MATH_DSP +#elif defined (ARM_MATH_CM4) + #include "core_cm4.h" + #define ARM_MATH_DSP +#elif defined (ARM_MATH_CM3) + #include "core_cm3.h" +#elif defined (ARM_MATH_CM0) + #include "core_cm0.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_CM0PLUS) + #include "core_cm0plus.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_ARMV8MBL) + #include "core_armv8mbl.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_ARMV8MML) + #include "core_armv8mml.h" + #if (defined (__DSP_PRESENT) && (__DSP_PRESENT == 1)) + #define ARM_MATH_DSP + #endif +#else + #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS, ARM_MATH_CM0, ARM_MATH_ARMV8MBL, ARM_MATH_ARMV8MML" +#endif + +#undef __CMSIS_GENERIC /* enable NVIC and Systick functions */ +#include "string.h" +#include "math.h" +#ifdef __cplusplus +extern "C" +{ +#endif + + + /** + * @brief Macros required for reciprocal calculation in Normalized LMS + */ + +#define DELTA_Q31 (0x100) +#define DELTA_Q15 0x5 +#define INDEX_MASK 0x0000003F +#ifndef PI + #define PI 3.14159265358979f +#endif + + /** + * @brief Macros required for SINE and COSINE Fast math approximations + */ + +#define FAST_MATH_TABLE_SIZE 512 +#define FAST_MATH_Q31_SHIFT (32 - 10) +#define FAST_MATH_Q15_SHIFT (16 - 10) +#define CONTROLLER_Q31_SHIFT (32 - 9) +#define TABLE_SPACING_Q31 0x400000 +#define TABLE_SPACING_Q15 0x80 + + /** + * @brief Macros required for SINE and COSINE Controller functions + */ + /* 1.31(q31) Fixed value of 2/360 */ + /* -1 to +1 is divided into 360 values so total spacing is (2/360) */ +#define INPUT_SPACING 0xB60B61 + + /** + * @brief Macro for Unaligned Support + */ +#ifndef UNALIGNED_SUPPORT_DISABLE + #define ALIGN4 +#else + #if defined (__GNUC__) + #define ALIGN4 __attribute__((aligned(4))) + #else + #define ALIGN4 __align(4) + #endif +#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */ + + /** + * @brief Error status returned by some functions in the library. + */ + + typedef enum + { + ARM_MATH_SUCCESS = 0, /**< No error */ + ARM_MATH_ARGUMENT_ERROR = -1, /**< One or more arguments are incorrect */ + ARM_MATH_LENGTH_ERROR = -2, /**< Length of data buffer is incorrect */ + ARM_MATH_SIZE_MISMATCH = -3, /**< Size of matrices is not compatible with the operation. */ + ARM_MATH_NANINF = -4, /**< Not-a-number (NaN) or infinity is generated */ + ARM_MATH_SINGULAR = -5, /**< Generated by matrix inversion if the input matrix is singular and cannot be inverted. */ + ARM_MATH_TEST_FAILURE = -6 /**< Test Failed */ + } arm_status; + + /** + * @brief 8-bit fractional data type in 1.7 format. + */ + typedef int8_t q7_t; + + /** + * @brief 16-bit fractional data type in 1.15 format. + */ + typedef int16_t q15_t; + + /** + * @brief 32-bit fractional data type in 1.31 format. + */ + typedef int32_t q31_t; + + /** + * @brief 64-bit fractional data type in 1.63 format. + */ + typedef int64_t q63_t; + + /** + * @brief 32-bit floating-point type definition. + */ + typedef float float32_t; + + /** + * @brief 64-bit floating-point type definition. + */ + typedef double float64_t; + + /** + * @brief definition to read/write two 16 bit values. + */ +#if defined ( __CC_ARM ) + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED __attribute__((unused)) + #define CMSIS_INLINE __attribute__((always_inline)) + +#elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + #define CMSIS_INLINE __attribute__((always_inline)) + +#elif defined ( __GNUC__ ) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + #define CMSIS_INLINE __attribute__((always_inline)) + +#elif defined ( __ICCARM__ ) + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED + #define CMSIS_INLINE + +#elif defined ( __TI_ARM__ ) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + #define CMSIS_INLINE + +#elif defined ( __CSMC__ ) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED + #define CMSIS_INLINE + +#elif defined ( __TASKING__ ) + #define __SIMD32_TYPE __unaligned int32_t + #define CMSIS_UNUSED + #define CMSIS_INLINE + +#else + #error Unknown compiler +#endif + +#define __SIMD32(addr) (*(__SIMD32_TYPE **) & (addr)) +#define __SIMD32_CONST(addr) ((__SIMD32_TYPE *)(addr)) +#define _SIMD32_OFFSET(addr) (*(__SIMD32_TYPE *) (addr)) +#define __SIMD64(addr) (*(int64_t **) & (addr)) + +/* #if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ +#if !defined (ARM_MATH_DSP) + /** + * @brief definition to pack two 16 bit values. + */ +#define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \ + (((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) ) +#define __PKHTB(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0xFFFF0000) | \ + (((int32_t)(ARG2) >> ARG3) & (int32_t)0x0000FFFF) ) + +/* #endif // defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ +#endif /* !defined (ARM_MATH_DSP) */ + + /** + * @brief definition to pack four 8 bit values. + */ +#ifndef ARM_MATH_BIG_ENDIAN + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v1) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v2) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v3) << 24) & (int32_t)0xFF000000) ) +#else + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v3) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v2) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v1) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v0) << 24) & (int32_t)0xFF000000) ) + +#endif + + + /** + * @brief Clips Q63 to Q31 values. + */ + CMSIS_INLINE __STATIC_INLINE q31_t clip_q63_to_q31( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x; + } + + /** + * @brief Clips Q63 to Q15 values. + */ + CMSIS_INLINE __STATIC_INLINE q15_t clip_q63_to_q15( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFF ^ ((q15_t) (x >> 63)))) : (q15_t) (x >> 15); + } + + /** + * @brief Clips Q31 to Q7 values. + */ + CMSIS_INLINE __STATIC_INLINE q7_t clip_q31_to_q7( + q31_t x) + { + return ((q31_t) (x >> 24) != ((q31_t) x >> 23)) ? + ((0x7F ^ ((q7_t) (x >> 31)))) : (q7_t) x; + } + + /** + * @brief Clips Q31 to Q15 values. + */ + CMSIS_INLINE __STATIC_INLINE q15_t clip_q31_to_q15( + q31_t x) + { + return ((q31_t) (x >> 16) != ((q31_t) x >> 15)) ? + ((0x7FFF ^ ((q15_t) (x >> 31)))) : (q15_t) x; + } + + /** + * @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format. + */ + + CMSIS_INLINE __STATIC_INLINE q63_t mult32x64( + q63_t x, + q31_t y) + { + return ((((q63_t) (x & 0x00000000FFFFFFFF) * y) >> 32) + + (((q63_t) (x >> 32) * y))); + } + +/* + #if defined (ARM_MATH_CM0_FAMILY) && defined ( __CC_ARM ) + #define __CLZ __clz + #endif + */ +/* note: function can be removed when all toolchain support __CLZ for Cortex-M0 */ +#if defined (ARM_MATH_CM0_FAMILY) && ((defined (__ICCARM__)) ) + CMSIS_INLINE __STATIC_INLINE uint32_t __CLZ( + q31_t data); + + CMSIS_INLINE __STATIC_INLINE uint32_t __CLZ( + q31_t data) + { + uint32_t count = 0; + uint32_t mask = 0x80000000; + + while ((data & mask) == 0) + { + count += 1u; + mask = mask >> 1u; + } + + return (count); + } +#endif + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type. + */ + + CMSIS_INLINE __STATIC_INLINE uint32_t arm_recip_q31( + q31_t in, + q31_t * dst, + q31_t * pRecipTable) + { + q31_t out; + uint32_t tempVal; + uint32_t index, i; + uint32_t signBits; + + if (in > 0) + { + signBits = ((uint32_t) (__CLZ( in) - 1)); + } + else + { + signBits = ((uint32_t) (__CLZ(-in) - 1)); + } + + /* Convert input sample to 1.31 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 24); + index = (index & INDEX_MASK); + + /* 1.31 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0u; i < 2u; i++) + { + tempVal = (uint32_t) (((q63_t) in * out) >> 31); + tempVal = 0x7FFFFFFFu - tempVal; + /* 1.31 with exp 1 */ + /* out = (q31_t) (((q63_t) out * tempVal) >> 30); */ + out = clip_q63_to_q31(((q63_t) out * tempVal) >> 30); + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1u); + } + + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type. + */ + CMSIS_INLINE __STATIC_INLINE uint32_t arm_recip_q15( + q15_t in, + q15_t * dst, + q15_t * pRecipTable) + { + q15_t out = 0; + uint32_t tempVal = 0; + uint32_t index = 0, i = 0; + uint32_t signBits = 0; + + if (in > 0) + { + signBits = ((uint32_t)(__CLZ( in) - 17)); + } + else + { + signBits = ((uint32_t)(__CLZ(-in) - 17)); + } + + /* Convert input sample to 1.15 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 8); + index = (index & INDEX_MASK); + + /* 1.15 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0u; i < 2u; i++) + { + tempVal = (uint32_t) (((q31_t) in * out) >> 15); + tempVal = 0x7FFFu - tempVal; + /* 1.15 with exp 1 */ + out = (q15_t) (((q31_t) out * tempVal) >> 14); + /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */ + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1); + } + + + /* + * @brief C custom defined intrinisic function for only M0 processors + */ +#if defined(ARM_MATH_CM0_FAMILY) + CMSIS_INLINE __STATIC_INLINE q31_t __SSAT( + q31_t x, + uint32_t y) + { + int32_t posMax, negMin; + uint32_t i; + + posMax = 1; + for (i = 0; i < (y - 1); i++) + { + posMax = posMax * 2; + } + + if (x > 0) + { + posMax = (posMax - 1); + + if (x > posMax) + { + x = posMax; + } + } + else + { + negMin = -posMax; + + if (x < negMin) + { + x = negMin; + } + } + return (x); + } +#endif /* end of ARM_MATH_CM0_FAMILY */ + + + /* + * @brief C custom defined intrinsic function for M3 and M0 processors + */ +/* #if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ +#if !defined (ARM_MATH_DSP) + + /* + * @brief C custom defined QADD8 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QADD8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) + (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) + (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) + (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) + (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QSUB8 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QSUB8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) - (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) - (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) - (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) - (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QADD16 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QADD16( + uint32_t x, + uint32_t y) + { +/* q31_t r, s; without initialisation 'arm_offset_q15 test' fails but 'intrinsic' tests pass! for armCC */ + q31_t r = 0, s = 0; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHADD16 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SHADD16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSUB16 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSUB16 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SHSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QASX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHASX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SHASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSAX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSAX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SHSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SMUSDX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMUSDX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + /* + * @brief C custom defined SMUADX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMUADX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + + /* + * @brief C custom defined QADD for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE int32_t __QADD( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x + (q31_t)y))); + } + + + /* + * @brief C custom defined QSUB for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE int32_t __QSUB( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x - (q31_t)y))); + } + + + /* + * @brief C custom defined SMLAD for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMLAD( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLADX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMLADX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLSDX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMLSDX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALD for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint64_t __SMLALD( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) + ((q15_t) x * (q15_t) y)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALDX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint64_t __SMLALDX( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) y)) + ((q15_t) x * (q15_t) (y >> 16)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMUAD for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMUAD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SMUSD for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMUSD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SXTB16 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SXTB16( + uint32_t x) + { + return ((uint32_t)(((((q31_t)x << 24) >> 24) & (q31_t)0x0000FFFF) | + ((((q31_t)x << 8) >> 8) & (q31_t)0xFFFF0000) )); + } + + /* + * @brief C custom defined SMMLA for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE int32_t __SMMLA( + int32_t x, + int32_t y, + int32_t sum) + { + return (sum + (int32_t) (((int64_t) x * y) >> 32)); + } + +#if 0 + /* + * @brief C custom defined PKHBT for unavailable DSP extension + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __PKHBT( + uint32_t x, + uint32_t y, + uint32_t leftshift) + { + return ( ((x ) & 0x0000FFFFUL) | + ((y << leftshift) & 0xFFFF0000UL) ); + } + + /* + * @brief C custom defined PKHTB for unavailable DSP extension + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __PKHTB( + uint32_t x, + uint32_t y, + uint32_t rightshift) + { + return ( ((x ) & 0xFFFF0000UL) | + ((y >> rightshift) & 0x0000FFFFUL) ); + } +#endif + +/* #endif // defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ +#endif /* !defined (ARM_MATH_DSP) */ + + + /** + * @brief Instance structure for the Q7 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q7_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q7; + + /** + * @brief Instance structure for the Q15 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_f32; + + + /** + * @brief Processing function for the Q7 FIR filter. + * @param[in] S points to an instance of the Q7 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q7( + const arm_fir_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 FIR filter. + * @param[in,out] S points to an instance of the Q7 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed. + */ + void arm_fir_init_q7( + arm_fir_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR filter. + * @param[in] S points to an instance of the Q15 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q15 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR filter. + * @param[in,out] S points to an instance of the Q15 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + * @return The function returns ARM_MATH_SUCCESS if initialization was successful or ARM_MATH_ARGUMENT_ERROR if + * numTaps is not a supported value. + */ + arm_status arm_fir_init_q15( + arm_fir_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR filter. + * @param[in] S points to an instance of the Q31 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q31 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR filter. + * @param[in,out] S points to an instance of the Q31 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_q31( + arm_fir_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR filter. + * @param[in] S points to an instance of the floating-point FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_f32( + const arm_fir_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR filter. + * @param[in,out] S points to an instance of the floating-point FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_f32( + arm_fir_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 Biquad cascade filter. + */ + typedef struct + { + int8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q15_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q15_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + int8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q15; + + /** + * @brief Instance structure for the Q31 Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q31_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q31; + + /** + * @brief Instance structure for the floating-point Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_casd_df1_inst_f32; + + + /** + * @brief Processing function for the Q15 Biquad cascade filter. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q15( + arm_biquad_casd_df1_inst_q15 * S, + uint8_t numStages, + q15_t * pCoeffs, + q15_t * pState, + int8_t postShift); + + + /** + * @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 Biquad cascade filter + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q31( + arm_biquad_casd_df1_inst_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q31_t * pState, + int8_t postShift); + + + /** + * @brief Processing function for the floating-point Biquad cascade filter. + * @param[in] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_f32( + const arm_biquad_casd_df1_inst_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point Biquad cascade filter. + * @param[in,out] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df1_init_f32( + arm_biquad_casd_df1_inst_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float32_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f32; + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float64_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f64; + + /** + * @brief Instance structure for the Q15 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q15_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q15; + + /** + * @brief Instance structure for the Q31 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q31_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q31; + + + /** + * @brief Floating-point matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pScratch); + + + /** + * @brief Q31, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_f32( + const arm_matrix_instance_f32 * pSrc, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q15( + const arm_matrix_instance_q15 * pSrc, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q31( + const arm_matrix_instance_q31 * pSrc, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q31 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix scaling. + * @param[in] pSrc points to the input matrix + * @param[in] scale scale factor + * @param[out] pDst points to the output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_f32( + const arm_matrix_instance_f32 * pSrc, + float32_t scale, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q15( + const arm_matrix_instance_q15 * pSrc, + q15_t scaleFract, + int32_t shift, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q31( + const arm_matrix_instance_q31 * pSrc, + q31_t scaleFract, + int32_t shift, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q31( + arm_matrix_instance_q31 * S, + uint16_t nRows, + uint16_t nColumns, + q31_t * pData); + + + /** + * @brief Q15 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q15( + arm_matrix_instance_q15 * S, + uint16_t nRows, + uint16_t nColumns, + q15_t * pData); + + + /** + * @brief Floating-point matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_f32( + arm_matrix_instance_f32 * S, + uint16_t nRows, + uint16_t nColumns, + float32_t * pData); + + + + /** + * @brief Instance structure for the Q15 PID Control. + */ + typedef struct + { + q15_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ +#if !defined (ARM_MATH_DSP) + q15_t A1; + q15_t A2; +#else + q31_t A1; /**< The derived gain A1 = -Kp - 2Kd | Kd.*/ +#endif + q15_t state[3]; /**< The state array of length 3. */ + q15_t Kp; /**< The proportional gain. */ + q15_t Ki; /**< The integral gain. */ + q15_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q15; + + /** + * @brief Instance structure for the Q31 PID Control. + */ + typedef struct + { + q31_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + q31_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + q31_t A2; /**< The derived gain, A2 = Kd . */ + q31_t state[3]; /**< The state array of length 3. */ + q31_t Kp; /**< The proportional gain. */ + q31_t Ki; /**< The integral gain. */ + q31_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q31; + + /** + * @brief Instance structure for the floating-point PID Control. + */ + typedef struct + { + float32_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + float32_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + float32_t A2; /**< The derived gain, A2 = Kd . */ + float32_t state[3]; /**< The state array of length 3. */ + float32_t Kp; /**< The proportional gain. */ + float32_t Ki; /**< The integral gain. */ + float32_t Kd; /**< The derivative gain. */ + } arm_pid_instance_f32; + + + + /** + * @brief Initialization function for the floating-point PID Control. + * @param[in,out] S points to an instance of the PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_f32( + arm_pid_instance_f32 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + */ + void arm_pid_reset_f32( + arm_pid_instance_f32 * S); + + + /** + * @brief Initialization function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q31( + arm_pid_instance_q31 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + */ + + void arm_pid_reset_q31( + arm_pid_instance_q31 * S); + + + /** + * @brief Initialization function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q15( + arm_pid_instance_q15 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q15 PID Control. + * @param[in,out] S points to an instance of the q15 PID Control structure + */ + void arm_pid_reset_q15( + arm_pid_instance_q15 * S); + + + /** + * @brief Instance structure for the floating-point Linear Interpolate function. + */ + typedef struct + { + uint32_t nValues; /**< nValues */ + float32_t x1; /**< x1 */ + float32_t xSpacing; /**< xSpacing */ + float32_t *pYData; /**< pointer to the table of Y values */ + } arm_linear_interp_instance_f32; + + /** + * @brief Instance structure for the floating-point bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + float32_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_f32; + + /** + * @brief Instance structure for the Q31 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q31_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q31; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q15_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q15; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q7_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q7; + + + /** + * @brief Q7 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the Sin twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q15( + arm_cfft_radix2_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q15( + const arm_cfft_radix2_instance_q15 * S, + q15_t * pSrc); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q15( + arm_cfft_radix4_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_q15( + const arm_cfft_radix4_instance_q15 * S, + q15_t * pSrc); + + /** + * @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q31; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q31( + arm_cfft_radix2_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q31( + const arm_cfft_radix2_instance_q31 * S, + q31_t * pSrc); + + /** + * @brief Instance structure for the Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q31; + +/* Deprecated */ + void arm_cfft_radix4_q31( + const arm_cfft_radix4_instance_q31 * S, + q31_t * pSrc); + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q31( + arm_cfft_radix4_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix2_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_f32( + arm_cfft_radix2_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_f32( + const arm_cfft_radix2_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix4_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_f32( + arm_cfft_radix4_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_f32( + const arm_cfft_radix4_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q15_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q15; + +void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + q15_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q31; + +void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + q31_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_f32; + + void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + float32_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the Q15 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q15_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q15_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q15; + + arm_status arm_rfft_init_q15( + arm_rfft_instance_q15 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q15( + const arm_rfft_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst); + + /** + * @brief Instance structure for the Q31 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q31_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q31_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q31; + + arm_status arm_rfft_init_q31( + arm_rfft_instance_q31 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q31( + const arm_rfft_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint16_t fftLenBy2; /**< length of the complex FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + float32_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + float32_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_f32; + + arm_status arm_rfft_init_f32( + arm_rfft_instance_f32 * S, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_f32( + const arm_rfft_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ +typedef struct + { + arm_cfft_instance_f32 Sint; /**< Internal CFFT structure. */ + uint16_t fftLenRFFT; /**< length of the real sequence */ + float32_t * pTwiddleRFFT; /**< Twiddle factors real stage */ + } arm_rfft_fast_instance_f32 ; + +arm_status arm_rfft_fast_init_f32 ( + arm_rfft_fast_instance_f32 * S, + uint16_t fftLen); + +void arm_rfft_fast_f32( + arm_rfft_fast_instance_f32 * S, + float32_t * p, float32_t * pOut, + uint8_t ifftFlag); + + /** + * @brief Instance structure for the floating-point DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + float32_t normalize; /**< normalizing factor. */ + float32_t *pTwiddle; /**< points to the twiddle factor table. */ + float32_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_f32 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_f32; + + + /** + * @brief Initialization function for the floating-point DCT4/IDCT4. + * @param[in,out] S points to an instance of floating-point DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of floating-point RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of floating-point CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLenReal is not a supported transform length. + */ + arm_status arm_dct4_init_f32( + arm_dct4_instance_f32 * S, + arm_rfft_instance_f32 * S_RFFT, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint16_t N, + uint16_t Nby2, + float32_t normalize); + + + /** + * @brief Processing function for the floating-point DCT4/IDCT4. + * @param[in] S points to an instance of the floating-point DCT4/IDCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_f32( + const arm_dct4_instance_f32 * S, + float32_t * pState, + float32_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q31 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q31_t normalize; /**< normalizing factor. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + q31_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q31 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q31; + + + /** + * @brief Initialization function for the Q31 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q31 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q31 RFFT/RIFFT structure + * @param[in] S_CFFT points to an instance of Q31 CFFT/CIFFT structure + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q31( + arm_dct4_instance_q31 * S, + arm_rfft_instance_q31 * S_RFFT, + arm_cfft_radix4_instance_q31 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q31_t normalize); + + + /** + * @brief Processing function for the Q31 DCT4/IDCT4. + * @param[in] S points to an instance of the Q31 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q31( + const arm_dct4_instance_q31 * S, + q31_t * pState, + q31_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q15 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q15_t normalize; /**< normalizing factor. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + q15_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q15 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q15; + + + /** + * @brief Initialization function for the Q15 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q15 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q15 RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of Q15 CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q15( + arm_dct4_instance_q15 * S, + arm_rfft_instance_q15 * S_RFFT, + arm_cfft_radix4_instance_q15 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q15_t normalize); + + + /** + * @brief Processing function for the Q15 DCT4/IDCT4. + * @param[in] S points to an instance of the Q15 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q15( + const arm_dct4_instance_q15 * S, + q15_t * pState, + q15_t * pInlineBuffer); + + + /** + * @brief Floating-point vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a floating-point vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scale scale factor to be applied + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_f32( + float32_t * pSrc, + float32_t scale, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q7 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q7( + q7_t * pSrc, + q7_t scaleFract, + int8_t shift, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q15 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q15( + q15_t * pSrc, + q15_t scaleFract, + int8_t shift, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q31 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q31( + q31_t * pSrc, + q31_t scaleFract, + int8_t shift, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Dot product of floating-point vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t blockSize, + float32_t * result); + + + /** + * @brief Dot product of Q7 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q7( + q7_t * pSrcA, + q7_t * pSrcB, + uint32_t blockSize, + q31_t * result); + + + /** + * @brief Dot product of Q15 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Dot product of Q31 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Shifts the elements of a Q7 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q7( + q7_t * pSrc, + int8_t shiftBits, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q15 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q15( + q15_t * pSrc, + int8_t shiftBits, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q31 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q31( + q31_t * pSrc, + int8_t shiftBits, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_f32( + float32_t * pSrc, + float32_t offset, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q7( + q7_t * pSrc, + q7_t offset, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q15( + q15_t * pSrc, + q15_t offset, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q31( + q31_t * pSrc, + q31_t offset, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a floating-point vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q7 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a floating-point vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_f32( + float32_t value, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q7 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q7( + q7_t value, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q15 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q15( + q15_t value, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q31 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q31( + q31_t value, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Partial convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q7 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Partial convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Instance structure for the Q15 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_f32; + + + /** + * @brief Processing function for the floating-point FIR decimator. + * @param[in] S points to an instance of the floating-point FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_f32( + const arm_fir_decimate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR decimator. + * @param[in,out] S points to an instance of the floating-point FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_f32( + arm_fir_decimate_instance_f32 * S, + uint16_t numTaps, + uint8_t M, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR decimator. + * @param[in,out] S points to an instance of the Q15 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q15( + arm_fir_decimate_instance_q15 * S, + uint16_t numTaps, + uint8_t M, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR decimator. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q31( + const arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q31( + arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR decimator. + * @param[in,out] S points to an instance of the Q31 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q31( + arm_fir_decimate_instance_q31 * S, + uint16_t numTaps, + uint8_t M, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q15_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q31_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + float32_t *pState; /**< points to the state variable array. The array is of length phaseLength+numTaps-1. */ + } arm_fir_interpolate_instance_f32; + + + /** + * @brief Processing function for the Q15 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q15( + const arm_fir_interpolate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR interpolator. + * @param[in,out] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q15( + arm_fir_interpolate_instance_q15 * S, + uint8_t L, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q31( + const arm_fir_interpolate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR interpolator. + * @param[in,out] S points to an instance of the Q31 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q31( + arm_fir_interpolate_instance_q31 * S, + uint8_t L, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR interpolator. + * @param[in] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_f32( + const arm_fir_interpolate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR interpolator. + * @param[in,out] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_f32( + arm_fir_interpolate_instance_f32 * S, + uint8_t L, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the high precision Q31 Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q63_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< additional shift, in bits, applied to each output sample. */ + } arm_biquad_cas_df1_32x64_ins_q31; + + + /** + * @param[in] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cas_df1_32x64_q31( + const arm_biquad_cas_df1_32x64_ins_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @param[in,out] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cas_df1_32x64_init_q31( + arm_biquad_cas_df1_32x64_ins_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q63_t * pState, + uint8_t postShift); + + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_stereo_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float64_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float64_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f64; + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f32( + const arm_biquad_cascade_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. 2 channels + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_stereo_df2T_f32( + const arm_biquad_cascade_stereo_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f64( + const arm_biquad_cascade_df2T_instance_f64 * S, + float64_t * pSrc, + float64_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f32( + arm_biquad_cascade_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_stereo_df2T_init_f32( + arm_biquad_cascade_stereo_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f64( + arm_biquad_cascade_df2T_instance_f64 * S, + uint8_t numStages, + float64_t * pCoeffs, + float64_t * pState); + + + /** + * @brief Instance structure for the Q15 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_f32; + + + /** + * @brief Initialization function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q15( + arm_fir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pCoeffs, + q15_t * pState); + + + /** + * @brief Processing function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q15( + const arm_fir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q31( + arm_fir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pCoeffs, + q31_t * pState); + + + /** + * @brief Processing function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q31( + const arm_fir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_f32( + arm_fir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Processing function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_f32( + const arm_fir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q15_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q15_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q31_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q31_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + float32_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + float32_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_f32; + + + /** + * @brief Processing function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_f32( + const arm_iir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize-1. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_f32( + arm_iir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pkCoeffs, + float32_t * pvCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q31( + const arm_iir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_q31( + arm_iir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pkCoeffs, + q31_t * pvCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the Q15 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q15( + const arm_iir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the fixed-point Q15 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process per call. + */ + void arm_iir_lattice_init_q15( + arm_iir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pkCoeffs, + q15_t * pvCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the floating-point LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that controls filter coefficient updates. */ + } arm_lms_instance_f32; + + + /** + * @brief Processing function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_f32( + const arm_lms_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_init_f32( + arm_lms_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q15; + + + /** + * @brief Initialization function for the Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q15( + arm_lms_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Processing function for Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q15( + const arm_lms_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q31; + + + /** + * @brief Processing function for Q31 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q31( + const arm_lms_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 LMS filter. + * @param[in] S points to an instance of the Q31 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q31( + arm_lms_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Instance structure for the floating-point normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that control filter coefficient updates. */ + float32_t energy; /**< saves previous frame energy. */ + float32_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_f32; + + + /** + * @brief Processing function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_f32( + arm_lms_norm_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_init_f32( + arm_lms_norm_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q31_t *recipTable; /**< points to the reciprocal initial value table. */ + q31_t energy; /**< saves previous frame energy. */ + q31_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q31; + + + /** + * @brief Processing function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q31( + arm_lms_norm_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q31( + arm_lms_norm_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Instance structure for the Q15 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< Number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q15_t *recipTable; /**< Points to the reciprocal initial value table. */ + q15_t energy; /**< saves previous frame energy. */ + q15_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q15; + + + /** + * @brief Processing function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q15( + arm_lms_norm_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q15( + arm_lms_norm_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Correlation of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Correlation of Q15 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_correlate_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Instance structure for the floating-point sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + float32_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_f32; + + /** + * @brief Instance structure for the Q31 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q31_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q31; + + /** + * @brief Instance structure for the Q15 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q15_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q15; + + /** + * @brief Instance structure for the Q7 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q7_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q7; + + + /** + * @brief Processing function for the floating-point sparse FIR filter. + * @param[in] S points to an instance of the floating-point sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_f32( + arm_fir_sparse_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + float32_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point sparse FIR filter. + * @param[in,out] S points to an instance of the floating-point sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_f32( + arm_fir_sparse_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 sparse FIR filter. + * @param[in] S points to an instance of the Q31 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q31( + arm_fir_sparse_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + q31_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 sparse FIR filter. + * @param[in,out] S points to an instance of the Q31 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q31( + arm_fir_sparse_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 sparse FIR filter. + * @param[in] S points to an instance of the Q15 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q15( + arm_fir_sparse_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + q15_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 sparse FIR filter. + * @param[in,out] S points to an instance of the Q15 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q15( + arm_fir_sparse_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q7 sparse FIR filter. + * @param[in] S points to an instance of the Q7 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q7( + arm_fir_sparse_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + q7_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 sparse FIR filter. + * @param[in,out] S points to an instance of the Q7 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q7( + arm_fir_sparse_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Floating-point sin_cos function. + * @param[in] theta input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cos output. + */ + void arm_sin_cos_f32( + float32_t theta, + float32_t * pSinVal, + float32_t * pCosVal); + + + /** + * @brief Q31 sin_cos function. + * @param[in] theta scaled input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cosine output. + */ + void arm_sin_cos_q31( + q31_t theta, + q31_t * pSinVal, + q31_t * pCosVal); + + + /** + * @brief Floating-point complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + /** + * @brief Q31 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup PID PID Motor Control + * + * A Proportional Integral Derivative (PID) controller is a generic feedback control + * loop mechanism widely used in industrial control systems. + * A PID controller is the most commonly used type of feedback controller. + * + * This set of functions implements (PID) controllers + * for Q15, Q31, and floating-point data types. The functions operate on a single sample + * of data and each call to the function returns a single processed value. + * S points to an instance of the PID control data structure. in + * is the input sample value. The functions return the output value. + * + * \par Algorithm: + *
+   *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
+   *    A0 = Kp + Ki + Kd
+   *    A1 = (-Kp ) - (2 * Kd )
+   *    A2 = Kd  
+ * + * \par + * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant + * + * \par + * \image html PID.gif "Proportional Integral Derivative Controller" + * + * \par + * The PID controller calculates an "error" value as the difference between + * the measured output and the reference input. + * The controller attempts to minimize the error by adjusting the process control inputs. + * The proportional value determines the reaction to the current error, + * the integral value determines the reaction based on the sum of recent errors, + * and the derivative value determines the reaction based on the rate at which the error has been changing. + * + * \par Instance Structure + * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure. + * A separate instance structure must be defined for each PID Controller. + * There are separate instance structure declarations for each of the 3 supported data types. + * + * \par Reset Functions + * There is also an associated reset function for each data type which clears the state array. + * + * \par Initialization Functions + * There is also an associated initialization function for each data type. + * The initialization function performs the following operations: + * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains. + * - Zeros out the values in the state buffer. + * + * \par + * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function. + * + * \par Fixed-Point Behavior + * Care must be taken when using the fixed-point versions of the PID Controller functions. + * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup PID + * @{ + */ + + /** + * @brief Process function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + */ + CMSIS_INLINE __STATIC_INLINE float32_t arm_pid_f32( + arm_pid_instance_f32 * S, + float32_t in) + { + float32_t out; + + /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2] */ + out = (S->A0 * in) + + (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + + } + + /** + * @brief Process function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 64-bit accumulator. + * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. + * Thus, if the accumulator result overflows it wraps around rather than clip. + * In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions. + * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. + */ + CMSIS_INLINE __STATIC_INLINE q31_t arm_pid_q31( + arm_pid_instance_q31 * S, + q31_t in) + { + q63_t acc; + q31_t out; + + /* acc = A0 * x[n] */ + acc = (q63_t) S->A0 * in; + + /* acc += A1 * x[n-1] */ + acc += (q63_t) S->A1 * S->state[0]; + + /* acc += A2 * x[n-2] */ + acc += (q63_t) S->A2 * S->state[1]; + + /* convert output to 1.31 format to add y[n-1] */ + out = (q31_t) (acc >> 31u); + + /* out += y[n-1] */ + out += S->state[2]; + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + + /** + * @brief Process function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using a 64-bit internal accumulator. + * Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result. + * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. + * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. + * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. + * Lastly, the accumulator is saturated to yield a result in 1.15 format. + */ + CMSIS_INLINE __STATIC_INLINE q15_t arm_pid_q15( + arm_pid_instance_q15 * S, + q15_t in) + { + q63_t acc; + q15_t out; + +#if defined (ARM_MATH_DSP) + __SIMD32_TYPE *vstate; + + /* Implementation of PID controller */ + + /* acc = A0 * x[n] */ + acc = (q31_t) __SMUAD((uint32_t)S->A0, (uint32_t)in); + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + vstate = __SIMD32_CONST(S->state); + acc = (q63_t)__SMLALD((uint32_t)S->A1, (uint32_t)*vstate, (uint64_t)acc); +#else + /* acc = A0 * x[n] */ + acc = ((q31_t) S->A0) * in; + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + acc += (q31_t) S->A1 * S->state[0]; + acc += (q31_t) S->A2 * S->state[1]; +#endif + + /* acc += y[n-1] */ + acc += (q31_t) S->state[2] << 15; + + /* saturate the output */ + out = (q15_t) (__SSAT((acc >> 15), 16)); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + /** + * @} end of PID group + */ + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f32( + const arm_matrix_instance_f32 * src, + arm_matrix_instance_f32 * dst); + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f64( + const arm_matrix_instance_f64 * src, + arm_matrix_instance_f64 * dst); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup clarke Vector Clarke Transform + * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector. + * Generally the Clarke transform uses three-phase currents Ia, Ib and Ic to calculate currents + * in the two-phase orthogonal stator axis Ialpha and Ibeta. + * When Ialpha is superposed with Ia as shown in the figure below + * \image html clarke.gif Stator current space vector and its components in (a,b). + * and Ia + Ib + Ic = 0, in this condition Ialpha and Ibeta + * can be calculated using only Ia and Ib. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeFormula.gif + * where Ia and Ib are the instantaneous stator phases and + * pIalpha and pIbeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup clarke + * @{ + */ + + /** + * + * @brief Floating-point Clarke transform + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + */ + CMSIS_INLINE __STATIC_INLINE void arm_clarke_f32( + float32_t Ia, + float32_t Ib, + float32_t * pIalpha, + float32_t * pIbeta) + { + /* Calculate pIalpha using the equation, pIalpha = Ia */ + *pIalpha = Ia; + + /* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */ + *pIbeta = ((float32_t) 0.57735026919 * Ia + (float32_t) 1.15470053838 * Ib); + } + + + /** + * @brief Clarke transform for Q31 version + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + CMSIS_INLINE __STATIC_INLINE void arm_clarke_q31( + q31_t Ia, + q31_t Ib, + q31_t * pIalpha, + q31_t * pIbeta) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIalpha from Ia by equation pIalpha = Ia */ + *pIalpha = Ia; + + /* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30); + + /* Intermediate product is calculated by (2/sqrt(3) * Ib) */ + product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30); + + /* pIbeta is calculated by adding the intermediate products */ + *pIbeta = __QADD(product1, product2); + } + + /** + * @} end of clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q31( + q7_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_clarke Vector Inverse Clarke Transform + * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeInvFormula.gif + * where pIa and pIb are the instantaneous stator phases and + * Ialpha and Ibeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_clarke + * @{ + */ + + /** + * @brief Floating-point Inverse Clarke transform + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + */ + CMSIS_INLINE __STATIC_INLINE void arm_inv_clarke_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pIa, + float32_t * pIb) + { + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */ + *pIb = -0.5f * Ialpha + 0.8660254039f * Ibeta; + } + + + /** + * @brief Inverse Clarke transform for Q31 version + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the subtraction, hence there is no risk of overflow. + */ + CMSIS_INLINE __STATIC_INLINE void arm_inv_clarke_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pIa, + q31_t * pIb) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31); + + /* Intermediate product is calculated by (1/sqrt(3) * pIb) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31); + + /* pIb is calculated by subtracting the products */ + *pIb = __QSUB(product2, product1); + } + + /** + * @} end of inv_clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q15( + q7_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup park Vector Park Transform + * + * Forward Park transform converts the input two-coordinate vector to flux and torque components. + * The Park transform can be used to realize the transformation of the Ialpha and the Ibeta currents + * from the stationary to the moving reference frame and control the spatial relationship between + * the stator vector current and rotor flux vector. + * If we consider the d axis aligned with the rotor flux, the diagram below shows the + * current vector and the relationship from the two reference frames: + * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame" + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkFormula.gif + * where Ialpha and Ibeta are the stator vector components, + * pId and pIq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup park + * @{ + */ + + /** + * @brief Floating-point Park transform + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * The function implements the forward Park transform. + * + */ + CMSIS_INLINE __STATIC_INLINE void arm_park_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pId, + float32_t * pIq, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */ + *pId = Ialpha * cosVal + Ibeta * sinVal; + + /* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */ + *pIq = -Ialpha * sinVal + Ibeta * cosVal; + } + + + /** + * @brief Park transform for Q31 version + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition and subtraction, hence there is no risk of overflow. + */ + CMSIS_INLINE __STATIC_INLINE void arm_park_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pId, + q31_t * pIq, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Ialpha * cosVal) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * sinVal) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Ialpha * sinVal) */ + product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * cosVal) */ + product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31); + + /* Calculate pId by adding the two intermediate products 1 and 2 */ + *pId = __QADD(product1, product2); + + /* Calculate pIq by subtracting the two intermediate products 3 from 4 */ + *pIq = __QSUB(product4, product3); + } + + /** + * @} end of park group + */ + + /** + * @brief Converts the elements of the Q7 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q7_to_float( + q7_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_park Vector Inverse Park transform + * Inverse Park transform converts the input flux and torque components to two-coordinate vector. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkInvFormula.gif + * where pIalpha and pIbeta are the stator vector components, + * Id and Iq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_park + * @{ + */ + + /** + * @brief Floating-point Inverse Park transform + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + */ + CMSIS_INLINE __STATIC_INLINE void arm_inv_park_f32( + float32_t Id, + float32_t Iq, + float32_t * pIalpha, + float32_t * pIbeta, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */ + *pIalpha = Id * cosVal - Iq * sinVal; + + /* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */ + *pIbeta = Id * sinVal + Iq * cosVal; + } + + + /** + * @brief Inverse Park transform for Q31 version + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + CMSIS_INLINE __STATIC_INLINE void arm_inv_park_q31( + q31_t Id, + q31_t Iq, + q31_t * pIalpha, + q31_t * pIbeta, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Id * cosVal) */ + product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Iq * sinVal) */ + product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Id * sinVal) */ + product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Iq * cosVal) */ + product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31); + + /* Calculate pIalpha by using the two intermediate products 1 and 2 */ + *pIalpha = __QSUB(product1, product2); + + /* Calculate pIbeta by using the two intermediate products 3 and 4 */ + *pIbeta = __QADD(product4, product3); + } + + /** + * @} end of Inverse park group + */ + + + /** + * @brief Converts the elements of the Q31 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_float( + q31_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup LinearInterpolate Linear Interpolation + * + * Linear interpolation is a method of curve fitting using linear polynomials. + * Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line + * + * \par + * \image html LinearInterp.gif "Linear interpolation" + * + * \par + * A Linear Interpolate function calculates an output value(y), for the input(x) + * using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values) + * + * \par Algorithm: + *
+   *       y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
+   *       where x0, x1 are nearest values of input x
+   *             y0, y1 are nearest values to output y
+   * 
+ * + * \par + * This set of functions implements Linear interpolation process + * for Q7, Q15, Q31, and floating-point data types. The functions operate on a single + * sample of data and each call to the function returns a single processed value. + * S points to an instance of the Linear Interpolate function data structure. + * x is the input sample value. The functions returns the output value. + * + * \par + * if x is outside of the table boundary, Linear interpolation returns first value of the table + * if x is below input range and returns last value of table if x is above range. + */ + + /** + * @addtogroup LinearInterpolate + * @{ + */ + + /** + * @brief Process function for the floating-point Linear Interpolation Function. + * @param[in,out] S is an instance of the floating-point Linear Interpolation structure + * @param[in] x input sample to process + * @return y processed output sample. + * + */ + CMSIS_INLINE __STATIC_INLINE float32_t arm_linear_interp_f32( + arm_linear_interp_instance_f32 * S, + float32_t x) + { + float32_t y; + float32_t x0, x1; /* Nearest input values */ + float32_t y0, y1; /* Nearest output values */ + float32_t xSpacing = S->xSpacing; /* spacing between input values */ + int32_t i; /* Index variable */ + float32_t *pYData = S->pYData; /* pointer to output table */ + + /* Calculation of index */ + i = (int32_t) ((x - S->x1) / xSpacing); + + if (i < 0) + { + /* Iniatilize output for below specified range as least output value of table */ + y = pYData[0]; + } + else if ((uint32_t)i >= S->nValues) + { + /* Iniatilize output for above specified range as last output value of table */ + y = pYData[S->nValues - 1]; + } + else + { + /* Calculation of nearest input values */ + x0 = S->x1 + i * xSpacing; + x1 = S->x1 + (i + 1) * xSpacing; + + /* Read of nearest output values */ + y0 = pYData[i]; + y1 = pYData[i + 1]; + + /* Calculation of output */ + y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0)); + + } + + /* returns output value */ + return (y); + } + + + /** + * + * @brief Process function for the Q31 Linear Interpolation Function. + * @param[in] pYData pointer to Q31 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + CMSIS_INLINE __STATIC_INLINE q31_t arm_linear_interp_q31( + q31_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q31_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (q31_t)0xFFF00000) >> 20); + + if (index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if (index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* shift left by 11 to keep fract in 1.31 format */ + fract = (x & 0x000FFFFF) << 11; + + /* Read two nearest output values from the index in 1.31(q31) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 2.30 format */ + y = ((q31_t) ((q63_t) y0 * (0x7FFFFFFF - fract) >> 32)); + + /* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */ + y += ((q31_t) (((q63_t) y1 * fract) >> 32)); + + /* Convert y to 1.31 format */ + return (y << 1u); + } + } + + + /** + * + * @brief Process function for the Q15 Linear Interpolation Function. + * @param[in] pYData pointer to Q15 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + CMSIS_INLINE __STATIC_INLINE q15_t arm_linear_interp_q15( + q15_t * pYData, + q31_t x, + uint32_t nValues) + { + q63_t y; /* output */ + q15_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (int32_t)0xFFF00000) >> 20); + + if (index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if (index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 13.35 format */ + y = ((q63_t) y0 * (0xFFFFF - fract)); + + /* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */ + y += ((q63_t) y1 * (fract)); + + /* convert y to 1.15 format */ + return (q15_t) (y >> 20); + } + } + + + /** + * + * @brief Process function for the Q7 Linear Interpolation Function. + * @param[in] pYData pointer to Q7 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + */ + CMSIS_INLINE __STATIC_INLINE q7_t arm_linear_interp_q7( + q7_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q7_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + uint32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + if (x < 0) + { + return (pYData[0]); + } + index = (x >> 20) & 0xfff; + + if (index >= (nValues - 1)) + { + return (pYData[nValues - 1]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index and are in 1.7(q7) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */ + y = ((y0 * (0xFFFFF - fract))); + + /* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */ + y += (y1 * fract); + + /* convert y to 1.7(q7) format */ + return (q7_t) (y >> 20); + } + } + + /** + * @} end of LinearInterpolate group + */ + + /** + * @brief Fast approximation to the trigonometric sine function for floating-point data. + * @param[in] x input value in radians. + * @return sin(x). + */ + float32_t arm_sin_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q31_t arm_sin_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q15_t arm_sin_q15( + q15_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for floating-point data. + * @param[in] x input value in radians. + * @return cos(x). + */ + float32_t arm_cos_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q31_t arm_cos_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q15_t arm_cos_q15( + q15_t x); + + + /** + * @ingroup groupFastMath + */ + + + /** + * @defgroup SQRT Square Root + * + * Computes the square root of a number. + * There are separate functions for Q15, Q31, and floating-point data types. + * The square root function is computed using the Newton-Raphson algorithm. + * This is an iterative algorithm of the form: + *
+   *      x1 = x0 - f(x0)/f'(x0)
+   * 
+ * where x1 is the current estimate, + * x0 is the previous estimate, and + * f'(x0) is the derivative of f() evaluated at x0. + * For the square root function, the algorithm reduces to: + *
+   *     x0 = in/2                         [initial guess]
+   *     x1 = 1/2 * ( x0 + in / x0)        [each iteration]
+   * 
+ */ + + + /** + * @addtogroup SQRT + * @{ + */ + + /** + * @brief Floating-point square root function. + * @param[in] in input value. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + CMSIS_INLINE __STATIC_INLINE arm_status arm_sqrt_f32( + float32_t in, + float32_t * pOut) + { + if (in >= 0.0f) + { + +#if (__FPU_USED == 1) && defined ( __CC_ARM ) + *pOut = __sqrtf(in); +#elif (__FPU_USED == 1) && (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined(__GNUC__) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined ( __ICCARM__ ) && (__VER__ >= 6040000) + __ASM("VSQRT.F32 %0,%1" : "=t"(*pOut) : "t"(in)); +#else + *pOut = sqrtf(in); +#endif + + return (ARM_MATH_SUCCESS); + } + else + { + *pOut = 0.0f; + return (ARM_MATH_ARGUMENT_ERROR); + } + } + + + /** + * @brief Q31 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q31( + q31_t in, + q31_t * pOut); + + + /** + * @brief Q15 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x0000 to 0x7FFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q15( + q15_t in, + q15_t * pOut); + + /** + * @} end of SQRT group + */ + + + /** + * @brief floating-point Circular write function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_f32( + int32_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const int32_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + + /** + * @brief floating-point Circular Read function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularRead_f32( + int32_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + int32_t * dst, + int32_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if (dst == (int32_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if (rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q15 Circular write function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_q15( + q15_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q15_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q15 Circular Read function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularRead_q15( + q15_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q15_t * dst, + q15_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if (dst == (q15_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update wOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if (rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q7 Circular write function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_q7( + q7_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q7_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q7 Circular Read function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularRead_q7( + q7_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q7_t * dst, + q7_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if (dst == (q7_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if (rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Sum of the squares of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q31( + q31_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q15( + q15_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q7( + q7_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult); + + + /** + * @brief Mean value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Mean value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Variance of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Standard deviation of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Floating-point complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t numSamples, + q31_t * realResult, + q31_t * imagResult); + + + /** + * @brief Q31 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t numSamples, + q63_t * realResult, + q63_t * imagResult); + + + /** + * @brief Floating-point complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t numSamples, + float32_t * realResult, + float32_t * imagResult); + + + /** + * @brief Q15 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q15( + q15_t * pSrcCmplx, + q15_t * pSrcReal, + q15_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q31( + q31_t * pSrcCmplx, + q31_t * pSrcReal, + q31_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_f32( + float32_t * pSrcCmplx, + float32_t * pSrcReal, + float32_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Minimum value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] result is output pointer + * @param[in] index is the array index of the minimum value in the input buffer. + */ + void arm_min_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * result, + uint32_t * index); + + + /** + * @brief Minimum value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[in] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q7 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q15 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q31 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a floating-point vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Q15 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Converts the elements of the floating-point vector to Q31 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q31 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q31( + float32_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q15 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q15 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q15( + float32_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q7 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q7 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q7( + float32_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q15 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q15( + q31_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q7( + q31_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_float( + q15_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q31 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q31( + q15_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q7( + q15_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup BilinearInterpolate Bilinear Interpolation + * + * Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid. + * The underlying function f(x, y) is sampled on a regular grid and the interpolation process + * determines values between the grid points. + * Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension. + * Bilinear interpolation is often used in image processing to rescale images. + * The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types. + * + * Algorithm + * \par + * The instance structure used by the bilinear interpolation functions describes a two dimensional data table. + * For floating-point, the instance structure is defined as: + *
+   *   typedef struct
+   *   {
+   *     uint16_t numRows;
+   *     uint16_t numCols;
+   *     float32_t *pData;
+   * } arm_bilinear_interp_instance_f32;
+   * 
+ * + * \par + * where numRows specifies the number of rows in the table; + * numCols specifies the number of columns in the table; + * and pData points to an array of size numRows*numCols values. + * The data table pTable is organized in row order and the supplied data values fall on integer indexes. + * That is, table element (x,y) is located at pTable[x + y*numCols] where x and y are integers. + * + * \par + * Let (x, y) specify the desired interpolation point. Then define: + *
+   *     XF = floor(x)
+   *     YF = floor(y)
+   * 
+ * \par + * The interpolated output point is computed as: + *
+   *  f(x, y) = f(XF, YF) * (1-(x-XF)) * (1-(y-YF))
+   *           + f(XF+1, YF) * (x-XF)*(1-(y-YF))
+   *           + f(XF, YF+1) * (1-(x-XF))*(y-YF)
+   *           + f(XF+1, YF+1) * (x-XF)*(y-YF)
+   * 
+ * Note that the coordinates (x, y) contain integer and fractional components. + * The integer components specify which portion of the table to use while the + * fractional components control the interpolation processor. + * + * \par + * if (x,y) are outside of the table boundary, Bilinear interpolation returns zero output. + */ + + /** + * @addtogroup BilinearInterpolate + * @{ + */ + + + /** + * + * @brief Floating-point bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate. + * @param[in] Y interpolation coordinate. + * @return out interpolated value. + */ + CMSIS_INLINE __STATIC_INLINE float32_t arm_bilinear_interp_f32( + const arm_bilinear_interp_instance_f32 * S, + float32_t X, + float32_t Y) + { + float32_t out; + float32_t f00, f01, f10, f11; + float32_t *pData = S->pData; + int32_t xIndex, yIndex, index; + float32_t xdiff, ydiff; + float32_t b1, b2, b3, b4; + + xIndex = (int32_t) X; + yIndex = (int32_t) Y; + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (xIndex < 0 || xIndex > (S->numRows - 1) || yIndex < 0 || yIndex > (S->numCols - 1)) + { + return (0); + } + + /* Calculation of index for two nearest points in X-direction */ + index = (xIndex - 1) + (yIndex - 1) * S->numCols; + + + /* Read two nearest points in X-direction */ + f00 = pData[index]; + f01 = pData[index + 1]; + + /* Calculation of index for two nearest points in Y-direction */ + index = (xIndex - 1) + (yIndex) * S->numCols; + + + /* Read two nearest points in Y-direction */ + f10 = pData[index]; + f11 = pData[index + 1]; + + /* Calculation of intermediate values */ + b1 = f00; + b2 = f01 - f00; + b3 = f10 - f00; + b4 = f00 - f01 - f10 + f11; + + /* Calculation of fractional part in X */ + xdiff = X - xIndex; + + /* Calculation of fractional part in Y */ + ydiff = Y - yIndex; + + /* Calculation of bi-linear interpolated output */ + out = b1 + b2 * xdiff + b3 * ydiff + b4 * xdiff * ydiff; + + /* return to application */ + return (out); + } + + + /** + * + * @brief Q31 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + CMSIS_INLINE __STATIC_INLINE q31_t arm_bilinear_interp_q31( + arm_bilinear_interp_instance_q31 * S, + q31_t X, + q31_t Y) + { + q31_t out; /* Temporary output */ + q31_t acc = 0; /* output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q31_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q31_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* shift left xfract by 11 to keep 1.31 format */ + xfract = (X & 0x000FFFFF) << 11u; + + /* Read two nearest output values from the index */ + x1 = pYData[(rI) + (int32_t)nCols * (cI) ]; + x2 = pYData[(rI) + (int32_t)nCols * (cI) + 1]; + + /* 20 bits for the fractional part */ + /* shift left yfract by 11 to keep 1.31 format */ + yfract = (Y & 0x000FFFFF) << 11u; + + /* Read two nearest output values from the index */ + y1 = pYData[(rI) + (int32_t)nCols * (cI + 1) ]; + y2 = pYData[(rI) + (int32_t)nCols * (cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 3.29(q29) format */ + out = ((q31_t) (((q63_t) x1 * (0x7FFFFFFF - xfract)) >> 32)); + acc = ((q31_t) (((q63_t) out * (0x7FFFFFFF - yfract)) >> 32)); + + /* x2 * (xfract) * (1-yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) x2 * (0x7FFFFFFF - yfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (xfract) >> 32)); + + /* y1 * (1 - xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y1 * (0x7FFFFFFF - xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* y2 * (xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y2 * (xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* Convert acc to 1.31(q31) format */ + return ((q31_t)(acc << 2)); + } + + + /** + * @brief Q15 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + CMSIS_INLINE __STATIC_INLINE q15_t arm_bilinear_interp_q15( + arm_bilinear_interp_instance_q15 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q15_t x1, x2, y1, y2; /* Nearest output values */ + q31_t xfract, yfract; /* X, Y fractional parts */ + int32_t rI, cI; /* Row and column indices */ + q15_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & 0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 13.51 format */ + + /* x1 is in 1.15(q15), xfract in 12.20 format and out is in 13.35 format */ + /* convert 13.35 to 13.31 by right shifting and out is in 1.31 */ + out = (q31_t) (((q63_t) x1 * (0xFFFFF - xfract)) >> 4u); + acc = ((q63_t) out * (0xFFFFF - yfract)); + + /* x2 * (xfract) * (1-yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) x2 * (0xFFFFF - yfract)) >> 4u); + acc += ((q63_t) out * (xfract)); + + /* y1 * (1 - xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y1 * (0xFFFFF - xfract)) >> 4u); + acc += ((q63_t) out * (yfract)); + + /* y2 * (xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y2 * (xfract)) >> 4u); + acc += ((q63_t) out * (yfract)); + + /* acc is in 13.51 format and down shift acc by 36 times */ + /* Convert out to 1.15 format */ + return ((q15_t)(acc >> 36)); + } + + + /** + * @brief Q7 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + CMSIS_INLINE __STATIC_INLINE q7_t arm_bilinear_interp_q7( + arm_bilinear_interp_instance_q7 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q7_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q7_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 16.47 format */ + out = ((x1 * (0xFFFFF - xfract))); + acc = (((q63_t) out * (0xFFFFF - yfract))); + + /* x2 * (xfract) * (1-yfract) in 2.22 and adding to acc */ + out = ((x2 * (0xFFFFF - yfract))); + acc += (((q63_t) out * (xfract))); + + /* y1 * (1 - xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y1 * (0xFFFFF - xfract))); + acc += (((q63_t) out * (yfract))); + + /* y2 * (xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y2 * (yfract))); + acc += (((q63_t) out * (xfract))); + + /* acc in 16.47 format and down shift by 40 to convert to 1.7 format */ + return ((q7_t)(acc >> 40)); + } + + /** + * @} end of BilinearInterpolate group + */ + + +/* SMMLAR */ +#define multAcc_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) + ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMLSR */ +#define multSub_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) - ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMULR */ +#define mult_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((q63_t) x * y + 0x80000000LL ) >> 32) + +/* SMMLA */ +#define multAcc_32x32_keep32(a, x, y) \ + a += (q31_t) (((q63_t) x * y) >> 32) + +/* SMMLS */ +#define multSub_32x32_keep32(a, x, y) \ + a -= (q31_t) (((q63_t) x * y) >> 32) + +/* SMMUL */ +#define mult_32x32_keep32(a, x, y) \ + a = (q31_t) (((q63_t) x * y ) >> 32) + + +#if defined ( __CC_ARM ) + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("push") \ + _Pragma ("O1") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) + #define LOW_OPTIMIZATION_EXIT \ + _Pragma ("pop") + #else + #define LOW_OPTIMIZATION_EXIT + #endif + + /* Enter low optimization region - place directly above function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined (__ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __GNUC__ ) + #define LOW_OPTIMIZATION_ENTER \ + __attribute__(( optimize("-O1") )) + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __ICCARM__ ) + /* Enter low optimization region - place directly above function definition */ + #if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define LOW_OPTIMIZATION_EXIT + + /* Enter low optimization region - place directly above function definition */ + #if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __TI_ARM__ ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __CSMC__ ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __TASKING__ ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#endif + + +#ifdef __cplusplus +} +#endif + +/* Compiler specific diagnostic adjustment */ +#if defined ( __CC_ARM ) + +#elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + +#elif defined ( __GNUC__ ) +#pragma GCC diagnostic pop + +#elif defined ( __ICCARM__ ) + +#elif defined ( __TI_ARM__ ) + +#elif defined ( __CSMC__ ) + +#elif defined ( __TASKING__ ) + +#else + #error Unknown compiler +#endif + +#endif /* _ARM_MATH_H */ + +/** + * + * End of file. + */ diff --git a/3rd_party/CMSIS/Include/cmsis_armcc.h b/3rd_party/CMSIS/Include/cmsis_armcc.h index 7b2a2847..1d6a5fbd 100644 --- a/3rd_party/CMSIS/Include/cmsis_armcc.h +++ b/3rd_party/CMSIS/Include/cmsis_armcc.h @@ -73,6 +73,9 @@ #ifndef __PACKED_STRUCT #define __PACKED_STRUCT __packed struct #endif +#ifndef __PACKED_UNION + #define __PACKED_UNION __packed union +#endif #ifndef __UNALIGNED_UINT32 /* deprecated */ #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x))) #endif @@ -91,7 +94,9 @@ #ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) #endif - +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif /* ########################### Core Function Access ########################### */ /** \ingroup CMSIS_Core_FunctionInterface diff --git a/3rd_party/CMSIS/Include/cmsis_armclang.h b/3rd_party/CMSIS/Include/cmsis_armclang.h index 7c22d840..21482970 100644 --- a/3rd_party/CMSIS/Include/cmsis_armclang.h +++ b/3rd_party/CMSIS/Include/cmsis_armclang.h @@ -22,7 +22,7 @@ * 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 #define __CMSIS_ARMCLANG_H @@ -56,10 +56,13 @@ #ifndef __PACKED_STRUCT #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) #endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif #ifndef __UNALIGNED_UINT32 /* deprecated */ #pragma clang diagnostic push #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; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) @@ -67,7 +70,7 @@ #ifndef __UNALIGNED_UINT16_WRITE #pragma clang diagnostic push #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; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) @@ -75,7 +78,7 @@ #ifndef __UNALIGNED_UINT16_READ #pragma clang diagnostic push #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; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) @@ -83,7 +86,7 @@ #ifndef __UNALIGNED_UINT32_WRITE #pragma clang diagnostic push #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; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) @@ -91,6 +94,7 @@ #ifndef __UNALIGNED_UINT32_READ #pragma clang diagnostic push #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; }; #pragma clang diagnostic pop #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) @@ -98,6 +102,9 @@ #ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) #endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif /* ########################### Core Function Access ########################### */ diff --git a/3rd_party/CMSIS/Include/cmsis_ccs.h b/3rd_party/CMSIS/Include/cmsis_ccs.h index 7243f2e0..d69e9be1 100644 --- a/3rd_party/CMSIS/Include/cmsis_ccs.h +++ b/3rd_party/CMSIS/Include/cmsis_ccs.h @@ -44,11 +44,12 @@ // // v5e, v6, Cortex-M3, Cortex-M4, Cortex-R4, and Cortex-A8 compiler intrinsics // -#define __CLZ _norm -#define __SXTB _sxtb -#define __SXTH _sxth -#define __UXTB _uxtb -#define __UXTH _uxth +#define __CLZ _norm +#define __SXTB _sxtb +#define __SXTH _sxth +#define __UXTB _uxtb +#define __UXTH _uxth + // CCS supports intrinsics to take advantage of the shift operand left/right // before saturation extension of SSAT, but CMSIS does not take advantage // of those, so tell the compiler to use a sat & shift left with a shift @@ -78,6 +79,8 @@ #define __ISB _isb +#define __WFI() __asm(" wfi") + #elif (__TI_COMPILER_VERSION__ >= 4009000) #define __enable_fault_irq _enable_interrupts @@ -88,10 +91,12 @@ __attribute__( ( always_inline ) ) static inline void __nop(void) { __asm(" nop"); } + __attribute__( ( always_inline ) ) static inline void __NOP(void) { __asm(" nop"); } + // Data Synchronization Barrier __attribute__( ( always_inline ) ) static inline void __DSB(void) { @@ -103,6 +108,11 @@ __attribute__( ( always_inline ) ) static inline void __ISB(void) __asm(" isb"); } +__attribute__( ( always_inline ) ) static inline void __WFI(void) +{ + __asm(" wfi"); +} + #endif /*__TI_COMPILER_VERSION__ version*/ #endif /*__TI_COMPILER_VERSION__*/ @@ -112,15 +122,15 @@ __attribute__( ( always_inline ) ) static inline void __ISB(void) // #define __ROR __ror #define __SXTB16(src) _sxtb16((src),0) -#define __QADD _sadd -#define __QDADD _sdadd -#define __QDSUB _sdsub -#define __SMLABB _smlabb -#define __SMLABT _smlabt -#define __SMLALBB _smlalbb -#define __SMLALBT _smlalbt -#define __SMLALTB _smlaltb -#define __SMLALTT _smlaltt +#define __QADD _sadd +#define __QDADD _sdadd +#define __QDSUB _sdsub +#define __SMLABB _smlabb +#define __SMLABT _smlabt +#define __SMLALBB _smlalbb +#define __SMLALBT _smlalbt +#define __SMLALTB _smlaltb +#define __SMLALTT _smlaltt #define __SMLATB _smlatb #define __SMLATT _smlatt #define __SMLAWB _smlawb @@ -132,77 +142,77 @@ __attribute__( ( always_inline ) ) static inline void __ISB(void) #define __SMULTT _smultt #define __SMULWB _smulwb #define __SMULWT _smulwt -#define __QSUB _ssub -#define __SUBC _subc +#define __QSUB _ssub +#define __SUBC _subc // // v6, Cortex-M4, Cortex-R4, and Cortex-A8 compiler intrinsics // -#define __SHASX _shaddsubx -#define __SHSAX _shsubaddx -#define __PKHBT _pkhbt -#define __PKHTB _pkhtb +#define __SHASX _shaddsubx +#define __SHSAX _shsubaddx +#define __PKHBT _pkhbt +#define __PKHTB _pkhtb #define __QADD16 _qadd16 -#define __QADD8 _qadd8 +#define __QADD8 _qadd8 #define __QSUB16 _qsub16 -#define __QSUB8 _qsub8 -#define __QASX _saddsubx -#define __QSAX _qsubaddx +#define __QSUB8 _qsub8 +#define __QASX _saddsubx +#define __QSAX _qsubaddx #define __SADD16 _sadd16 -#define __SADD8 _sadd8 -#define __SASX _saddsubx -#define __SEL _sel -#define __SHADD16 _shadd16 +#define __SADD8 _sadd8 +#define __SASX _saddsubx +#define __SEL _sel +#define __SHADD16 _shadd16 #define __SHADD8 _shadd8 -#define __SHSUB16 _shsub16 +#define __SHSUB16 _shsub16 #define __SHSUB8 _shsub8 -#define __SMLAD _smlad +#define __SMLAD _smlad #define __SMLADX _smladx #define __SMLALD(src1, src2, accumulator) _smlald(accumulator, src1, src2) -#define __SMLALDX _smlaldx -#define __SMLSD _smlsd +#define __SMLALDX _smlaldx +#define __SMLSD _smlsd #define __SMLSDX _smlsdx #define __SMLSLD _smlsld -#define __SMLSLDX _smlsldx -#define __SMMLA _smmla +#define __SMLSLDX _smlsldx +#define __SMMLA _smmla #define __SMMLAR _smmlar -#define __SMMLS _smmls +#define __SMMLS _smmls #define __SMMLSR _smmlsr -#define __SMMUL _smmul +#define __SMMUL _smmul #define __SMMULR _smmulr -#define __SMUAD _smuad +#define __SMUAD _smuad #define __SMUADX _smuadx -#define __SMUSD _smusd +#define __SMUSD _smusd #define __SMUSDX _smusdx #define __SSAT16 _ssat16 #define __SSUB16 _ssub16 -#define __SSUB8 _ssub8 -#define __SSAX _ssubaddx -#define __SXTAB _sxtab -#define __SXTAB16 _sxtab16 -#define __SXTAH _sxtah -#define __UMAAL _umaal +#define __SSUB8 _ssub8 +#define __SSAX _ssubaddx +#define __SXTAB _sxtab +#define __SXTAB16 _sxtab16 +#define __SXTAH _sxtah +#define __UMAAL _umaal #define __UADD16 _uadd16 -#define __UADD8 _uadd8 -#define __UHADD16 _uhadd16 +#define __UADD8 _uadd8 +#define __UHADD16 _uhadd16 #define __UHADD8 _uhadd8 -#define __UASX _uaddsubx -#define __UHSUB16 _uhsub16 +#define __UASX _uaddsubx +#define __UHSUB16 _uhsub16 #define __UHSUB8 _uhsub8 -#define __UQADD16 _uqadd16 +#define __UQADD16 _uqadd16 #define __UQADD8 _uqadd8 -#define __UQASX _uqaddsubx -#define __UQSUB16 _uqsub16 +#define __UQASX _uqaddsubx +#define __UQSUB16 _uqsub16 #define __UQSUB8 _uqsub8 -#define __UQSAX _uqsubaddx -#define __USAD8 _usad8 +#define __UQSAX _uqsubaddx +#define __USAD8 _usad8 #define __USAT16 _usat16 #define __USUB16 _usub16 -#define __USUB8 _usub8 -#define __USAX _usubaddx -#define __UXTAB _uxtab -#define __UXTAB16 _uxtab16 -#define __UXTAH _uxtah +#define __USUB8 _usub8 +#define __USAX _usubaddx +#define __UXTAB _uxtab +#define __UXTAB16 _uxtab16 +#define __UXTAH _uxtah #define __UXTB16 _uxtb16 #endif /*__TI_TMS470_V7M4__*/ diff --git a/3rd_party/CMSIS/Include/cmsis_compiler.h b/3rd_party/CMSIS/Include/cmsis_compiler.h index 2ef183fb..fece0274 100644 --- a/3rd_party/CMSIS/Include/cmsis_compiler.h +++ b/3rd_party/CMSIS/Include/cmsis_compiler.h @@ -53,6 +53,7 @@ */ #elif defined ( __ICCARM__ ) + #ifndef __ASM #define __ASM __asm #endif @@ -65,6 +66,21 @@ #include + /* 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 #define __NO_RETURN __noreturn #endif @@ -80,6 +96,9 @@ #ifndef __PACKED_STRUCT #define __PACKED_STRUCT __packed struct #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION __packed union + #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ __packed struct T_UINT32 { uint32_t v; }; #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) @@ -104,6 +123,32 @@ #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. #define __ALIGNED(x) #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 #define __PACKED_STRUCT struct __attribute__((packed)) #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed)) + #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ struct __attribute__((packed)) T_UINT32 { uint32_t v; }; #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) @@ -159,6 +207,10 @@ #ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif /* @@ -195,6 +247,9 @@ #ifndef __PACKED_STRUCT #define __PACKED_STRUCT struct __packed__ #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __packed__ + #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ struct __packed__ T_UINT32 { uint32_t v; }; #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) @@ -218,6 +273,10 @@ #ifndef __ALIGNED #define __ALIGNED(x) __align(x) #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif /* @@ -252,6 +311,9 @@ #ifndef __PACKED_STRUCT #define __PACKED_STRUCT @packed struct #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION @packed union + #endif #ifndef __UNALIGNED_UINT32 /* deprecated */ @packed struct T_UINT32 { uint32_t v; }; #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) @@ -276,6 +338,10 @@ #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. #define __ALIGNED(x) #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif #else diff --git a/3rd_party/CMSIS/Include/cmsis_gcc.h b/3rd_party/CMSIS/Include/cmsis_gcc.h index f023d77b..05f75703 100644 --- a/3rd_party/CMSIS/Include/cmsis_gcc.h +++ b/3rd_party/CMSIS/Include/cmsis_gcc.h @@ -31,6 +31,11 @@ #pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wunused-parameter" +/* Fallback for __has_builtin */ +#ifndef __has_builtin + #define __has_builtin(x) (0) +#endif + /* CMSIS compiler specific defines */ #ifndef __ASM #define __ASM __asm @@ -56,6 +61,9 @@ #ifndef __PACKED_STRUCT #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) #endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif #ifndef __UNALIGNED_UINT32 /* deprecated */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpacked" @@ -99,6 +107,9 @@ #ifndef __ALIGNED #define __ALIGNED(x) __attribute__((aligned(x))) #endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif /* ########################### Core Function Access ########################### */ @@ -694,12 +705,17 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) { #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 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; __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); return(result); +#endif #else - return(0U); + return(0U); #endif } @@ -713,7 +729,12 @@ __attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) { #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 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"); +#endif #else (void)fpscr; #endif diff --git a/3rd_party/CMSIS/Include/cmsis_version.h b/3rd_party/CMSIS/Include/cmsis_version.h new file mode 100644 index 00000000..d458a6c8 --- /dev/null +++ b/3rd_party/CMSIS/Include/cmsis_version.h @@ -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 diff --git a/3rd_party/CMSIS/Include/core_armv8mbl.h b/3rd_party/CMSIS/Include/core_armv8mbl.h index d0393520..ccb1e3a3 100644 --- a/3rd_party/CMSIS/Include/core_armv8mbl.h +++ b/3rd_party/CMSIS/Include/core_armv8mbl.h @@ -2,7 +2,7 @@ * @file core_armv8mbl.h * @brief CMSIS ARMv8MBL Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ -/* CMSIS cmGrebe definitions */ -#define __ARMv8MBL_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __ARMv8MBL_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#include "cmsis_version.h" + +/* 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) | \ - __ARMv8MBL_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __ARMv8MBL_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M ( 2U) /*!< Cortex-M Core */ diff --git a/3rd_party/CMSIS/Include/core_armv8mml.h b/3rd_party/CMSIS/Include/core_armv8mml.h index 286322f7..80f41527 100644 --- a/3rd_party/CMSIS/Include/core_armv8mml.h +++ b/3rd_party/CMSIS/Include/core_armv8mml.h @@ -2,7 +2,7 @@ * @file core_armv8mml.h * @brief CMSIS ARMv8MML Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS ARMv8MML definitions */ -#define __ARMv8MML_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __ARMv8MML_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#define __ARMv8MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main 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) | \ - __ARMv8MML_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __ARMv8MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (81U) /*!< Cortex-M Core */ @@ -480,7 +482,7 @@ typedef struct uint32_t RESERVED4[15U]; __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 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]; __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ uint32_t RESERVED6[1U]; diff --git a/3rd_party/CMSIS/Include/core_cm0.h b/3rd_party/CMSIS/Include/core_cm0.h index f1fbbe9c..27fdbcfe 100644 --- a/3rd_party/CMSIS/Include/core_cm0.h +++ b/3rd_party/CMSIS/Include/core_cm0.h @@ -2,7 +2,7 @@ * @file core_cm0.h * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS CM0 definitions */ -#define __CM0_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __CM0_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main 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) | \ - __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __CM0_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (0U) /*!< Cortex-M Core */ diff --git a/3rd_party/CMSIS/Include/core_cm0plus.h b/3rd_party/CMSIS/Include/core_cm0plus.h index 2dca31a3..4fbaa918 100644 --- a/3rd_party/CMSIS/Include/core_cm0plus.h +++ b/3rd_party/CMSIS/Include/core_cm0plus.h @@ -2,7 +2,7 @@ * @file core_cm0plus.h * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS CM0+ definitions */ -#define __CM0PLUS_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __CM0PLUS_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0PLUS_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main 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) | \ - __CM0PLUS_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __CM0PLUS_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (0U) /*!< Cortex-M Core */ @@ -932,6 +934,13 @@ __STATIC_INLINE void __NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif /* ########################## FPU functions #################################### */ /** diff --git a/3rd_party/CMSIS/Include/core_cm23.h b/3rd_party/CMSIS/Include/core_cm23.h index 378c69be..b97fa9dd 100644 --- a/3rd_party/CMSIS/Include/core_cm23.h +++ b/3rd_party/CMSIS/Include/core_cm23.h @@ -2,7 +2,7 @@ * @file core_cm23.h * @brief CMSIS Cortex-M23 Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ -/* CMSIS cmGrebe definitions */ -#define __CM23_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __CM23_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#include "cmsis_version.h" + +/* 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) | \ - __CM23_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __CM23_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (23U) /*!< Cortex-M Core */ diff --git a/3rd_party/CMSIS/Include/core_cm3.h b/3rd_party/CMSIS/Include/core_cm3.h index cfeb58be..2f4295f1 100644 --- a/3rd_party/CMSIS/Include/core_cm3.h +++ b/3rd_party/CMSIS/Include/core_cm3.h @@ -2,7 +2,7 @@ * @file core_cm3.h * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS CM3 definitions */ -#define __CM3_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __CM3_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main 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) | \ - __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __CM3_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (3U) /*!< Cortex-M Core */ @@ -1761,6 +1763,13 @@ __STATIC_INLINE void __NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif /* ########################## FPU functions #################################### */ /** diff --git a/3rd_party/CMSIS/Include/core_cm33.h b/3rd_party/CMSIS/Include/core_cm33.h index 9e880ae7..dee3d65b 100644 --- a/3rd_party/CMSIS/Include/core_cm33.h +++ b/3rd_party/CMSIS/Include/core_cm33.h @@ -2,7 +2,7 @@ * @file core_cm33.h * @brief CMSIS Cortex-M33 Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS CM33 definitions */ -#define __CM33_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __CM33_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#define __CM33_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main 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) | \ - __CM33_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __CM33_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (33U) /*!< Cortex-M Core */ @@ -480,7 +482,7 @@ typedef struct uint32_t RESERVED4[15U]; __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 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]; __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ uint32_t RESERVED6[1U]; diff --git a/3rd_party/CMSIS/Include/core_cm4.h b/3rd_party/CMSIS/Include/core_cm4.h index bdaedcf9..28df20ad 100644 --- a/3rd_party/CMSIS/Include/core_cm4.h +++ b/3rd_party/CMSIS/Include/core_cm4.h @@ -2,7 +2,7 @@ * @file core_cm4.h * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ -/* CMSIS CM4 definitions */ -#define __CM4_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __CM4_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#include "cmsis_version.h" + +/* 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) | \ - __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (4U) /*!< Cortex-M Core */ @@ -1935,6 +1937,14 @@ __STATIC_INLINE void __NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + /* ########################## FPU functions #################################### */ /** diff --git a/3rd_party/CMSIS/Include/core_cm7.h b/3rd_party/CMSIS/Include/core_cm7.h index fee3d0c9..bf701fe8 100644 --- a/3rd_party/CMSIS/Include/core_cm7.h +++ b/3rd_party/CMSIS/Include/core_cm7.h @@ -2,7 +2,7 @@ * @file core_cm7.h * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS CM7 definitions */ -#define __CM7_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __CM7_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main 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) | \ - __CM7_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_M (7U) /*!< Cortex-M Core */ @@ -482,7 +484,7 @@ typedef struct uint32_t RESERVED4[15U]; __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 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]; __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ uint32_t RESERVED6[1U]; @@ -2143,6 +2145,13 @@ __STATIC_INLINE void __NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif /* ########################## FPU functions #################################### */ /** diff --git a/3rd_party/CMSIS/Include/core_sc000.h b/3rd_party/CMSIS/Include/core_sc000.h index 53dfaadd..bd26eaa0 100644 --- a/3rd_party/CMSIS/Include/core_sc000.h +++ b/3rd_party/CMSIS/Include/core_sc000.h @@ -2,7 +2,7 @@ * @file core_sc000.h * @brief CMSIS SC000 Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS SC000 definitions */ -#define __SC000_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __SC000_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#define __SC000_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main 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) | \ - __SC000_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __SC000_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_SC (000U) /*!< Cortex secure core */ diff --git a/3rd_party/CMSIS/Include/core_sc300.h b/3rd_party/CMSIS/Include/core_sc300.h index 78450e0f..780372a3 100644 --- a/3rd_party/CMSIS/Include/core_sc300.h +++ b/3rd_party/CMSIS/Include/core_sc300.h @@ -2,7 +2,7 @@ * @file core_sc300.h * @brief CMSIS SC300 Core Peripheral Access Layer Header File * @version V5.0.2 - * @date 13. February 2017 + * @date 19. April 2017 ******************************************************************************/ /* * Copyright (c) 2009-2017 ARM Limited. All rights reserved. @@ -60,11 +60,13 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS SC300 definitions */ -#define __SC300_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS HAL main version */ -#define __SC300_CMSIS_VERSION_SUB ( 0U) /*!< [15:0] CMSIS HAL sub version */ +#define __SC300_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main 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) | \ - __SC300_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + __SC300_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ #define __CORTEX_SC (300U) /*!< Cortex secure core */ diff --git a/3rd_party/CMSIS/Include/mpu_armv7.h b/3rd_party/CMSIS/Include/mpu_armv7.h new file mode 100644 index 00000000..8710b5c3 --- /dev/null +++ b/3rd_party/CMSIS/Include/mpu_armv7.h @@ -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 diff --git a/3rd_party/CMSIS/LICENSE.txt b/3rd_party/CMSIS/LICENSE.txt index 8dada3ed..c0ee8129 100644 --- a/3rd_party/CMSIS/LICENSE.txt +++ b/3rd_party/CMSIS/LICENSE.txt @@ -1,201 +1,201 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - 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 - - http://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. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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 + + http://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. diff --git a/3rd_party/CMSIS/README.txt b/3rd_party/CMSIS/README.txt index 9410a1b2..a4e6e77a 100644 --- a/3rd_party/CMSIS/README.txt +++ b/3rd_party/CMSIS/README.txt @@ -1,7 +1,7 @@ About CMSIS =========== 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 software projects and reduces time-to-market for new embedded applications. diff --git a/3rd_party/efm32pg1b/gnu/startup_efm32pg1b.c b/3rd_party/efm32pg1b/gnu/startup_efm32pg1b.c index 0b422f0f..bc2792f0 100644 --- a/3rd_party/efm32pg1b/gnu/startup_efm32pg1b.c +++ b/3rd_party/efm32pg1b/gnu/startup_efm32pg1b.c @@ -42,7 +42,7 @@ ---------------------------------------------------------------------------*/ /* start and end of stack defined in the linker script ---------------------*/ -extern int __stack_start__; +/*extern int __stack_start__;*/ extern int __stack_end__; /* Weak prototypes for error handlers --------------------------------------*/ diff --git a/3rd_party/ek-lm3s6965/gnu/startup_LM3S6965.c b/3rd_party/ek-lm3s6965/gnu/startup_LM3S6965.c index c625f530..05510a33 100644 --- a/3rd_party/ek-lm3s6965/gnu/startup_LM3S6965.c +++ b/3rd_party/ek-lm3s6965/gnu/startup_LM3S6965.c @@ -42,7 +42,7 @@ ---------------------------------------------------------------------------*/ /* start and end of stack defined in the linker script ---------------------*/ -extern int __stack_start__; +/*extern int __stack_start__;*/ extern int __stack_end__; /* Weak prototypes for error handlers --------------------------------------*/ diff --git a/3rd_party/ek-tm4c123gxl/gnu/startup_TM4C123GH6PM.c b/3rd_party/ek-tm4c123gxl/gnu/startup_TM4C123GH6PM.c index 9e002ef0..cedcc132 100644 --- a/3rd_party/ek-tm4c123gxl/gnu/startup_TM4C123GH6PM.c +++ b/3rd_party/ek-tm4c123gxl/gnu/startup_TM4C123GH6PM.c @@ -42,7 +42,7 @@ ---------------------------------------------------------------------------*/ /* start and end of stack defined in the linker script ---------------------*/ -extern int __stack_start__; +/*extern int __stack_start__;*/ extern int __stack_end__; /* Weak prototypes for error handlers --------------------------------------*/ diff --git a/3rd_party/mbed-lpc1768/gnu/startup_LPC17xx.c b/3rd_party/mbed-lpc1768/gnu/startup_LPC17xx.c index 3209b2e6..710eff89 100644 --- a/3rd_party/mbed-lpc1768/gnu/startup_LPC17xx.c +++ b/3rd_party/mbed-lpc1768/gnu/startup_LPC17xx.c @@ -41,7 +41,7 @@ ---------------------------------------------------------------------------*/ /* start and end of stack defined in the linker script ---------------------*/ -extern int __stack_start__; +/*extern int __stack_start__;*/ extern int __stack_end__; /* Weak prototypes for error handlers --------------------------------------*/ diff --git a/3rd_party/nucleo-l053r8/gnu/startup_stm32l053xx.c b/3rd_party/nucleo-l053r8/gnu/startup_stm32l053xx.c index b2543ea0..6f1e66e5 100644 --- a/3rd_party/nucleo-l053r8/gnu/startup_stm32l053xx.c +++ b/3rd_party/nucleo-l053r8/gnu/startup_stm32l053xx.c @@ -42,7 +42,7 @@ ---------------------------------------------------------------------------*/ /* start and end of stack defined in the linker script ---------------------*/ -extern int __stack_start__; +/*extern int __stack_start__;*/ extern int __stack_end__; /* Weak prototypes for error handlers --------------------------------------*/ diff --git a/3rd_party/nucleo-l152re/gnu/startup_stm32l1xx.c b/3rd_party/nucleo-l152re/gnu/startup_stm32l1xx.c index b7e737ed..a4c5822f 100644 --- a/3rd_party/nucleo-l152re/gnu/startup_stm32l1xx.c +++ b/3rd_party/nucleo-l152re/gnu/startup_stm32l1xx.c @@ -42,7 +42,7 @@ ---------------------------------------------------------------------------*/ /* start and end of stack defined in the linker script ---------------------*/ -extern int __stack_start__; +/*extern int __stack_start__;*/ extern int __stack_end__; /* Weak prototypes for error handlers --------------------------------------*/ diff --git a/3rd_party/stm32f4-discovery/gnu/startup_stm32f4xx.c b/3rd_party/stm32f4-discovery/gnu/startup_stm32f4xx.c index 3277a4c8..1d11693a 100644 --- a/3rd_party/stm32f4-discovery/gnu/startup_stm32f4xx.c +++ b/3rd_party/stm32f4-discovery/gnu/startup_stm32f4xx.c @@ -42,7 +42,7 @@ ---------------------------------------------------------------------------*/ /* start and end of stack defined in the linker script ---------------------*/ -extern int __stack_start__; +/*extern int __stack_start__;*/ extern int __stack_end__; /* Weak prototypes for error handlers --------------------------------------*/ diff --git a/3rd_party/stm32f7-discovery/gnu/startup_stm32f746xx.c b/3rd_party/stm32f7-discovery/gnu/startup_stm32f746xx.c index 9c935f75..1317ce04 100644 --- a/3rd_party/stm32f7-discovery/gnu/startup_stm32f746xx.c +++ b/3rd_party/stm32f7-discovery/gnu/startup_stm32f746xx.c @@ -42,7 +42,7 @@ ---------------------------------------------------------------------------*/ /* start and end of stack defined in the linker script ---------------------*/ -extern int __stack_start__; +/*extern int __stack_start__;*/ extern int __stack_end__; /* Weak prototypes for error handlers --------------------------------------*/ diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile index a36ac59c..afa9d841 100644 --- a/doxygen/Doxyfile +++ b/doxygen/Doxyfile @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "QP/C++" -PROJECT_NUMBER = "5.9.6" +PROJECT_NUMBER = "5.9.7" PROJECT_BRIEF = PROJECT_LOGO = images/header_logo_ql.png OUTPUT_DIRECTORY = @@ -71,13 +71,13 @@ HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = NO -HIDE_SCOPE_NAMES = NO +HIDE_SCOPE_NAMES = YES HIDE_COMPOUND_REFERENCE= NO SHOW_INCLUDE_FILES = YES SHOW_GROUPED_MEMB_INC = NO FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES -SORT_MEMBER_DOCS = YES +SORT_MEMBER_DOCS = NO SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO @@ -112,6 +112,7 @@ INPUT = \ main.dox \ gs.dox \ struct.dox \ + api.dox \ exa.dox \ exa_apps.dox \ exa_native.dox \ diff --git a/doxygen/Doxyfile-CHM b/doxygen/Doxyfile-CHM index bdb505f9..19d80e97 100644 --- a/doxygen/Doxyfile-CHM +++ b/doxygen/Doxyfile-CHM @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "QP/C++" -PROJECT_NUMBER = "5.9.6" +PROJECT_NUMBER = "5.9.7" PROJECT_BRIEF = PROJECT_LOGO = images/header_logo_ql.png OUTPUT_DIRECTORY = @@ -71,13 +71,13 @@ HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = NO -HIDE_SCOPE_NAMES = NO +HIDE_SCOPE_NAMES = YES HIDE_COMPOUND_REFERENCE= NO SHOW_INCLUDE_FILES = YES SHOW_GROUPED_MEMB_INC = NO FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES -SORT_MEMBER_DOCS = YES +SORT_MEMBER_DOCS = NO SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO @@ -112,6 +112,7 @@ INPUT = \ main.dox \ gs.dox \ struct.dox \ + api.dox \ exa.dox \ exa_apps.dox \ exa_native.dox \ diff --git a/doxygen/api.dox b/doxygen/api.dox new file mode 100644 index 00000000..eb7b6064 --- /dev/null +++ b/doxygen/api.dox @@ -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. + +
+@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. + +
+@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() + +
+@subsection api_qf_ps Publish-Subscribe +- ::QSubscrList (Subscriber List struct) +- QF::psInit() +- %QF:: PUBLISH() +- QActive::subscribe() +- QActive::unsubscribe() +- QActive::unsubscribeAll() + +
+@subsection api_qf_evt Dynamic Events +- QEvt class +- Q_NEW() +- Q_NEW_X() +- Q_NEW_REF() +- Q_DELETE_REF() +- QF::gc() + +
+@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() + +
+@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() + +
+@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. + +
+@subsection api_qs_ini QS Initialization and Control +- QS_INIT() +- QS::initBuf() +- QS::getByte() +- QS::getBlock() +- QS::onStartup() +- QS::onCleanup() +- QS::onFlush() +- QS::onGetTime() + +
+@subsection api_qs_rx QS Receive-Channel (QS-RX) +- QS::rxInitBuf() +- QS::rxPut() +- QS::rxParse() +- QS::onCommand() + +
+@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() + +
+@subsection api_qs_dict QS Dictionaries +- QS_SIG_DICTIONARY() +- QS_OBJ_DICTIONARY() +- QS_FUN_DICTIONARY() +- QS_USR_DICTIONARY() + +
+@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. + +
+@subsection api_qv_init Kernel Initialization and Control +- QV_INIT() +- QF_run() +- 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. + + +
+@subsection api_qk_ctrl Kernel Initialization and Control +- QK_INIT() +- QF_run() +- QK::onIdle() +- QK_schedLock() +- QK_schedUnlock() +- QK::getVersion() + + +
+@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. + + +
+@subsection api_qxk_ctrl Kernel Initialization and Control +- QXK_INIT() +- QF_run() +- QXK::onIdle() +- QXK_schedLock() +- QXK_schedUnlock() +- QXK::getVersion() + + +
+@subsection api_qxk_isr Interrupt Management +- QXK_ISR_ENTRY() +- QXK_ISR_EXIT() + + +
+@subsection api_qxk_xthr Extended Thread Management +- QXThread class +- QXThread::QXThread() +- QXThread::start() +- QXThread::postX() +- QXThread::delay() +- QXThread::delayCancel() +- QXThread::queueGet() +- Q_XTHREAD_CAST() + + +
+@subsection api_qxk_sema Semaphores +- QXSemaphore class (Semaphore Control Block) +- QXSemaphore::init() +- QXSemaphore::wait() +- QXSemaphore::tryWait() +- QXSemaphore::signal() + + +
+@subsection api_qxk_mutex Mutexes +- QXMutex class (Mutex Control Block) +- QXMutex::init() +- QXMutex::lock() +- QXMutex::tryLock() +- QXMutex::unlock() + + +
+@subsection api_qxk_queue Message Queues +- QXThread::postX() - posting messages to blocking threads +- QXThread::queueGet() - waiting (blocking) on message queue + + +
+@subsection api_qxk_mem Memory Pools +- QMPool class +- QMPool::init() +- QMPool::get() +- QMPool::put() + + +
+@subsection api_qxk_tls Thread-Local Storage +- QXK_current() +- QXK_TLS() + +*/ + +} // namespace QP diff --git a/doxygen/history.dox b/doxygen/history.dox index a7ac588c..b2b625f3 100644 --- a/doxygen/history.dox +++ b/doxygen/history.dox @@ -2,6 +2,34 @@ namespace QP { /** @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": +- feature#129 "Allow blocking while holding a mutex in QXK"; and +- feature#130 "Allow QXK mutex locks to nest while acquired by the same thread"; and +- feature#131 "Add a non-blocking "tryLock()" operation to the QXK mutex". + +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 The main focus of this release are improvements to the "dual-mode" QXK kernel. Specifically, this release implements the featrue request #128 "QP Semaphore Max Value Setting" 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). diff --git a/doxygen/images/car_mud.jpg b/doxygen/images/car_mud.jpg new file mode 100644 index 00000000..ed18484f Binary files /dev/null and b/doxygen/images/car_mud.jpg differ diff --git a/doxygen/main.dox b/doxygen/main.dox index bea0d736..f2a4aa47 100644 --- a/doxygen/main.dox +++ b/doxygen/main.dox @@ -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 hierarchical state machines (UML statecharts). 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 QM™ modeling tool. +@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 cars without an infrastructure of roads. +
@subsection kernels Built-in Kernels diff --git a/doxygen/make.bat b/doxygen/make.bat index 886ae62a..f0bb59b5 100644 --- a/doxygen/make.bat +++ b/doxygen/make.bat @@ -1,8 +1,8 @@ @echo off :: ========================================================================== :: Product: QP/C++ script for generating Doxygen documentation -:: Last Updated for Version: 5.9.6 -:: Date of the Last Update: 2017-08-01 +:: Last Updated for Version: 5.9.7 +:: Date of the Last Update: 2017-08-18 :: :: Q u a n t u m L e a P s :: --------------------------- @@ -38,7 +38,7 @@ echo usage: echo make echo make -CHM -set VERSION=5.9.6 +set VERSION=5.9.7 :: Generate Resource Standard Metrics for QP/C++ ............................. set DOXHOME="C:\tools\doxygen\bin" diff --git a/doxygen/metrics.dox b/doxygen/metrics.dox index cb9e0984..6c4ade06 100644 --- a/doxygen/metrics.dox +++ b/doxygen/metrics.dox @@ -1,7 +1,7 @@ /** @page metrics Code Metrics @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 Version 7.75 - mSquaredTechnologies.com @@ -9,7 +9,7 @@ License Type: Windows Single User License Licensed To : Quantum Leaps, LLC License No. : WS2975 License Date: Dec 15, 2013 - Build Date : Sep 2 2009 Run Date: Aug 04, 2017 + Build Date : Sep 2 2009 Run Date: Aug 21, 2017 (C)1996-2009 M Squared Technologies LLC ________________________________________________________________________ @@ -154,7 +154,7 @@ ~~ 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 ~~ @@ -187,6 +187,11 @@ Complexity Param 0 Return 1 Cyclo Vg 1 Total 2 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 Parameters: (void) Complexity Param 0 Return 1 Cyclo Vg 1 Total 2 @@ -196,17 +201,17 @@ ~~ 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 Function Count....: 2 - Total Function LOC.....: 6 Total Function Pts LOC : 0.0 - Total Function eLOC....: 4 Total Function Pts eLOC: 0.0 - Total Function lLOC....: 2 Total Function Pts lLOC: 0.0 - Total Function Params .: 0 Total Function Return .: 2 - Total Cyclo Complexity : 2 Total Function Complex.: 4 + File Function Count....: 3 + Total Function LOC.....: 9 Total Function Pts LOC : 0.0 + Total Function eLOC....: 6 Total Function Pts eLOC: 0.0 + Total Function lLOC....: 3 Total Function Pts lLOC: 0.0 + Total Function Params .: 0 Total Function Return .: 3 + Total Cyclo Complexity : 3 Total Function Complex.: 6 ------ ----- ----- ------ ------ ----- Max Function LOC ......: 3 Average Function LOC ..: 3.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 Compiler Directive 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 Parameters: (QActive * const act, QTimeEvtCtr const nTicks) @@ -296,7 +301,7 @@ ~~ 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 ~~ @@ -333,7 +338,7 @@ ~~ 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 ~~ @@ -576,7 +581,7 @@ ~~ 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 ~~ @@ -660,7 +665,7 @@ ~~ 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 ~~ @@ -704,7 +709,7 @@ ~~ 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 ~~ @@ -1763,7 +1768,7 @@ Function Base : 1 Loops for / foreach : 1 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 Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t @@ -1774,7 +1779,7 @@ Conditional if / else if: 1 Logical and ( && ) : 3 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 Parameters: (void) @@ -1782,7 +1787,24 @@ Function Base : 1 Conditional if / else if: 1 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_ Parameters: (void) @@ -1797,27 +1819,27 @@ ~~ 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 Function Count....: 7 - Total Function LOC.....: 125 Total Function Pts LOC : 3.1 - Total Function eLOC....: 106 Total Function Pts eLOC: 2.6 - Total Function lLOC....: 62 Total Function Pts lLOC: 1.3 - Total Function Params .: 6 Total Function Return .: 7 - Total Cyclo Complexity : 20 Total Function Complex.: 33 + File Function Count....: 9 + Total Function LOC.....: 171 Total Function Pts LOC : 4.0 + Total Function eLOC....: 146 Total Function Pts eLOC: 3.4 + Total Function lLOC....: 84 Total Function Pts lLOC: 1.7 + Total Function Params .: 8 Total Function Return .: 9 + Total Cyclo Complexity : 26 Total Function Complex.: 43 ------ ----- ----- ------ ------ ----- - Max Function LOC ......: 62 Average Function LOC ..: 17.86 - Max Function eLOC .....: 54 Average Function eLOC .: 15.14 - Max Function lLOC .....: 28 Average Function lLOC .: 8.86 + Max Function LOC ......: 62 Average Function LOC ..: 19.00 + Max Function eLOC .....: 54 Average Function eLOC .: 16.22 + 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 Interface Complex. : 7 Avg Interface Complex. : 1.86 - Max Cyclomatic Complex.: 7 Avg Cyclomatic Complex.: 2.86 - Max Total Complexity ..: 12 Avg Total Complexity ..: 4.71 + Max Interface Complex. : 7 Avg Interface Complex. : 1.89 + Max Cyclomatic Complex.: 7 Avg Cyclomatic Complex.: 2.89 + Max Total Complexity ..: 12 Avg Total Complexity ..: 4.78 ________________________________________________________________________ End of File: ..\src\qk\qk.cpp @@ -1825,55 +1847,9 @@ 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 ~~ - LOC 62 eLOC 54 lLOC 19 Comment 114 Lines 174 - ------------------------------------------------------------------------ - - ~~ 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 + LOC 0 eLOC 0 lLOC 0 Comment 38 Lines 38 ________________________________________________________________________ End of File: ..\src\qk\qk_mutex.cpp @@ -1889,7 +1865,7 @@ Function: QP::QF::init Parameters: (void) 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 Parameters: (void) @@ -1910,7 +1886,7 @@ Function Base : 1 Loops for / foreach : 1 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 Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t @@ -1921,16 +1897,33 @@ Conditional if / else if: 1 Logical and ( && ) : 4 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 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 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 - Complexity Param 0 Return 1 Cyclo Vg 3 Total 4 - LOC 12 eLOC 10 lLOC 6 Comment 14 Lines 15 + Complexity Param 1 Return 1 Cyclo Vg 4 Total 6 + LOC 23 eLOC 20 lLOC 10 Comment 29 Lines 34 Function: static_cast Parameters: (0)) @@ -1947,7 +1940,7 @@ Loops while / do : 1 Conditional if / else if: 6 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 Parameters: (void) @@ -1955,33 +1948,33 @@ Function Base : 1 Conditional if / else if: 1 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 ~~ - LOC 240 eLOC 203 lLOC 103 Comment 232 Lines 455 + LOC 291 eLOC 248 lLOC 127 Comment 290 Lines 567 ------------------------------------------------------------------------ ~~ File Functional Summary ~~ - File Function Count....: 10 - Total Function LOC.....: 184 Total Function Pts LOC : 4.5 - Total Function eLOC....: 156 Total Function Pts eLOC: 3.8 - Total Function lLOC....: 88 Total Function Pts lLOC: 1.9 - Total Function Params .: 7 Total Function Return .: 10 - Total Cyclo Complexity : 29 Total Function Complex.: 46 + File Function Count....: 12 + Total Function LOC.....: 235 Total Function Pts LOC : 5.5 + Total Function eLOC....: 201 Total Function Pts eLOC: 4.7 + Total Function lLOC....: 112 Total Function Pts lLOC: 2.4 + Total Function Params .: 9 Total Function Return .: 12 + Total Cyclo Complexity : 35 Total Function Complex.: 56 ------ ----- ----- ------ ------ ----- - Max Function LOC ......: 78 Average Function LOC ..: 18.40 - Max Function eLOC .....: 68 Average Function eLOC .: 15.60 - Max Function lLOC .....: 34 Average Function lLOC .: 8.80 + Max Function LOC ......: 79 Average Function LOC ..: 19.58 + Max Function eLOC .....: 69 Average Function eLOC .: 16.75 + 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 Interface Complex. : 7 Avg Interface Complex. : 1.70 - Max Cyclomatic Complex.: 8 Avg Cyclomatic Complex.: 2.90 - Max Total Complexity ..: 13 Avg Total Complexity ..: 4.60 + Max Interface Complex. : 7 Avg Interface Complex. : 1.75 + Max Cyclomatic Complex.: 8 Avg Cyclomatic Complex.: 2.92 + Max Total Complexity ..: 13 Avg Total Complexity ..: 4.67 ________________________________________________________________________ End of File: ..\src\qxk\qxk.cpp @@ -1990,54 +1983,65 @@ ________________________________________________________________________ Function: QP::QXMutex::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 + Parameters: (uint_fast8_t ceiling) + Cyclomatic Complexity Vg Detail + 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 + 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) Cyclomatic Complexity Vg Detail Function Base : 1 - Conditional if / else if: 1 - Inlined if-else ( ? : ) : 1 - Logical and ( && ) : 1 - Complexity Param 0 Return 1 Cyclo Vg 4 Total 5 - LOC 22 eLOC 20 lLOC 9 Comment 28 Lines 29 + Conditional if / else if: 3 + Logical and ( && ) : 4 + Complexity Param 0 Return 1 Cyclo Vg 8 Total 9 + LOC 39 eLOC 34 lLOC 19 Comment 41 Lines 59 Function: QP::QXMutex::unlock Parameters: (void) Cyclomatic Complexity Vg Detail Function Base : 1 - Conditional if / else if: 3 - Logical and ( && ) : 1 - Complexity Param 0 Return 1 Cyclo Vg 5 Total 6 - LOC 44 eLOC 38 lLOC 17 Comment 36 Lines 53 + Conditional if / else if: 4 + Logical and ( && ) : 8 + Complexity Param 0 Return 1 Cyclo Vg 13 Total 14 + LOC 56 eLOC 49 lLOC 25 Comment 57 Lines 95 ------------------------------------------------------------------------ ~~ 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 Function Count....: 3 - Total Function LOC.....: 70 Total Function Pts LOC : 1.7 - Total Function eLOC....: 61 Total Function Pts eLOC: 1.5 - Total Function lLOC....: 28 Total Function Pts lLOC: 0.5 - Total Function Params .: 1 Total Function Return .: 3 - Total Cyclo Complexity : 10 Total Function Complex.: 14 + File Function Count....: 4 + Total Function LOC.....: 152 Total Function Pts LOC : 3.2 + Total Function eLOC....: 135 Total Function Pts eLOC: 2.8 + Total Function lLOC....: 78 Total Function Pts lLOC: 1.5 + Total Function Params .: 2 Total Function Return .: 4 + Total Cyclo Complexity : 31 Total Function Complex.: 37 ------ ----- ----- ------ ------ ----- - Max Function LOC ......: 44 Average Function LOC ..: 23.33 - Max Function eLOC .....: 38 Average Function eLOC .: 20.33 - Max Function lLOC .....: 17 Average Function lLOC .: 9.33 + Max Function LOC ......: 56 Average Function LOC ..: 38.00 + Max Function eLOC .....: 49 Average Function eLOC .: 33.75 + 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 Interface Complex. : 2 Avg Interface Complex. : 1.33 - Max Cyclomatic Complex.: 5 Avg Cyclomatic Complex.: 3.33 - Max Total Complexity ..: 6 Avg Total Complexity ..: 4.67 + Max Interface Complex. : 2 Avg Interface Complex. : 1.50 + Max Cyclomatic Complex.: 13 Avg Cyclomatic Complex.: 7.75 + Max Total Complexity ..: 14 Avg Total Complexity ..: 9.25 ________________________________________________________________________ End of File: ..\src\qxk\qxk_mutex.cpp @@ -2051,13 +2055,21 @@ LOC 6 eLOC 4 lLOC 4 Comment 18 Lines 7 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 Function Base : 1 Conditional if / else if: 1 Logical and ( && ) : 3 - Complexity Param 2 Return 1 Cyclo Vg 5 Total 8 - LOC 28 eLOC 24 lLOC 17 Comment 38 Lines 41 + Complexity Param 1 Return 1 Cyclo Vg 5 Total 7 + 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 Parameters: (void) @@ -2066,33 +2078,33 @@ Conditional if / else if: 3 Logical and ( && ) : 2 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 ~~ - LOC 81 eLOC 68 lLOC 34 Comment 129 Lines 207 + LOC 95 eLOC 80 lLOC 43 Comment 144 Lines 240 ------------------------------------------------------------------------ ~~ File Functional Summary ~~ - File Function Count....: 3 - Total Function LOC.....: 62 Total Function Pts LOC : 1.5 - Total Function eLOC....: 50 Total Function Pts eLOC: 1.3 - Total Function lLOC....: 34 Total Function Pts lLOC: 0.6 - Total Function Params .: 4 Total Function Return .: 3 - Total Cyclo Complexity : 12 Total Function Complex.: 19 + File Function Count....: 4 + Total Function LOC.....: 78 Total Function Pts LOC : 1.8 + Total Function eLOC....: 64 Total Function Pts eLOC: 1.5 + Total Function lLOC....: 43 Total Function Pts lLOC: 0.8 + Total Function Params .: 3 Total Function Return .: 4 + Total Cyclo Complexity : 14 Total Function Complex.: 21 ------ ----- ----- ------ ------ ----- - Max Function LOC ......: 28 Average Function LOC ..: 20.67 - Max Function eLOC .....: 24 Average Function eLOC .: 16.67 - Max Function lLOC .....: 17 Average Function lLOC .: 11.33 + Max Function LOC ......: 29 Average Function LOC ..: 19.50 + Max Function eLOC .....: 25 Average Function eLOC .: 16.00 + 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 Interface Complex. : 3 Avg Interface Complex. : 2.33 - Max Cyclomatic Complex.: 6 Avg Cyclomatic Complex.: 4.00 - Max Total Complexity ..: 8 Avg Total Complexity ..: 6.33 + Max Interface Complex. : 3 Avg Interface Complex. : 1.75 + Max Cyclomatic Complex.: 6 Avg Cyclomatic Complex.: 3.50 + Max Total Complexity ..: 7 Avg Total Complexity ..: 5.25 ________________________________________________________________________ End of File: ..\src\qxk\qxk_sema.cpp @@ -2124,7 +2136,7 @@ Conditional if / else if: 1 Logical and ( && ) : 4 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_ Parameters: (QEvt const * const e, uint_fast16_t const margin) @@ -2132,7 +2144,7 @@ Function Base : 1 Conditional if / else if: 9 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 Parameters: (QEvt const * const) @@ -2140,13 +2152,13 @@ LOC 3 eLOC 2 lLOC 1 Comment 9 Lines 3 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 Function Base : 1 Conditional if / else if: 4 Logical and ( && ) : 3 - Complexity Param 2 Return 1 Cyclo Vg 8 Total 11 - LOC 61 eLOC 53 lLOC 34 Comment 55 Lines 88 + Complexity Param 1 Return 1 Cyclo Vg 8 Total 10 + LOC 61 eLOC 54 lLOC 34 Comment 53 Lines 88 Function: QP::QXThread::block_ Parameters: (void) @@ -2163,13 +2175,12 @@ LOC 8 eLOC 5 lLOC 2 Comment 9 Lines 9 Function: QP::QXThread::teArm_ - Parameters: (enum_t const sig, uint_fast16_t const nTicks, uint_fast8_t - const tickRate) + Parameters: (enum_t const sig, uint_fast16_t const nTicks) Cyclomatic Complexity Vg Detail Function Base : 1 Conditional if / else if: 2 - Complexity Param 3 Return 1 Cyclo Vg 3 Total 7 - LOC 16 eLOC 11 lLOC 7 Comment 21 Lines 32 + Complexity Param 2 Return 1 Cyclo Vg 3 Total 6 + LOC 18 eLOC 14 lLOC 8 Comment 20 Lines 33 Function: QP::QXThread::teDisarm_ Parameters: (void) @@ -2180,12 +2191,12 @@ LOC 11 eLOC 8 lLOC 5 Comment 10 Lines 14 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 Function Base : 1 Logical and ( && ) : 3 - Complexity Param 2 Return 1 Cyclo Vg 4 Total 7 - LOC 20 eLOC 18 lLOC 13 Comment 17 Lines 35 + Complexity Param 1 Return 1 Cyclo Vg 4 Total 6 + LOC 20 eLOC 19 lLOC 13 Comment 17 Lines 34 Function: QP::QXThread::delayCancel Parameters: (void) @@ -2199,27 +2210,27 @@ ~~ 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 Function Count....: 13 - Total Function LOC.....: 246 Total Function Pts LOC : 5.5 - Total Function eLOC....: 198 Total Function Pts eLOC: 4.6 - Total Function lLOC....: 129 Total Function Pts lLOC: 2.6 - Total Function Params .: 20 Total Function Return .: 13 - Total Cyclo Complexity : 43 Total Function Complex.: 76 + Total Function LOC.....: 249 Total Function Pts LOC : 5.5 + Total Function eLOC....: 204 Total Function Pts eLOC: 4.6 + Total Function lLOC....: 131 Total Function Pts lLOC: 2.6 + Total Function Params .: 17 Total Function Return .: 13 + Total Cyclo Complexity : 43 Total Function Complex.: 73 ------ ----- ----- ------ ------ ----- - Max Function LOC ......: 79 Average Function LOC ..: 18.92 - Max Function eLOC .....: 64 Average Function eLOC .: 15.23 - Max Function lLOC .....: 44 Average Function lLOC .: 9.92 + Max Function LOC ......: 79 Average Function LOC ..: 19.15 + Max Function eLOC .....: 64 Average Function eLOC .: 15.69 + 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 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 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 @@ -2232,9 +2243,9 @@ ~~ 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 - 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 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 Parameters: (void) 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 Compiler Directive 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 Parameters: (QActive * const act, QTimeEvtCtr const nTicks) @@ -2941,40 +2957,35 @@ Function: QP::QF::run Parameters: (void) 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 Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t const qLen, void * const stkSto, uint_fast16_t const, QEvt c onst * const ie) 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 Parameters: (void) 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_ Parameters: (void) Complexity Param 0 Return 1 Cyclo Vg 7 Total 8 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 Parameters: () Complexity Param 0 Return 1 Cyclo Vg 1 Total 2 @@ -2983,7 +2994,7 @@ Function: QP::QF::init Parameters: (void) 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 Parameters: (void) @@ -2998,19 +3009,29 @@ Function: QP::QF::run Parameters: (void) 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 Parameters: (uint_fast8_t const prio, QEvt const *qSto[], uint_fast16_t const qLen, void * const stkSto, uint_fast16_t const stkSize , QEvt const * const ie) 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 Parameters: (void) - Complexity Param 0 Return 1 Cyclo Vg 3 Total 4 - LOC 12 eLOC 10 lLOC 6 Comment 14 Lines 15 + 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) + 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 Parameters: (0)) @@ -3020,27 +3041,32 @@ Function: QXK_activate_ Parameters: (void) 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 Parameters: (void) 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 - 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 + Parameters: (uint_fast8_t ceiling) + Complexity Param 1 Return 1 Cyclo Vg 3 Total 5 + LOC 12 eLOC 11 lLOC 7 Comment 20 Lines 22 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) - Complexity Param 0 Return 1 Cyclo Vg 4 Total 5 - LOC 22 eLOC 20 lLOC 9 Comment 28 Lines 29 + Complexity Param 0 Return 1 Cyclo Vg 8 Total 9 + LOC 39 eLOC 34 lLOC 19 Comment 41 Lines 59 Function: QP::QXMutex::unlock Parameters: (void) - Complexity Param 0 Return 1 Cyclo Vg 5 Total 6 - LOC 44 eLOC 38 lLOC 17 Comment 36 Lines 53 + Complexity Param 0 Return 1 Cyclo Vg 13 Total 14 + LOC 56 eLOC 49 lLOC 25 Comment 57 Lines 95 Function: QP::QXSemaphore::init 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 Function: QP::QXSemaphore::wait - Parameters: (uint_fast16_t const nTicks, uint_fast8_t const tickRate) - Complexity Param 2 Return 1 Cyclo Vg 5 Total 8 - LOC 28 eLOC 24 lLOC 17 Comment 38 Lines 41 + Parameters: (uint_fast16_t const nTicks) + Complexity Param 1 Return 1 Cyclo Vg 5 Total 7 + 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 Parameters: (void) 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 Parameters: (QXThreadHandler const handler, uint_fast8_t const tickRate) @@ -3077,12 +3108,12 @@ const qLen, void * const stkSto, uint_fast16_t const stkSize , QEvt const * const) 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_ Parameters: (QEvt const * const e, uint_fast16_t const margin) 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 Parameters: (QEvt const * const) @@ -3090,9 +3121,9 @@ LOC 3 eLOC 2 lLOC 1 Comment 9 Lines 3 Function: QP::QXThread::queueGet - Parameters: (uint_fast16_t const nTicks, uint_fast8_t const tickRate) - Complexity Param 2 Return 1 Cyclo Vg 8 Total 11 - LOC 61 eLOC 53 lLOC 34 Comment 55 Lines 88 + Parameters: (uint_fast16_t const nTicks) + Complexity Param 1 Return 1 Cyclo Vg 8 Total 10 + LOC 61 eLOC 54 lLOC 34 Comment 53 Lines 88 Function: QP::QXThread::block_ Parameters: (void) @@ -3105,10 +3136,9 @@ LOC 8 eLOC 5 lLOC 2 Comment 9 Lines 9 Function: QP::QXThread::teArm_ - Parameters: (enum_t const sig, uint_fast16_t const nTicks, uint_fast8_t - const tickRate) - Complexity Param 3 Return 1 Cyclo Vg 3 Total 7 - LOC 16 eLOC 11 lLOC 7 Comment 21 Lines 32 + Parameters: (enum_t const sig, uint_fast16_t const nTicks) + Complexity Param 2 Return 1 Cyclo Vg 3 Total 6 + LOC 18 eLOC 14 lLOC 8 Comment 20 Lines 33 Function: QP::QXThread::teDisarm_ Parameters: (void) @@ -3116,9 +3146,9 @@ LOC 11 eLOC 8 lLOC 5 Comment 10 Lines 14 Function: QP::QXThread::delay - Parameters: (uint_fast16_t const nTicks, uint_fast8_t const tickRate) - Complexity Param 2 Return 1 Cyclo Vg 4 Total 7 - LOC 20 eLOC 18 lLOC 13 Comment 17 Lines 35 + Parameters: (uint_fast16_t const nTicks) + Complexity Param 1 Return 1 Cyclo Vg 4 Total 6 + LOC 20 eLOC 19 lLOC 13 Comment 17 Lines 34 Function: QP::QXThread::delayCancel Parameters: (void) @@ -3126,26 +3156,26 @@ LOC 14 eLOC 11 lLOC 7 Comment 2 Lines 16 Total: Functions - LOC 2584 eLOC 2142 lLOC 1274 InCmp 340 CycloCmp 439 - Function Points FP(LOC) 43.8 FP(eLOC) 36.8 FP(lLOC) 22.2 + LOC 2741 eLOC 2285 lLOC 1364 InCmp 344 CycloCmp 466 + Function Points FP(LOC) 46.7 FP(eLOC) 39.5 FP(lLOC) 23.8 ------------------------------------------------------------------------ ~~ Project Functional Analysis ~~ - Total Functions .......: 173 Total Physical Lines ..: 3511 - Total LOC .............: 2584 Total Function Pts LOC : 43.8 - Total eLOC ............: 2142 Total Function Pts eLOC: 36.8 - Total lLOC.............: 1274 Total Function Pts lLOC: 22.2 - Total Cyclomatic Comp. : 439 Total Interface Comp. .: 340 - Total Parameters ......: 167 Total Return Points ...: 173 - Total Comment Lines ...: 2516 Total Blank Lines .....: 465 + Total Functions .......: 177 Total Physical Lines ..: 3793 + Total LOC .............: 2741 Total Function Pts LOC : 46.7 + Total eLOC ............: 2285 Total Function Pts eLOC: 39.5 + Total lLOC.............: 1364 Total Function Pts lLOC: 23.8 + Total Cyclomatic Comp. : 466 Total Interface Comp. .: 344 + Total Parameters ......: 167 Total Return Points ...: 177 + Total Comment Lines ...: 2682 Total Blank Lines .....: 513 ------ ----- ----- ------ ------ ----- - Avg Physical Lines ....: 20.29 - Avg LOC ...............: 14.94 Avg eLOC ..............: 12.38 - Avg lLOC ..............: 7.36 Avg Cyclomatic Comp. ..: 2.54 - Avg Interface Comp. ...: 1.97 Avg Parameters ........: 0.97 - Avg Return Points .....: 1.00 Avg Comment Lines .....: 14.54 + Avg Physical Lines ....: 21.43 + Avg LOC ...............: 15.49 Avg eLOC ..............: 12.91 + Avg lLOC ..............: 7.71 Avg Cyclomatic Comp. ..: 2.63 + Avg Interface Comp. ...: 1.94 Avg Parameters ........: 0.94 + Avg Return Points .....: 1.00 Avg Comment Lines .....: 15.15 ------ ----- ----- ------ ------ ----- Max LOC ...............: 117 Max eLOC ..............: 100 Max lLOC ..............: 61 diff --git a/doxygen/snippets/qf_xctor.cpp b/doxygen/snippets/qf_xctor.cpp new file mode 100644 index 00000000..7f7cd11a --- /dev/null +++ b/doxygen/snippets/qf_xctor.cpp @@ -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 \ No newline at end of file diff --git a/doxygen/snippets/qf_xstart.cpp b/doxygen/snippets/qf_xstart.cpp new file mode 100644 index 00000000..1a8e5575 --- /dev/null +++ b/doxygen/snippets/qf_xstart.cpp @@ -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(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(0)); // initialization event + . . . +} diff --git a/examples/arm-cm/blinky_efm32-slstk3401a/qv/arm/blinky-qv.uvoptx b/examples/arm-cm/blinky_efm32-slstk3401a/qv/arm/blinky-qv.uvoptx index b747aa3a..91ea2ae1 100644 --- a/examples/arm-cm/blinky_efm32-slstk3401a/qv/arm/blinky-qv.uvoptx +++ b/examples/arm-cm/blinky_efm32-slstk3401a/qv/arm/blinky-qv.uvoptx @@ -100,6 +100,7 @@ 1 0 0 + 1 3 @@ -199,9 +200,16 @@ 0 - - - 0 + 0 + 0 + + + + + + + + @@ -284,6 +292,7 @@ 1 0 0 + 1 3 @@ -383,9 +392,16 @@ 0 - - - 0 + 0 + 0 + + + + + + + + @@ -468,6 +484,7 @@ 1 0 0 + 1 3 @@ -579,9 +596,16 @@ 0 - - - 0 + 0 + 0 + + + + + + + + diff --git a/examples/arm-cm/blinky_efm32-slstk3401a/qv/arm/blinky-qv.uvprojx b/examples/arm-cm/blinky_efm32-slstk3401a/qv/arm/blinky-qv.uvprojx index 21efb6b3..4b67df4b 100644 --- a/examples/arm-cm/blinky_efm32-slstk3401a/qv/arm/blinky-qv.uvprojx +++ b/examples/arm-cm/blinky_efm32-slstk3401a/qv/arm/blinky-qv.uvprojx @@ -10,7 +10,8 @@ blinky-dbg 0x4 ARM-ADS - 5060183::V5.06 update 2 (build 183)::ARMCC + 5060528::V5.06 update 5 (build 528)::ARMCC + 0 EFM32PG1B200F256GM48 @@ -330,6 +331,7 @@ 0 0 0 + 0 EFM32PG1B200F256GM48=1 __FPU_PRESENT @@ -347,6 +349,7 @@ 0 1 0 + 0 Stack_Size=1024 Heap_Size=16 @@ -566,6 +569,7 @@ 0 0 0 + 2 @@ -583,6 +587,7 @@ 2 2 2 + 2 @@ -621,7 +626,8 @@ blinky-rel 0x4 ARM-ADS - 5060183::V5.06 update 2 (build 183)::ARMCC + 5060528::V5.06 update 5 (build 528)::ARMCC + 0 EFM32PG1B200F256GM48 @@ -941,11 +947,12 @@ 0 0 0 + 0 NDEBUG EFM32PG1B200F256GM48=1 __FPU_PRESENT - ..\..;..\..\..\..\..\include;..\..\..\..\..\src\qf;..\..\..\..\..\ports\arm-cm\qv\arm;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b + ..\..;..\..\..\..\..\include;..\..\..\..\..\src;..\..\..\..\..\ports\arm-cm\qv\arm;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b @@ -958,6 +965,7 @@ 0 1 0 + 0 Stack_Size=1024 Heap_Size=16 @@ -1177,6 +1185,7 @@ 0 0 0 + 2 @@ -1194,6 +1203,7 @@ 2 2 2 + 2 @@ -1232,7 +1242,8 @@ blinky-spy 0x4 ARM-ADS - 5060183::V5.06 update 2 (build 183)::ARMCC + 5060528::V5.06 update 5 (build 528)::ARMCC + 0 EFM32PG1B200F256GM48 @@ -1552,11 +1563,12 @@ 0 0 0 + 0 Q_SPY EFM32PG1B200F256GM48=1 __FPU_PRESENT - ..\..;..\..\..\..\..\include;..\..\..\..\..\src\qf;..\..\..\..\..\ports\arm-cm\qv\arm;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b + ..\..;..\..\..\..\..\include;..\..\..\..\..\src;..\..\..\..\..\ports\arm-cm\qv\arm;..\..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\..\3rd_party\efm32pg1b @@ -1569,6 +1581,7 @@ 0 1 0 + 0 Stack_Size=1024 Heap_Size=16 @@ -1775,4 +1788,10 @@ + + + + + + diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qk/bsp.cpp b/examples/arm-cm/dpp_efm32-slstk3401a/qk/bsp.cpp index 57296812..865e3b62 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qk/bsp.cpp +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, EFM32-SLSTK3401A board, preemptive QK kernel -// Last Updated for Version: 5.9.5 -// Date of the Last Update: 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-18 // // 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 static uint32_t l_rnd; // random seed -static QP::QMutex l_rndMutex; // to protect the random number generator #ifdef Q_SPY @@ -265,20 +264,19 @@ uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { l_rnd = seed; - l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority } //............................................................................ diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewd b/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewd index 3e40dff6..dddf0adc 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewd +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewd @@ -1,4741 +1,4213 @@ - - + - 2 - - Debug - - ARM - - 1 - - C-SPY - 2 - - 28 - 1 + 3 + + Debug + + ARM + 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ARMSIM_ID - 2 - - 1 - 1 - 1 - - - - - - - - ANGEL_ID - 2 - - 0 - 1 - 1 - - - - - - - - - - - - CMSISDAP_ID - 2 - - 4 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GDBSERVER_ID - 2 - - 0 - 1 - 1 - - - - - - - - - - - IARROM_ID - 2 - - 1 - 1 - 1 - - - - - - - - - IJET_ID - 2 - - 8 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JLINK_ID - 2 - - 16 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LMIFTDI_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - MACRAIGOR_ID - 2 - - 3 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - PEMICRO_ID - 2 - - 3 - 1 - 1 - - - - - - - - RDI_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - - - - - - - STLINK_ID - 2 - - 3 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - THIRDPARTY_ID - 2 - - 0 - 1 - 1 - - - - - - - - TIFET_ID - 2 - - 1 - 1 - 1 - - - - - - - - - - - - - - - - - - - XDS100_ID - 2 - - 5 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $TOOLKIT_DIR$\plugins\middleware\HCCWare\HCCWare.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\middleware\PercepioTraceExporter\PercepioTraceExportPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\AVIX\AVIX.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\MQX\MQXRtosPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\Quadros\Quadros_EWB7_Plugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin - 0 - - - $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin - 1 - - - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin - 0 - - - $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin - 0 - - - - - Release - - ARM - - 0 - - C-SPY - 2 - - 28 - 1 + + C-SPY + 2 + + 28 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 1 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 1 + + + + + + + + STLINK_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 6 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + Release + + ARM + 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ARMSIM_ID - 2 - - 1 - 1 - 0 - - - - - - - - ANGEL_ID - 2 - - 0 - 1 - 0 - - - - - - - - - - - - CMSISDAP_ID - 2 - - 4 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GDBSERVER_ID - 2 - - 0 - 1 - 0 - - - - - - - - - - - IARROM_ID - 2 - - 1 - 1 - 0 - - - - - - - - - IJET_ID - 2 - - 8 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JLINK_ID - 2 - - 16 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LMIFTDI_ID - 2 - - 2 - 1 - 0 - - - - - - - - - - MACRAIGOR_ID - 2 - - 3 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - PEMICRO_ID - 2 - - 3 - 1 - 0 - - - - - - - - RDI_ID - 2 - - 2 - 1 - 0 - - - - - - - - - - - - - - - - STLINK_ID - 2 - - 3 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - THIRDPARTY_ID - 2 - - 0 - 1 - 0 - - - - - - - - TIFET_ID - 2 - - 1 - 1 - 0 - - - - - - - - - - - - - - - - - - - XDS100_ID - 2 - - 5 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $TOOLKIT_DIR$\plugins\middleware\HCCWare\HCCWare.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\middleware\PercepioTraceExporter\PercepioTraceExportPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\AVIX\AVIX.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\MQX\MQXRtosPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\Quadros\Quadros_EWB7_Plugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin - 0 - - - $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin - 1 - - - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin - 0 - - - $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin - 0 - - - - - Spy - - ARM - - 1 - - C-SPY - 2 - - 28 - 1 + + C-SPY + 2 + + 28 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 0 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 0 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 0 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 0 + + + + + + + + STLINK_ID + 2 + + 4 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 0 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 6 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + Spy + + ARM + 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ARMSIM_ID - 2 - - 1 - 1 - 1 - - - - - - - - ANGEL_ID - 2 - - 0 - 1 - 1 - - - - - - - - - - - - CMSISDAP_ID - 2 - - 4 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GDBSERVER_ID - 2 - - 0 - 1 - 1 - - - - - - - - - - - IARROM_ID - 2 - - 1 - 1 - 1 - - - - - - - - - IJET_ID - 2 - - 8 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JLINK_ID - 2 - - 16 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LMIFTDI_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - MACRAIGOR_ID - 2 - - 3 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - PEMICRO_ID - 2 - - 3 - 1 - 1 - - - - - - - - RDI_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - - - - - - - STLINK_ID - 2 - - 3 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - THIRDPARTY_ID - 2 - - 0 - 1 - 1 - - - - - - - - TIFET_ID - 2 - - 1 - 1 - 1 - - - - - - - - - - - - - - - - - - - XDS100_ID - 2 - - 5 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $TOOLKIT_DIR$\plugins\middleware\HCCWare\HCCWare.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\middleware\PercepioTraceExporter\PercepioTraceExportPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\AVIX\AVIX.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\MQX\MQXRtosPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\Quadros\Quadros_EWB7_Plugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin - 0 - - - $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin - 1 - - - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin - 0 - - - $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin - 0 - - - + + C-SPY + 2 + + 28 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 1 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 1 + + + + + + + + STLINK_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 6 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + - - diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewp b/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewp index de24af15..b3d0efdf 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewp +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewp @@ -1,3040 +1,3190 @@ - - + - 2 - - Debug - - ARM - - 1 - - General - 3 - - 24 - 1 + 3 + + Debug + + ARM + 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 31 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 1 - - - - - - - - - CUSTOM - 3 - - - - 0 - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" - - - - - ILINK - 0 - - 17 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 1 - - - - - - - BILINK - 0 - - - - Coder - 0 - - - - - Release - - ARM - - 0 - - General - 3 - - 24 - 1 + + General + 3 + + 28 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" + + + + + ILINK + 0 + + 20 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + Coder + 0 + + + + + Release + + ARM + 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 31 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 0 - - - - - - - - - CUSTOM - 3 - - - - 0 - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" - - - - - ILINK - 0 - - 17 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 0 - - - - - - - BILINK - 0 - - - - Coder - 0 - - - - - Spy - - ARM - - 1 - - General - 3 - - 24 - 1 + + General + 3 + + 28 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" + + + + + ILINK + 0 + + 20 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + BILINK + 0 + + + + Coder + 0 + + + + + Spy + + ARM + 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 31 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 1 - - - - - - - - - CUSTOM - 3 - - - - 0 - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" - - - - - ILINK - 0 - - 17 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 1 - - - - - - - BILINK - 0 - - - - Coder - 0 - - - - - Application - - $PROJ_DIR$\..\bsp.cpp - - - $PROJ_DIR$\..\..\bsp.h - - - $PROJ_DIR$\..\..\dpp.h - - - $PROJ_DIR$\..\main.cpp - - - $PROJ_DIR$\..\..\philo.cpp - - - $PROJ_DIR$\..\..\..\..\..\include\qstamp.cpp - - - $PROJ_DIR$\..\..\table.cpp - - - - efm32pg1b - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_cmu.c - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_emu.c - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_gpio.c - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_usart.c - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\iar\startup_efm32pg1b.s - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c - - - - QP - - $PROJ_DIR$\..\..\..\..\..\src\qf\qep_hsm.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qep_msm.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_act.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_actq.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_defer.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_dyn.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_mem.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf_pkg.h - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_ps.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qact.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qeq.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qmact.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_time.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qk\qk.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qk\qk_mutex.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qk_pkg.h - - - - QP_port - - $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.s - - - - QS - - Debug - Release - - - $PROJ_DIR$\..\..\..\..\..\src\qs\qs.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qs\qs_fp.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qs_pkg.h - - - $PROJ_DIR$\..\..\..\..\..\src\qs\qs_rx.cpp - - + + General + 3 + + 28 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" + + + + + ILINK + 0 + + 20 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + Coder + 0 + + + + + Application + + $PROJ_DIR$\..\bsp.cpp + + + $PROJ_DIR$\..\..\bsp.h + + + $PROJ_DIR$\..\..\dpp.h + + + $PROJ_DIR$\..\main.cpp + + + $PROJ_DIR$\..\..\philo.cpp + + + $PROJ_DIR$\..\..\..\..\..\include\qstamp.cpp + + + $PROJ_DIR$\..\..\table.cpp + + + + efm32pg1b + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_cmu.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_emu.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_gpio.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_usart.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\iar\startup_efm32pg1b.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c + + + + QP + + $PROJ_DIR$\..\..\..\..\..\src\qf\qep_hsm.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qep_msm.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_act.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_actq.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_defer.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_dyn.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_mem.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf_pkg.h + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_ps.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qact.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qeq.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qmact.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_time.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qk\qk.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qk\qk_mutex.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qk_pkg.h + + + + QP_port + + $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.s + + + + QS + + Debug + Release + + + $PROJ_DIR$\..\..\..\..\..\src\qs\qs.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qs\qs_fp.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qs_pkg.h + + + $PROJ_DIR$\..\..\..\..\..\src\qs\qs_rx.cpp + + - - diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/bsp.cpp b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/bsp.cpp index 0b44dbe6..d5c51645 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/bsp.cpp +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, EFM32-SLSTK3401A board, preemptive QXK kernel -// Last Updated for Version: 5.9.5 -// Date of the Last Update: 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-19 // // 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 static uint32_t l_rnd; // random seed -static QP::QXMutex l_rndMutex; // to protect the random number generator #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 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 PHILO_STAT = QP::QS_USER, PAUSED_STAT, @@ -262,19 +256,18 @@ uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { - l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority l_rnd = seed; } //............................................................................ @@ -301,7 +294,7 @@ void QF::onStartup(void) { // set up the SysTick timer to fire at BSP::TICKS_PER_SEC rate 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); // set priorities of ALL ISRs used in the system, see NOTE00 diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/main.cpp b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/main.cpp index 10bc5189..c40b97f5 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/main.cpp +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/main.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.8.3 -// Last updated on 2017-03-13 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // 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[4]); - QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe + // init publish-subscribe + QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // initialize event pools... QP::QF::poolInit(smlPoolSto, @@ -79,32 +80,39 @@ int main() { sizeof(test1StackSto), // stack size [bytes] static_cast(0)); // initialization event + // NOTE: leave priority 2 free for a mutex + // start the Philo active objects... for (uint8_t n = 0U; n < N_PHILO; ++n) { DPP::AO_Philo[n]->start( - static_cast(n + 2), // QP priority of the AO + static_cast(n + 3), // QP priority of the AO philoQueueSto[n], // event queue storage Q_DIM(philoQueueSto[n]), // queue length [events] static_cast(0), // no stack storage static_cast(0), // stack size [bytes] static_cast(0)); // initialization event } + // 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); + // NOTE: leave priority (N_PHILO + 4) free for mutex + // start the extended Test2 thread DPP::XT_Test2->start( - static_cast(N_PHILO + 3), // QP prio of the thread + static_cast(N_PHILO + 5), // QP prio of the thread test2QueueSto, // event queue storage Q_DIM(test2QueueSto), // queue length [events] test2StackSto, // stack storage sizeof(test2StackSto), // stack size [bytes] static_cast(0)); // initialization event + // NOTE: leave priority (N_PHILO + 6) free for mutex + DPP::AO_Table->start( - static_cast(N_PHILO + 4), // QP priority of the AO + static_cast(N_PHILO + 7), // QP priority of the AO tableQueueSto, // event queue storage Q_DIM(tableQueueSto), // queue length [events] static_cast(0), // no stack storage diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/test.cpp b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/test.cpp index 144a3157..45d00f8f 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/test.cpp +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/test.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.9.6 -// Last updated on 2017-07-27 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // 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 - l_mutex.init(3U); - for (;;) { - - // wait on a semaphore (BLOCK with timeout) - (void)l_sema.wait(BSP::TICKS_PER_SEC, 0U); + l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex BSP::ledOn(); - l_mutex.lock(); // exercise the mutex - // some flating point code to exercise the VFP... - float volatile x = 1.4142135F; - x = x * 1.4142135F; - //QP::QXThread::delay(1U, 0U); // asserts (blocking while holding a mutex) - l_mutex.unlock(); + if (l_mutex.tryLock()) { // exercise the mutex + float volatile x; - 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 - 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); @@ -95,34 +100,31 @@ static void Thread1_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 */ 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 (;;) { - // some flating point code to exercise the VFP... - float volatile x = 1.4142135F; - x = x * 1.4142135F; + // wait on a semaphore (BLOCK indefinitely) + l_sema.wait(); - // wait on the internal event queue (BLOCK) with timeout - QP::QEvt const *e = me->queueGet(BSP::TICKS_PER_SEC/2, 0U); - BSP::ledOff(); - - if (e != static_cast(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 - } + l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex + QP::QXThread::delay(1U); // wait more (BLOCK) + l_mutex.unlock(); // test TLS lib_fun(2U); diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/bsp.h b/examples/arm-cm/dpp_ek-tm4c123gxl/bsp.h index 2825d2c2..17165127 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/bsp.h +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/bsp.h @@ -1,7 +1,7 @@ //**************************************************************************** // Product: DPP example -// Last Updated for Version: 5.6.0 -// Date of the Last Update: 2015-12-28 +// Last Updated for Version: 5.8.1 +// Date of the Last Update: 2016-12-12 // // 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 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... static void wait4SW1(void); @@ -54,6 +54,8 @@ public: static void ledOff(void); }; +extern QP::QActive *the_Ticker0; + } // namespace DPP #endif // bsp_h diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qk/bsp.cpp b/examples/arm-cm/dpp_ek-tm4c123gxl/qk/bsp.cpp index 152a24bc..74f0df13 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/qk/bsp.cpp +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, EK-TM4C123GXL board, preemptive QK kernel -// Last updated for version 5.9.5 -// Last updated on 2017-07-20 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // 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) static uint32_t l_rnd; // random seed -static QP::QMutex l_rndMutex; // to protect the random number generator #ifdef Q_SPY @@ -257,19 +256,19 @@ uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { - l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority l_rnd = seed; } //............................................................................ diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/bsp.cpp b/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/bsp.cpp index 96a0c59f..064518d7 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/bsp.cpp +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, EK-TM4C123GXL board, preemptive QXK kernel -// Last updated for version 5.9.5 -// Last updated on 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-19 // // 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) static uint32_t l_rnd; // random seed -static QP::QXMutex l_rndMutex; // to protect the random number generator #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 - // The flating point code is to exercise the FPU + // Some flating point code is to exercise the VFP... float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { - l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority l_rnd = seed; } //............................................................................ @@ -284,7 +282,7 @@ void QF::onStartup(void) { // set up the SysTick timer to fire at BSP::TICKS_PER_SEC rate 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); // set priorities of ALL ISRs used in the system, see NOTE00 diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/main.cpp b/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/main.cpp index 5226db61..c40b97f5 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/main.cpp +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/main.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.7.2 -// Last updated on 2016-09-28 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // Q u a n t u m L e a P s // --------------------------- @@ -35,6 +35,9 @@ #include "dpp.h" #include "bsp.h" +static QP::QTicker l_ticker0(0); // ticker for tick rate 0 +QP::QActive *DPP::the_Ticker0 = &l_ticker0; + //............................................................................ int main() { static QP::QEvt const *tableQueueSto[N_PHILO]; @@ -61,7 +64,8 @@ int main() { QS_OBJ_DICTIONARY(philoQueueSto[3]); 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... QP::QF::poolInit(smlPoolSto, @@ -76,10 +80,12 @@ int main() { sizeof(test1StackSto), // stack size [bytes] static_cast(0)); // initialization event + // NOTE: leave priority 2 free for a mutex + // start the Philo active objects... for (uint8_t n = 0U; n < N_PHILO; ++n) { DPP::AO_Philo[n]->start( - static_cast(n + 2), // QP priority of the AO + static_cast(n + 3), // QP priority of the AO philoQueueSto[n], // event queue storage Q_DIM(philoQueueSto[n]), // queue length [events] static_cast(0), // no stack storage @@ -87,17 +93,26 @@ int main() { static_cast(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 DPP::XT_Test2->start( - static_cast(N_PHILO + 2), // QP prio of the thread + static_cast(N_PHILO + 5), // QP prio of the thread test2QueueSto, // event queue storage Q_DIM(test2QueueSto), // queue length [events] test2StackSto, // stack storage sizeof(test2StackSto), // stack size [bytes] static_cast(0)); // initialization event + // NOTE: leave priority (N_PHILO + 6) free for mutex + DPP::AO_Table->start( - static_cast(N_PHILO + 3), // QP priority of the AO + static_cast(N_PHILO + 7), // QP priority of the AO tableQueueSto, // event queue storage Q_DIM(tableQueueSto), // queue length [events] static_cast(0), // no stack storage diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/test.cpp b/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/test.cpp index ba7cfb3d..45d00f8f 100644 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/test.cpp +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qxk/test.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.9.6 -// Last updated on 2017-07-27 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // 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_Test2 = &l_test2; -//............................................................................ -static void Thread1_run(QP::QXThread * const /*me*/) { +// Thread-Local Storage for the "extended" threads ........................... +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 (;;) { - - // wait on a semaphore (BLOCK with timeout) - (void)l_sema.wait(BSP::TICKS_PER_SEC, 0U); + l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex BSP::ledOn(); - l_mutex.lock(); // exercise the mutex - // some flating point code to exercise the VFP... - float volatile x = 1.4142135F; - x = x * 1.4142135F; - //QP::QXThread::delay(1U, 0U); // asserts (blocking while holding a mutex) - l_mutex.unlock(); + if (l_mutex.tryLock()) { // exercise the mutex + float volatile x; - 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 - 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) { + // 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 */ 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 (;;) { - // some flating point code to exercise the VFP... - float volatile x = 1.4142135F; - x = x * 1.4142135F; + // wait on a semaphore (BLOCK indefinitely) + l_sema.wait(); - // wait on the internal event queue (BLOCK) with timeout - QP::QEvt const *e = me->queueGet(BSP::TICKS_PER_SEC/2, 0U); - BSP::ledOff(); + l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex + QP::QXThread::delay(1U); // wait more (BLOCK) + l_mutex.unlock(); - if (e != static_cast(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 + lib_fun(2U); } } diff --git a/examples/arm-cm/dpp_nucleo-l053r8/bsp.h b/examples/arm-cm/dpp_nucleo-l053r8/bsp.h index 2825d2c2..17165127 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/bsp.h +++ b/examples/arm-cm/dpp_nucleo-l053r8/bsp.h @@ -1,7 +1,7 @@ //**************************************************************************** // Product: DPP example -// Last Updated for Version: 5.6.0 -// Date of the Last Update: 2015-12-28 +// Last Updated for Version: 5.8.1 +// Date of the Last Update: 2016-12-12 // // 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 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... static void wait4SW1(void); @@ -54,6 +54,8 @@ public: static void ledOff(void); }; +extern QP::QActive *the_Ticker0; + } // namespace DPP #endif // bsp_h diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qk/bsp.cpp b/examples/arm-cm/dpp_nucleo-l053r8/qk/bsp.cpp index 5c58de5b..5f03a614 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qk/bsp.cpp +++ b/examples/arm-cm/dpp_nucleo-l053r8/qk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, STM32 NUCLEO-L053R8 board, preemptive QK kernel -// Last updated for version 5.9.5 -// Last updated on 2016-07-20 +// Last updated for version 5.9.7 +// Last updated on 2016-08-20 // // 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) static unsigned l_rnd; // random seed -static QP::QMutex l_rndMutex; // to protect the random number generator #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 - 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { - l_rndMutex.init(N_PHILO + 1U); l_rnd = seed; } //............................................................................ diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qxk/bsp.cpp b/examples/arm-cm/dpp_nucleo-l053r8/qxk/bsp.cpp index d51bdf24..5717bf5e 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qxk/bsp.cpp +++ b/examples/arm-cm/dpp_nucleo-l053r8/qxk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, STM32 NUCLEO-L053R8 board, preemptive QXK kernel -// Last updated for version 5.9.5 -// Last updated on 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-19 // // 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) static unsigned l_rnd; // random seed -static QP::QXMutex l_rndMutex; // to protect the random number generator #ifdef Q_SPY @@ -111,7 +110,8 @@ void SysTick_Handler(void) { } #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 // 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 - 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { - l_rndMutex.init(N_PHILO + 1U); l_rnd = seed; } //............................................................................ diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qxk/main.cpp b/examples/arm-cm/dpp_nucleo-l053r8/qxk/main.cpp index 5226db61..c40b97f5 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qxk/main.cpp +++ b/examples/arm-cm/dpp_nucleo-l053r8/qxk/main.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.7.2 -// Last updated on 2016-09-28 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // Q u a n t u m L e a P s // --------------------------- @@ -35,6 +35,9 @@ #include "dpp.h" #include "bsp.h" +static QP::QTicker l_ticker0(0); // ticker for tick rate 0 +QP::QActive *DPP::the_Ticker0 = &l_ticker0; + //............................................................................ int main() { static QP::QEvt const *tableQueueSto[N_PHILO]; @@ -61,7 +64,8 @@ int main() { QS_OBJ_DICTIONARY(philoQueueSto[3]); 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... QP::QF::poolInit(smlPoolSto, @@ -76,10 +80,12 @@ int main() { sizeof(test1StackSto), // stack size [bytes] static_cast(0)); // initialization event + // NOTE: leave priority 2 free for a mutex + // start the Philo active objects... for (uint8_t n = 0U; n < N_PHILO; ++n) { DPP::AO_Philo[n]->start( - static_cast(n + 2), // QP priority of the AO + static_cast(n + 3), // QP priority of the AO philoQueueSto[n], // event queue storage Q_DIM(philoQueueSto[n]), // queue length [events] static_cast(0), // no stack storage @@ -87,17 +93,26 @@ int main() { static_cast(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 DPP::XT_Test2->start( - static_cast(N_PHILO + 2), // QP prio of the thread + static_cast(N_PHILO + 5), // QP prio of the thread test2QueueSto, // event queue storage Q_DIM(test2QueueSto), // queue length [events] test2StackSto, // stack storage sizeof(test2StackSto), // stack size [bytes] static_cast(0)); // initialization event + // NOTE: leave priority (N_PHILO + 6) free for mutex + DPP::AO_Table->start( - static_cast(N_PHILO + 3), // QP priority of the AO + static_cast(N_PHILO + 7), // QP priority of the AO tableQueueSto, // event queue storage Q_DIM(tableQueueSto), // queue length [events] static_cast(0), // no stack storage diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qxk/test.cpp b/examples/arm-cm/dpp_nucleo-l053r8/qxk/test.cpp index ba7cfb3d..45d00f8f 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qxk/test.cpp +++ b/examples/arm-cm/dpp_nucleo-l053r8/qxk/test.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.9.6 -// Last updated on 2017-07-27 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // 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_Test2 = &l_test2; -//............................................................................ -static void Thread1_run(QP::QXThread * const /*me*/) { +// Thread-Local Storage for the "extended" threads ........................... +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 (;;) { - - // wait on a semaphore (BLOCK with timeout) - (void)l_sema.wait(BSP::TICKS_PER_SEC, 0U); + l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex BSP::ledOn(); - l_mutex.lock(); // exercise the mutex - // some flating point code to exercise the VFP... - float volatile x = 1.4142135F; - x = x * 1.4142135F; - //QP::QXThread::delay(1U, 0U); // asserts (blocking while holding a mutex) - l_mutex.unlock(); + if (l_mutex.tryLock()) { // exercise the mutex + float volatile x; - 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 - 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) { + // 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 */ 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 (;;) { - // some flating point code to exercise the VFP... - float volatile x = 1.4142135F; - x = x * 1.4142135F; + // wait on a semaphore (BLOCK indefinitely) + l_sema.wait(); - // wait on the internal event queue (BLOCK) with timeout - QP::QEvt const *e = me->queueGet(BSP::TICKS_PER_SEC/2, 0U); - BSP::ledOff(); + l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex + QP::QXThread::delay(1U); // wait more (BLOCK) + l_mutex.unlock(); - if (e != static_cast(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 + lib_fun(2U); } } diff --git a/examples/arm-cm/dpp_stm32f4-discovery/qk/bsp.cpp b/examples/arm-cm/dpp_stm32f4-discovery/qk/bsp.cpp index 65a13681..564551c5 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/qk/bsp.cpp +++ b/examples/arm-cm/dpp_stm32f4-discovery/qk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, STM32F4-Discovery board, preemptive QK kernel -// Last Updated for Version: 5.9.5 -// Date of the Last Update: 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-20 // // 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 static uint32_t l_rnd; // random seed -static QP::QMutex l_rndMutex; // to protect the random number generator #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 - // Some flating point code is to exercise the VFP... + // The flating point code is to exercise the FPU float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { l_rnd = seed; - l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority } //............................................................................ diff --git a/examples/arm-cm/dpp_stm32f4-discovery/qxk/bsp.cpp b/examples/arm-cm/dpp_stm32f4-discovery/qxk/bsp.cpp index 8bfa5a77..e6843170 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/qxk/bsp.cpp +++ b/examples/arm-cm/dpp_stm32f4-discovery/qxk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, STM32F4-Discovery board, dual-mode QXK kernel -// Last Updated for Version: 5.9.5 -// Date of the Last Update: 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-19 // // 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 static uint32_t l_rnd; // random seed -static QP::QXMutex l_rndMutex; // to protect the random number generator #ifdef Q_SPY @@ -292,22 +291,20 @@ uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { l_rnd = seed; - l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority } - //............................................................................ void BSP::terminate(int16_t result) { (void)result; diff --git a/examples/arm-cm/dpp_stm32f4-discovery/qxk/main.cpp b/examples/arm-cm/dpp_stm32f4-discovery/qxk/main.cpp index 10bc5189..c40b97f5 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/qxk/main.cpp +++ b/examples/arm-cm/dpp_stm32f4-discovery/qxk/main.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.8.3 -// Last updated on 2017-03-13 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // 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[4]); - QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe + // init publish-subscribe + QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // initialize event pools... QP::QF::poolInit(smlPoolSto, @@ -79,32 +80,39 @@ int main() { sizeof(test1StackSto), // stack size [bytes] static_cast(0)); // initialization event + // NOTE: leave priority 2 free for a mutex + // start the Philo active objects... for (uint8_t n = 0U; n < N_PHILO; ++n) { DPP::AO_Philo[n]->start( - static_cast(n + 2), // QP priority of the AO + static_cast(n + 3), // QP priority of the AO philoQueueSto[n], // event queue storage Q_DIM(philoQueueSto[n]), // queue length [events] static_cast(0), // no stack storage static_cast(0), // stack size [bytes] static_cast(0)); // initialization event } + // 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); + // NOTE: leave priority (N_PHILO + 4) free for mutex + // start the extended Test2 thread DPP::XT_Test2->start( - static_cast(N_PHILO + 3), // QP prio of the thread + static_cast(N_PHILO + 5), // QP prio of the thread test2QueueSto, // event queue storage Q_DIM(test2QueueSto), // queue length [events] test2StackSto, // stack storage sizeof(test2StackSto), // stack size [bytes] static_cast(0)); // initialization event + // NOTE: leave priority (N_PHILO + 6) free for mutex + DPP::AO_Table->start( - static_cast(N_PHILO + 4), // QP priority of the AO + static_cast(N_PHILO + 7), // QP priority of the AO tableQueueSto, // event queue storage Q_DIM(tableQueueSto), // queue length [events] static_cast(0), // no stack storage diff --git a/examples/arm-cm/dpp_stm32f4-discovery/qxk/test.cpp b/examples/arm-cm/dpp_stm32f4-discovery/qxk/test.cpp index ba7cfb3d..45d00f8f 100644 --- a/examples/arm-cm/dpp_stm32f4-discovery/qxk/test.cpp +++ b/examples/arm-cm/dpp_stm32f4-discovery/qxk/test.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.9.6 -// Last updated on 2017-07-27 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // 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_Test2 = &l_test2; -//............................................................................ -static void Thread1_run(QP::QXThread * const /*me*/) { +// Thread-Local Storage for the "extended" threads ........................... +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 (;;) { - - // wait on a semaphore (BLOCK with timeout) - (void)l_sema.wait(BSP::TICKS_PER_SEC, 0U); + l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex BSP::ledOn(); - l_mutex.lock(); // exercise the mutex - // some flating point code to exercise the VFP... - float volatile x = 1.4142135F; - x = x * 1.4142135F; - //QP::QXThread::delay(1U, 0U); // asserts (blocking while holding a mutex) - l_mutex.unlock(); + if (l_mutex.tryLock()) { // exercise the mutex + float volatile x; - 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 - 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) { + // 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 */ 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 (;;) { - // some flating point code to exercise the VFP... - float volatile x = 1.4142135F; - x = x * 1.4142135F; + // wait on a semaphore (BLOCK indefinitely) + l_sema.wait(); - // wait on the internal event queue (BLOCK) with timeout - QP::QEvt const *e = me->queueGet(BSP::TICKS_PER_SEC/2, 0U); - BSP::ledOff(); + l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex + QP::QXThread::delay(1U); // wait more (BLOCK) + l_mutex.unlock(); - if (e != static_cast(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 + lib_fun(2U); } } diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/bsp.h b/examples/arm-cm/dpp_stm32f746g-discovery/bsp.h index 17165127..15f42a8a 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/bsp.h +++ b/examples/arm-cm/dpp_stm32f746g-discovery/bsp.h @@ -49,7 +49,6 @@ public: static uint32_t random(void); // pseudo-random generator // for testing... - static void wait4SW1(void); static void ledOn(void); static void ledOff(void); }; diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/qk/bsp.cpp b/examples/arm-cm/dpp_stm32f746g-discovery/qk/bsp.cpp index 7ba70010..7f9c171c 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/qk/bsp.cpp +++ b/examples/arm-cm/dpp_stm32f746g-discovery/qk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, STM32746G-Discovery board, preemptive QK kernel -// Last Updated for Version: 5.9.5 -// Date of the Last Update: 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-20 // // 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 ------------------------------------------------------- static uint32_t l_rnd; // random seed -static QP::QMutex l_rndMutex; // to protect the random number generator #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 - // Some flating point code is to exercise the VFP... + // The flating point code is to exercise the FPU float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { l_rnd = seed; - l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority } //............................................................................ diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/qxk/bsp.cpp b/examples/arm-cm/dpp_stm32f746g-discovery/qxk/bsp.cpp index adf3575c..817a3ed6 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/qxk/bsp.cpp +++ b/examples/arm-cm/dpp_stm32f746g-discovery/qxk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, STM32746G-Discovery board, dual-mode QXK kernel -// Last Updated for Version: 5.9.5 -// Date of the Last Update: 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-19 // // 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 ------------------------------------------------------- static uint32_t l_rnd; // random seed -static QP::QXMutex l_rndMutex; // to protect the random number generator #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 // Some flating point code is to exercise the VFP... float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { l_rnd = seed; - l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority } - //............................................................................ void BSP::terminate(int16_t result) { (void)result; diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/qxk/main.cpp b/examples/arm-cm/dpp_stm32f746g-discovery/qxk/main.cpp index 5226db61..c40b97f5 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/qxk/main.cpp +++ b/examples/arm-cm/dpp_stm32f746g-discovery/qxk/main.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.7.2 -// Last updated on 2016-09-28 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // Q u a n t u m L e a P s // --------------------------- @@ -35,6 +35,9 @@ #include "dpp.h" #include "bsp.h" +static QP::QTicker l_ticker0(0); // ticker for tick rate 0 +QP::QActive *DPP::the_Ticker0 = &l_ticker0; + //............................................................................ int main() { static QP::QEvt const *tableQueueSto[N_PHILO]; @@ -61,7 +64,8 @@ int main() { QS_OBJ_DICTIONARY(philoQueueSto[3]); 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... QP::QF::poolInit(smlPoolSto, @@ -76,10 +80,12 @@ int main() { sizeof(test1StackSto), // stack size [bytes] static_cast(0)); // initialization event + // NOTE: leave priority 2 free for a mutex + // start the Philo active objects... for (uint8_t n = 0U; n < N_PHILO; ++n) { DPP::AO_Philo[n]->start( - static_cast(n + 2), // QP priority of the AO + static_cast(n + 3), // QP priority of the AO philoQueueSto[n], // event queue storage Q_DIM(philoQueueSto[n]), // queue length [events] static_cast(0), // no stack storage @@ -87,17 +93,26 @@ int main() { static_cast(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 DPP::XT_Test2->start( - static_cast(N_PHILO + 2), // QP prio of the thread + static_cast(N_PHILO + 5), // QP prio of the thread test2QueueSto, // event queue storage Q_DIM(test2QueueSto), // queue length [events] test2StackSto, // stack storage sizeof(test2StackSto), // stack size [bytes] static_cast(0)); // initialization event + // NOTE: leave priority (N_PHILO + 6) free for mutex + DPP::AO_Table->start( - static_cast(N_PHILO + 3), // QP priority of the AO + static_cast(N_PHILO + 7), // QP priority of the AO tableQueueSto, // event queue storage Q_DIM(tableQueueSto), // queue length [events] static_cast(0), // no stack storage diff --git a/examples/arm-cm/dpp_stm32f746g-discovery/qxk/test.cpp b/examples/arm-cm/dpp_stm32f746g-discovery/qxk/test.cpp index ab32d4bb..45d00f8f 100644 --- a/examples/arm-cm/dpp_stm32f746g-discovery/qxk/test.cpp +++ b/examples/arm-cm/dpp_stm32f746g-discovery/qxk/test.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.9.6 -// Last updated on 2017-07-27 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // 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_Test2 = &l_test2; -//............................................................................ -static void Thread1_run(QP::QXThread * const /*me*/) { +// Thread-Local Storage for the "extended" threads ........................... +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 (;;) { + l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex + BSP::ledOn(); - // wait on a semaphore (BLOCK with timeout) - (void)l_sema.wait(BSP::TICKS_PER_SEC, 0U); - //BSP::ledOn(); + if (l_mutex.tryLock()) { // exercise the mutex + float volatile x; + // 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(); + BSP::ledOff(); - QP::QXThread::delay(BSP::TICKS_PER_SEC/7, 0U); // BLOCK + QP::QXThread::delay(BSP::TICKS_PER_SEC/7); // BLOCK // 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) { + // 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 */ 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 (;;) { - // some flating point code to exercise the VFP... - float volatile x = 1.4142135F; - x = x * 1.4142135F; + // wait on a semaphore (BLOCK indefinitely) + l_sema.wait(); - // wait on the internal event queue (BLOCK) with timeout - QP::QEvt const *e = me->queueGet(BSP::TICKS_PER_SEC/2, 0U); - //BSP::ledOff(); + l_mutex.lock(QXTHREAD_NO_TIMEOUT); // lock the mutex + QP::QXThread::delay(1U); // wait more (BLOCK) + l_mutex.unlock(); - if (e != static_cast(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 + lib_fun(2U); } } diff --git a/examples/arm-cm/game_efm32-slstk3401a/qk/bsp.cpp b/examples/arm-cm/game_efm32-slstk3401a/qk/bsp.cpp index 6300e19d..c499142c 100644 --- a/examples/arm-cm/game_efm32-slstk3401a/qk/bsp.cpp +++ b/examples/arm-cm/game_efm32-slstk3401a/qk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: "Fly 'n' Shoot" game example, EFM32-SLSTK3401A board, QK kernel -// Last Updated for Version: 5.9.5 -// Date of the Last Update: 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-20 // // 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 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 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 - // Some flating point code is to exercise the VFP... + // The flating point code is to exercise the FPU float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP_randomSeed(uint32_t 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) { diff --git a/examples/arm-cr/dpp_launchxl2-tms57012/qk/bsp.cpp b/examples/arm-cr/dpp_launchxl2-tms57012/qk/bsp.cpp index 9959f293..d396c2f0 100644 --- a/examples/arm-cr/dpp_launchxl2-tms57012/qk/bsp.cpp +++ b/examples/arm-cr/dpp_launchxl2-tms57012/qk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, LAUCHXL2-TMS570LS12 board, preemptive QK kernel -// Last Updated for Version: 5.9.5 -// Date of the Last Update: 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-20 // // Q u a n t u m L e a P s // --------------------------- @@ -69,7 +69,6 @@ namespace DPP { #define VIM_RAM ((t_isrFuncPTR *)0xFFF82000U) static uint32_t l_rnd; // random seed -static QP::QMutex l_rndMutex; // mutex to protect the random seed #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 - // Some flating point code is to exercise the VFP... + // The flating point code is to exercise the FPU float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { l_rnd = seed; - l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority } //............................................................................ diff --git a/examples/performance/dpp_efm32-slstk3401a/qk/bsp.cpp b/examples/performance/dpp_efm32-slstk3401a/qk/bsp.cpp index 146c7c30..76795f2d 100644 --- a/examples/performance/dpp_efm32-slstk3401a/qk/bsp.cpp +++ b/examples/performance/dpp_efm32-slstk3401a/qk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, EFM32-SLSTK3401A board, preemptive QK kernel -// Last Updated for Version: 5.9.5 -// Date of the Last Update: 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-20 // // 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 static uint32_t l_rnd; // random seed -static QP::QMutex l_rndMutex; // to protect the random number generator #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 - // Some flating point code is to exercise the VFP... + // The flating point code is to exercise the FPU float volatile x = 3.1415926F; 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) // LCG(2^32, 3*7*11*13*23, 0, seed) // uint32_t rnd = l_rnd * (3U*7U*11U*13U*23U); 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); } //............................................................................ void BSP::randomSeed(uint32_t seed) { l_rnd = seed; - l_rndMutex.init(N_PHILO); // ceiling <== maximum Philo priority } //............................................................................ diff --git a/examples/performance/dpp_efm32-slstk3401a/qxk/bsp.cpp b/examples/performance/dpp_efm32-slstk3401a/qxk/bsp.cpp index 92788d5e..9e97eeb9 100644 --- a/examples/performance/dpp_efm32-slstk3401a/qxk/bsp.cpp +++ b/examples/performance/dpp_efm32-slstk3401a/qxk/bsp.cpp @@ -1,7 +1,7 @@ ///*************************************************************************** // Product: DPP example, EFM32-SLSTK3401A board, preemptive QXK kernel -// Last Updated for Version: 5.9.5 -// Date of the Last Update: 2017-07-20 +// Last Updated for Version: 5.9.7 +// Date of the Last Update: 2017-08-20 // // Q u a n t u m L e a P s // --------------------------- diff --git a/examples/performance/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewd b/examples/performance/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewd index 3e40dff6..f6eedd1b 100644 --- a/examples/performance/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewd +++ b/examples/performance/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewd @@ -1,4741 +1,4213 @@ - - + - 2 - - Debug - - ARM - - 1 - - C-SPY - 2 - - 28 - 1 + 3 + + Debug + + ARM + 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ARMSIM_ID - 2 - - 1 - 1 - 1 - - - - - - - - ANGEL_ID - 2 - - 0 - 1 - 1 - - - - - - - - - - - - CMSISDAP_ID - 2 - - 4 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GDBSERVER_ID - 2 - - 0 - 1 - 1 - - - - - - - - - - - IARROM_ID - 2 - - 1 - 1 - 1 - - - - - - - - - IJET_ID - 2 - - 8 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JLINK_ID - 2 - - 16 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LMIFTDI_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - MACRAIGOR_ID - 2 - - 3 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - PEMICRO_ID - 2 - - 3 - 1 - 1 - - - - - - - - RDI_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - - - - - - - STLINK_ID - 2 - - 3 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - THIRDPARTY_ID - 2 - - 0 - 1 - 1 - - - - - - - - TIFET_ID - 2 - - 1 - 1 - 1 - - - - - - - - - - - - - - - - - - - XDS100_ID - 2 - - 5 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $TOOLKIT_DIR$\plugins\middleware\HCCWare\HCCWare.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\middleware\PercepioTraceExporter\PercepioTraceExportPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\AVIX\AVIX.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\MQX\MQXRtosPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\Quadros\Quadros_EWB7_Plugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin - 0 - - - $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin - 1 - - - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin - 0 - - - $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin - 0 - - - - - Release - - ARM - - 0 - - C-SPY - 2 - - 28 - 1 + + C-SPY + 2 + + 28 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 1 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 1 + + + + + + + + STLINK_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 6 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + Release + + ARM + 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ARMSIM_ID - 2 - - 1 - 1 - 0 - - - - - - - - ANGEL_ID - 2 - - 0 - 1 - 0 - - - - - - - - - - - - CMSISDAP_ID - 2 - - 4 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GDBSERVER_ID - 2 - - 0 - 1 - 0 - - - - - - - - - - - IARROM_ID - 2 - - 1 - 1 - 0 - - - - - - - - - IJET_ID - 2 - - 8 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JLINK_ID - 2 - - 16 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LMIFTDI_ID - 2 - - 2 - 1 - 0 - - - - - - - - - - MACRAIGOR_ID - 2 - - 3 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - PEMICRO_ID - 2 - - 3 - 1 - 0 - - - - - - - - RDI_ID - 2 - - 2 - 1 - 0 - - - - - - - - - - - - - - - - STLINK_ID - 2 - - 3 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - THIRDPARTY_ID - 2 - - 0 - 1 - 0 - - - - - - - - TIFET_ID - 2 - - 1 - 1 - 0 - - - - - - - - - - - - - - - - - - - XDS100_ID - 2 - - 5 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $TOOLKIT_DIR$\plugins\middleware\HCCWare\HCCWare.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\middleware\PercepioTraceExporter\PercepioTraceExportPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\AVIX\AVIX.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\MQX\MQXRtosPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\Quadros\Quadros_EWB7_Plugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin - 0 - - - $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin - 1 - - - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin - 0 - - - $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin - 0 - - - - - Spy - - ARM - - 1 - - C-SPY - 2 - - 28 - 1 + + C-SPY + 2 + + 28 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 0 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 0 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 0 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 0 + + + + + + + + STLINK_ID + 2 + + 4 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 0 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 6 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + Spy + + ARM + 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ARMSIM_ID - 2 - - 1 - 1 - 1 - - - - - - - - ANGEL_ID - 2 - - 0 - 1 - 1 - - - - - - - - - - - - CMSISDAP_ID - 2 - - 4 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GDBSERVER_ID - 2 - - 0 - 1 - 1 - - - - - - - - - - - IARROM_ID - 2 - - 1 - 1 - 1 - - - - - - - - - IJET_ID - 2 - - 8 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JLINK_ID - 2 - - 16 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LMIFTDI_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - MACRAIGOR_ID - 2 - - 3 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - PEMICRO_ID - 2 - - 3 - 1 - 1 - - - - - - - - RDI_ID - 2 - - 2 - 1 - 1 - - - - - - - - - - - - - - - - STLINK_ID - 2 - - 3 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - THIRDPARTY_ID - 2 - - 0 - 1 - 1 - - - - - - - - TIFET_ID - 2 - - 1 - 1 - 1 - - - - - - - - - - - - - - - - - - - XDS100_ID - 2 - - 5 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $TOOLKIT_DIR$\plugins\middleware\HCCWare\HCCWare.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\middleware\PercepioTraceExporter\PercepioTraceExportPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\AVIX\AVIX.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\MQX\MQXRtosPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\Quadros\Quadros_EWB7_Plugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin - 0 - - - $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin - 0 - - - $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin - 1 - - - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin - 0 - - - $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin - 0 - - - + + C-SPY + 2 + + 28 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + CADI_ID + 2 + + 0 + 1 + 1 + + + + + + + + + CMSISDAP_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IJET_ID + 2 + + 8 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + PEMICRO_ID + 2 + + 3 + 1 + 1 + + + + + + + + STLINK_ID + 2 + + 4 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + TIFET_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + XDS100_ID + 2 + + 6 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + - - diff --git a/examples/performance/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewp b/examples/performance/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewp index 7473b4d0..6bf0046a 100644 --- a/examples/performance/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewp +++ b/examples/performance/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewp @@ -1,3052 +1,3202 @@ - - + - 2 - - Debug - - ARM - - 1 - - General - 3 - - 24 - 1 + 3 + + Debug + + ARM + 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 31 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 1 - - - - - - - - - CUSTOM - 3 - - - - 0 - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" - - - - - ILINK - 0 - - 17 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 1 - - - - - - - BILINK - 0 - - - - Coder - 0 - - - - - Release - - ARM - - 0 - - General - 3 - - 24 - 1 + + General + 3 + + 28 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" + + + + + ILINK + 0 + + 20 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + Coder + 0 + + + + + Release + + ARM + 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 31 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 0 - - - - - - - - - CUSTOM - 3 - - - - 0 - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" - - - - - ILINK - 0 - - 17 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 0 - - - - - - - BILINK - 0 - - - - Coder - 0 - - - - - Spy - - ARM - - 1 - - General - 3 - - 24 - 1 + + General + 3 + + 28 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" + + + + + ILINK + 0 + + 20 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + BILINK + 0 + + + + Coder + 0 + + + + + Spy + + ARM + 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 31 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 1 - - - - - - - - - CUSTOM - 3 - - - - 0 - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" - - - - - ILINK - 0 - - 17 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 1 - - - - - - - BILINK - 0 - - - - Coder - 0 - - - - - Application - - $PROJ_DIR$\..\bsp.cpp - - - $PROJ_DIR$\..\..\bsp.h - - - $PROJ_DIR$\..\..\dpp.h - - - $PROJ_DIR$\..\main.cpp - - - $PROJ_DIR$\..\..\philo.cpp - - - $PROJ_DIR$\..\..\..\..\..\include\qstamp.cpp - - - $PROJ_DIR$\..\..\table.cpp - - - $PROJ_DIR$\..\test.cpp - - - $PROJ_DIR$\..\test.h - - - - efm32pg1b - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_cmu.c - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_emu.c - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_gpio.c - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_usart.c - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\iar\startup_efm32pg1b.s - - - $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c - - - - QP - - $PROJ_DIR$\..\..\..\..\..\src\qf\qep_hsm.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qep_msm.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_act.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_actq.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_defer.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_dyn.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_mem.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf_pkg.h - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_ps.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qact.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qeq.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qmact.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qf\qf_time.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qxk\qxk.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qxk\qxk_mutex.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qxk_pkg.h - - - $PROJ_DIR$\..\..\..\..\..\src\qxk\qxk_sema.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qxk\qxk_xthr.cpp - - - - QP_port - - $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qxk\iar\qxk_port.s - - - - QS - - Debug - Release - - - $PROJ_DIR$\..\..\..\..\..\src\qs\qs.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qs\qs_fp.cpp - - - $PROJ_DIR$\..\..\..\..\..\src\qs_pkg.h - - - $PROJ_DIR$\..\..\..\..\..\src\qs\qs_rx.cpp - - + + General + 3 + + 28 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + cmd /c "if exist $OBJ_DIR$\qstamp.o del $OBJ_DIR$\qstamp.o" + + + + + ILINK + 0 + + 20 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + Coder + 0 + + + + + Application + + $PROJ_DIR$\..\bsp.cpp + + + $PROJ_DIR$\..\..\bsp.h + + + $PROJ_DIR$\..\..\dpp.h + + + $PROJ_DIR$\..\main.cpp + + + $PROJ_DIR$\..\..\philo.cpp + + + $PROJ_DIR$\..\..\..\..\..\include\qstamp.cpp + + + $PROJ_DIR$\..\..\table.cpp + + + $PROJ_DIR$\..\test.cpp + + + $PROJ_DIR$\..\test.h + + + + efm32pg1b + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_cmu.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_emu.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_gpio.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\em_usart.c + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\iar\startup_efm32pg1b.s + + + $PROJ_DIR$\..\..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c + + + + QP + + $PROJ_DIR$\..\..\..\..\..\src\qf\qep_hsm.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qep_msm.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_act.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_actq.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_defer.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_dyn.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_mem.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf_pkg.h + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_ps.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qact.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qeq.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_qmact.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qf\qf_time.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qxk\qxk.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qxk\qxk_mutex.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qxk_pkg.h + + + $PROJ_DIR$\..\..\..\..\..\src\qxk\qxk_sema.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qxk\qxk_xthr.cpp + + + + QP_port + + $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qxk\iar\qxk_port.s + + + + QS + + Debug + Release + + + $PROJ_DIR$\..\..\..\..\..\src\qs\qs.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qs\qs_fp.cpp + + + $PROJ_DIR$\..\..\..\..\..\src\qs_pkg.h + + + $PROJ_DIR$\..\..\..\..\..\src\qs\qs_rx.cpp + + - - diff --git a/examples/performance/dpp_efm32-slstk3401a/qxk/test.cpp b/examples/performance/dpp_efm32-slstk3401a/qxk/test.cpp index 0e276115..b84999ac 100644 --- a/examples/performance/dpp_efm32-slstk3401a/qxk/test.cpp +++ b/examples/performance/dpp_efm32-slstk3401a/qxk/test.cpp @@ -1,7 +1,7 @@ //**************************************************************************** // DPP example for QXK -// Last updated for version 5.9.6 -// Last updated on 2017-07-27 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // 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 XT_Sema.init(1U); // 1 count for (;;) { - (void)XT_Sema.wait(0U, 0U); // wait forever + (void)XT_Sema.wait(QXTHREAD_NO_TIMEOUT); // wait forever BSP::ledOn(); - QP::QXThread::delay(1, 0U); // 1 cycle + QP::QXThread::delay(1U); // block for 1 clock tick BSP::ledOff(); } } diff --git a/include/qep.h b/include/qep.h index 380aedfa..dc353f46 100644 --- a/include/qep.h +++ b/include/qep.h @@ -3,8 +3,8 @@ /// @ingroup qep /// @cond ///*************************************************************************** -/// Last updated for version 5.9.6 -/// Last updated on 2017-08-01 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-18 /// /// 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 // major version number, Y is a 1-digit minor version number, and Z is // 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 // a 1-digit major version number, Y is a 1-digit minor version 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) -#define QP_RELEASE 0x9A315E6BU +//! Tamperproof current QP release (5.9.7) and date (2017-08-18) +#define QP_RELEASE 0x9A2F3B8AU //**************************************************************************** #ifndef Q_SIGNAL_SIZE @@ -315,9 +315,11 @@ public: virtual ~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(0)); } + //! @overload init(void) + virtual void init(QEvt const * const e); + //! Dispatches an event to QHsm virtual void dispatch(QEvt const * const e); diff --git a/include/qequeue.h b/include/qequeue.h index 3b26be58..f398b844 100644 --- a/include/qequeue.h +++ b/include/qequeue.h @@ -3,8 +3,8 @@ /// @ingroup qf /// @cond ///*************************************************************************** -/// Last updated for version 5.8.0 -/// Last updated on 2016-11-19 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-18 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -224,6 +224,21 @@ public: 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 //! is empty /// @note diff --git a/include/qf.h b/include/qf.h index 8fc92bcd..e1728d7b 100644 --- a/include/qf.h +++ b/include/qf.h @@ -3,8 +3,8 @@ /// @ingroup qf /// @cond ///*************************************************************************** -/// Last updated for version 5.9.6 -/// Last updated on 2017-08-01 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-20 /// /// 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; #endif - //! QF priority associated with the active object. + //! QF priority (1..#QF_MAX_ACTIVE) of this active object. 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 constructor (abstract class) QActive(QStateHandler const initial); @@ -353,13 +359,16 @@ private: /// list, so only armed time events consume CPU cycles. /// /// @note -/// QF manages the time events in the macro TICK_X(), which must be -/// called periodically, eitehr from a clock tick ISR, or from a task level. +/// QF manages the time events in the macro TICK_X(), which must be called +/// periodically, from the clock tick ISR or from the special QP::QTicker +/// active object. /// /// @note -/// In this version of QF QTimeEvt objects should __not__ be allocated -/// dynamically from event pools. Currently, QF will not correctly recycle -/// the dynamically allocated Time Events. +/// Even though QP::QTimeEvt is a subclass of QP::QEvt, QP::QTimeEvt instances +/// can NOT be allocated dynamically from event pools. In other words, it is +/// illegal to allocate QP::QTimeEvt instances with the Q_NEW() or Q_NEW_X() +/// macros. +/// class QTimeEvt : public QEvt { private: @@ -408,6 +417,8 @@ public: #if (!defined QP_IMPL) && (QP_API_VERSION < 500) //! @deprecated TimeEvt ctor provided for backwards compatibility. + /// @overload QTimeEvt::QTimeEvt(QActive * const, enum_t const, + /// uint_fast8_t const) QTimeEvt(enum_t const sgnl) : #ifdef Q_EVT_CTOR QEvt(static_cast(sgnl)), diff --git a/include/qk.h b/include/qk.h index 6699a142..6c8c38ac 100644 --- a/include/qk.h +++ b/include/qk.h @@ -3,8 +3,8 @@ /// @ingroup qk /// @cond ///*************************************************************************** -/// Last updated for version 5.8.1 -/// Last updated on 2016-12-14 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-18 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -57,10 +57,10 @@ extern "C" { struct QK_Attr { - uint_fast8_t volatile actPrio; //!< prio of the active AO - uint_fast8_t volatile nextPrio; //!< prio of the next AO to execute - uint_fast8_t volatile lockPrio; //!< lock prio (0 == no-lock) - uint_fast8_t volatile lockHolder; //!< prio of the lock holder + uint_fast8_t actPrio; //!< prio of the active AO + uint_fast8_t nextPrio; //!< prio of the next AO to execute + uint_fast8_t lockPrio; //!< lock prio (0 == no-lock) + uint_fast8_t lockHolder; //!< prio of the lock holder #ifndef QK_ISR_CONTEXT_ uint_fast8_t volatile intNest; //!< ISR nesting level #endif // QK_ISR_CONTEXT_ @@ -83,23 +83,28 @@ void QK_activate_(void); //**************************************************************************** namespace QP { +//! The scheduler lock status +typedef uint_fast16_t QSchedStatus; + //**************************************************************************** //! QK services. /// @description /// This class groups together QK services. It has only static members and /// should not be instantiated. /// -// @note The QK scheduler, QK priority, QK ready set, etc. belong conceptually -/// to the QK class (as static class members). However, to avoid C++ potential -/// name-mangling problems in assembly language, these elements are defined -/// outside of the QK class and use the extern "C" linkage specification. +/// @note +/// The QK scheduler, QK priority, QK ready set, etc. belong conceptually +/// to the QK class (as static class members). However, to avoid potential +/// C++ name-mangling problems in assembly language, these elements are +/// defined outside of the QK class and use the extern "C" linkage. class QK { 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 - static char_t const *getVersion(void) { - return versionStr; - } + //! QK selective scheduler unlock + static void schedUnlock(QSchedStatus const stat); //! QK idle callback (customized in BSPs for QK) /// @description @@ -112,20 +117,11 @@ public: /// /// @sa QP::QF::onIdle() static void onIdle(void); -}; -/*! Priority-ceiling Mutex the QK preemptive kernel */ -class QMutex { -public: - 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; + //! get the current QK version number string of the form X.Y.Z + static char_t const *getVersion(void) { + return versionStr; + } }; } // namespace QP @@ -149,22 +145,21 @@ private: //! Internal macro to represent the scheduler lock status // 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. #define QF_SCHED_LOCK_(prio_) do { \ if (QK_ISR_CONTEXT_()) { \ - schedLock_.m_lockPrio = static_cast(0); \ + lockStat_ = static_cast(0xFF); \ } else { \ - schedLock_.init((prio_)); \ - schedLock_.lock(); \ + lockStat_ = QK::schedLock((prio_)); \ } \ } while (false) //! Internal macro for selective scheduler unlocking. #define QF_SCHED_UNLOCK_() do { \ - if (schedLock_.m_lockPrio != static_cast(0)) { \ - schedLock_.unlock(); \ + if (lockStat_ != static_cast(0xFF)) { \ + QK::schedUnlock(lockStat_); \ } \ } while (false) diff --git a/include/qpcpp.lnt b/include/qpcpp.lnt index a664d10d..8ea122ba 100644 --- a/include/qpcpp.lnt +++ b/include/qpcpp.lnt @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////////////////////// // Product: PC-Lint 9.x option file for linting QP/C++ applications -// Last updated for version 5.9.5 -// Last updated on 2017-07-19 +// Last updated for version 5.9.7 +// Last updated on 2017-08-20 // // Q u a n t u m L e a P s // --------------------------- @@ -168,13 +168,13 @@ *toTimeEvt) -esym(1927, // 8-5-1 Symbol not in the ctor initializer list - QP::QMActive::m_prio, - QP::QMActive::m_eQueue, - QP::QMActive::m_osObject, - QP::QMActive::m_thread) + QP::QActive::m_prio, + QP::QActive::m_eQueue, + QP::QActive::m_osObject, + QP::QActive::m_thread) -esym(1536, // 9-3-1, 9-3-2 Exposing low access member - QP::QMActive::m_osObject, - QP::QMActive::m_thread) + QP::QActive::m_osObject, + QP::QActive::m_thread) -estring(1960, // 11-0-1(req) non-private data member m_eQueue, m_thread, @@ -244,10 +244,10 @@ -estring(1963, Q_NEW) // 16-3-2(adv) '#/##' used in macro -esym(1960, remove) // 17-0-2, Re-use of C++ identifier -esym(1401, // member not initialized by constructor - QP::QMActive::m_prio, - QP::QMActive::m_eQueue, - QP::QMActive::m_osObject, - QP::QMActive::m_thread) + QP::QActive::m_prio, + QP::QActive::m_eQueue, + QP::QActive::m_osObject, + QP::QActive::m_thread) -esym(1704, // constructor has private access specification QP::QTimeEvt::QTimeEvt, QP::QEQueue::QEQueue, @@ -292,6 +292,8 @@ // QXK -esym(1960, // 3-2-3(req) type previously declared QP::QActive) +-estring(1960, // 11-0-1(req) non-private data member + m_startPrio) -estring(1960, // 11-0-1(req) non-private data member curr, next, @@ -304,6 +306,8 @@ -esym(1712, // default constructor not defined QXThread) -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 diff --git a/include/qs.h b/include/qs.h index 5ae5e92f..c0ab66f5 100644 --- a/include/qs.h +++ b/include/qs.h @@ -3,8 +3,8 @@ /// @ingroup qs /// @cond ///*************************************************************************** -/// Last updated for version 5.9.0 -/// Last updated on 2017-05-16 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-18 /// /// 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_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_RESERVED1, - QS_QF_RESERVED0, + QS_MUTEX_LOCK, //!< a mutex was locked + QS_MUTEX_UNLOCK, //!< a mutex was unlocked // [50] built-in scheduler records QS_SCHED_LOCK, //!< scheduler was locked diff --git a/include/qxk.h b/include/qxk.h index 54d489f5..79e8e588 100644 --- a/include/qxk.h +++ b/include/qxk.h @@ -4,8 +4,8 @@ /// @ingroup qxk /// @cond ///*************************************************************************** -/// Last updated for version 5.9.4 -/// Last updated on 2017-07-06 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-18 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -81,11 +81,11 @@ extern "C" { //! attributes of the QXK kernel struct QXK_Attr { - QP::QActive *curr; //!< currently executing thread - QP::QActive *next; //!< next thread to execute - uint_fast8_t volatile actPrio; //!< prio of the active basic thread - uint_fast8_t volatile lockPrio; //!< lock prio (0 == no-lock) - uint_fast8_t volatile lockHolder; //!< prio of the lock holder + QP::QActive *curr; //!< currently executing thread + QP::QActive *next; //!< next thread to execute + uint_fast8_t actPrio; //!< prio of the active basic thread + uint_fast8_t lockPrio; //!< lock prio (0 == no-lock) + uint_fast8_t lockHolder; //!< prio of the lock holder #ifndef QXK_ISR_CONTEXT_ uint_fast8_t volatile intNest; //!< ISR nesting level #endif // QXK_ISR_CONTEXT_ @@ -111,6 +111,9 @@ QP::QActive *QXK_current(void); //**************************************************************************** namespace QP { +//! The scheduler lock status +typedef uint_fast16_t QSchedStatus; + //**************************************************************************** //! QXK services. /// @description @@ -124,13 +127,11 @@ namespace QP { /// the extern "C" linkage specification. class QXK { public: + //! QXK selective scheduler lock + static QSchedStatus schedLock(uint_fast8_t const ceiling); - //! QXK initialization - /// @description - /// 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 selective scheduler unlock + static void schedUnlock(QSchedStatus const stat); //! QXK idle callback (customized in BSPs for QXK) /// @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 @@ -193,22 +172,21 @@ private: //! Internal macro to represent the scheduler lock status // 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. #define QF_SCHED_LOCK_(prio_) do { \ if (QXK_ISR_CONTEXT_()) { \ - schedLock_.m_lockPrio = static_cast(0); \ + lockStat_ = static_cast(0xFF); \ } else { \ - schedLock_.init((prio_)); \ - schedLock_.lock(); \ + lockStat_ = QXK::schedLock((prio_)); \ } \ } while (false) //! Internal macro for selective scheduler unlocking. #define QF_SCHED_UNLOCK_() do { \ - if (schedLock_.m_lockPrio != static_cast(0)) { \ - schedLock_.unlock(); \ + if (lockStat_ != static_cast(0xFF)) { \ + QXK::schedUnlock(lockStat_); \ } \ } while (false) diff --git a/include/qxthread.h b/include/qxthread.h index 8370d2ab..e1bcbbb1 100644 --- a/include/qxthread.h +++ b/include/qxthread.h @@ -3,8 +3,8 @@ /// @ingroup qxk /// @cond ///*************************************************************************** -/// Last updated for version 5.9.6 -/// Last updated on 2017-07-27 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-20 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -39,6 +39,9 @@ #ifndef qxthread_h #define qxthread_h +//! no-timeout sepcification when blocking on queues or semaphores +#define QXTHREAD_NO_TIMEOUT (static_cast(0)) + namespace QP { class QXThread; // forward declaration @@ -73,15 +76,14 @@ public: uint_fast8_t const tickRate = static_cast(0)); //! delay (block) the current extended thread for a specified # ticks - static bool delay(uint_fast16_t const nTicks, - uint_fast8_t const tickRate = static_cast(0)); + static bool delay(uint_fast16_t const nTicks); //! cancel the delay bool delayCancel(void); //! obtain a message from the private message queue (block if no messages) - static QEvt const *queueGet(uint_fast16_t const nTicks, - uint_fast8_t const tickRate = static_cast(0)); + static QEvt const *queueGet( + uint_fast16_t const nTicks = QXTHREAD_NO_TIMEOUT); // virtual function overrides... //! Executes the top-most initial transition in QP::QMsm. @@ -123,8 +125,7 @@ public: private: void block_(void) const; void unblock_(void) const; - void teArm_(enum_t const sig, uint_fast16_t const nTicks, - uint_fast8_t const tickRate = static_cast(0)); + void teArm_(enum_t const sig, uint_fast16_t const nTicks); bool teDisarm_(void); // attributes... @@ -132,11 +133,9 @@ private: // friendships... friend class QXSemaphore; + friend class QXMutex; }; -//! no-timeout sepcification when blocking on queues or semaphores -#define QXTHREAD_NO_TIMEOUT (static_cast(0)) - //**************************************************************************** //! Counting Semaphore of the QXK preemptive kernel class QXSemaphore { @@ -146,19 +145,67 @@ public: uint_fast16_t const max_count = static_cast(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 bool signal(void); - //! wait (block) on the semaphore - bool wait(uint_fast16_t const nTicks, - uint_fast8_t const tickRate = static_cast(0)); - private: QPSet m_waitSet; //!< set of extended threads waiting on this semaphore uint_fast16_t m_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 #endif // qxthread_h diff --git a/ports/win32-qv/qf_port.cpp b/ports/win32-qv/qf_port.cpp index 395c1a5b..540aafd8 100644 --- a/ports/win32-qv/qf_port.cpp +++ b/ports/win32-qv/qf_port.cpp @@ -135,6 +135,7 @@ int_t QF::run(void) { // for events. Instead, the Win32-QV port efficiently waits until // QP events become available. QF_INT_ENABLE(); + (void)WaitForSingleObject(QV_win32Event_, (DWORD)INFINITE); QF_INT_DISABLE(); diff --git a/source/qk.cpp b/source/qk.cpp index 675ba954..242e81d3 100644 --- a/source/qk.cpp +++ b/source/qk.cpp @@ -3,8 +3,8 @@ /// @ingroup qk /// @cond ///*************************************************************************** -/// Last updated for version 5.9.0 -/// Last updated on 2017-05-04 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-18 /// /// 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? if (QK_sched_() != static_cast(0)) { - QK_activate_(); // process all events produced so far + QK_activate_(); // activate AOs to process all events posted so far } } //**************************************************************************** -// @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::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 -// 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(). -// +/// @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::QActive::start(). +/// +/// @returns In QK, the QP::QF::run() function does not return. +/// int_t QF::run(void) { QF_INT_DISABLE(); initial_events(); // process all events posted during initialization @@ -144,7 +137,7 @@ int_t QF::run(void) { // the QK idle loop... for (;;) { - QK::onIdle(); // invoke the QK on-idle callback + QK::onIdle(); // application-specific QK on-idle callback } #ifdef __GNUC__ // GNU compiler? return static_cast(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 /// and the stack storage must not be provided, because the QK kernel does /// not need per-AO stacks. - /// - Q_REQUIRE_ID(500, (!QK_ISR_CONTEXT_()) + Q_REQUIRE_ID(300, (!QK_ISR_CONTEXT_()) && (static_cast(0) < prio) && (prio <= static_cast(QF_MAX_ACTIVE)) && (stkSto == static_cast(0))); - m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO - m_prio = prio; // set the QF priority of this AO + m_eQueue.init(qSto, qLen); // initialize the built-in queue - 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) QS_FLUSH(); // flush the trace buffer to the host @@ -201,20 +193,20 @@ void QActive::start(uint_fast8_t const prio, } //**************************************************************************** -// @description -// The preferred way of calling this function is from within the active -// object that needs to stop. In other words, an active object should stop -// itself rather than being stopped by someone else. This policy works -// best, because only the active object itself "knows" when it has reached -// the appropriate state for the shutdown. -// -// @note -// 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. -// +/// @description +/// This function must be called from within the AO that needs to stop. +/// In other words, an AO should stop itself rather than being stopped by +/// someone else. This policy works best, because only the AO itself "knows" +/// when it has reached the appropriate state for the shutdown. +/// +/// @note +/// 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. +/// 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 @@ -227,6 +219,115 @@ void QActive::stop(void) { 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(QK_attr_.lockPrio << 8); + QK_attr_.lockPrio = ceiling; + + QS_BEGIN_NOCRIT_(QS_SCHED_LOCK, + static_cast(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(stat), /* the previous lock prio */ + static_cast(QK_attr_.lockPrio)); // new lock prio + QS_END_NOCRIT_() + + // add the previous lock holder priority + stat |= static_cast(QK_attr_.lockHolder); + + QK_attr_.lockHolder = QK_attr_.actPrio; + } + else { + stat = static_cast(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(0xFF)) { + uint_fast8_t lockPrio = QK_attr_.lockPrio; // volatilie into tmp + uint_fast8_t prevPrio = static_cast(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(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(lockPrio),/* prio before unlocking */ + static_cast(prevPrio));// prio after unlocking + QS_END_NOCRIT_() + + // restore the previous lock priority and lock holder + QK_attr_.lockPrio = prevPrio; + QK_attr_.lockHolder = + static_cast(stat & static_cast(0xFF)); + + // find the highest-prio thread ready to run + if (QK_sched_() != static_cast(0)) { // priority found? + QK_activate_(); // activate any unlocked basic threads + } + + QF_CRIT_EXIT_(); + } +} + } // namespace QP //============================================================================ @@ -234,16 +335,16 @@ extern "C" { //**************************************************************************** /// @description -/// This function finds out the priority of the highest-priority active object -/// 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, -/// if mutex is configured in the port. +/// 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 +/// current priority. /// /// @returns the 1-based priority of the the active object, or zero if /// no eligible active object is ready to run. /// -/// @attention QK_sched_() must be always called with interrupts -/// __disabled__ and returns with interrupts __disabled__. +/// @attention +/// QK_sched_() must be always called with interrupts **disabled** and +/// returns with interrupts **disabled**. /// uint_fast8_t QK_sched_(void) { // find the highest-prio AO with non-empty event queue diff --git a/source/qk_mutex.cpp b/source/qk_mutex.cpp index 02ea39bf..bd4d2769 100644 --- a/source/qk_mutex.cpp +++ b/source/qk_mutex.cpp @@ -1,12 +1,11 @@ /// @file -/// @brief QP::QMutex::init(), QP::QMutex::lock(), and QP::QMutex::unlock() -/// definitions. +/// @brief QK mutex implementation (obsolete). /// @ingroup qk /// @cond ///*************************************************************************** /// Product: QK/C++ -/// Last updated for version 5.9.0 -/// Last updated on 2017-05-09 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-18 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -37,138 +36,3 @@ /// mailto:info@state-machine.com ///*************************************************************************** /// @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(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(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(0), static_cast(0)) - QS_TIME_(); // timestamp - QS_2U8_(static_cast(m_prevPrio), /* previous lock prio */ - static_cast(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(MUTEX_UNUSED))); - - uint_fast8_t p = m_prevPrio; - m_prevPrio = static_cast(MUTEX_UNUSED); - - QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, - static_cast(0), static_cast(0)) - QS_TIME_(); // timestamp - QS_2U8_(static_cast(QK_attr_.lockPrio), /* prev lock prio */ - (QK_attr_.lockPrio > p) /* the new lock prio */ - ? static_cast(p) - : static_cast(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(0)) { // priority found? - QK_activate_(); // activate any unlocked AOs - } - } - QF_CRIT_EXIT_(); -} - -} // namespace QP diff --git a/source/qxk.cpp b/source/qxk.cpp index 2772a119..9d8ae6e2 100644 --- a/source/qxk.cpp +++ b/source/qxk.cpp @@ -4,8 +4,8 @@ /// @ingroup qxk /// @cond ///*************************************************************************** -/// Last updated for version 5.9.6 -/// Last updated on 2017-07-27 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-20 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -67,19 +67,20 @@ public: QXKIdleThread() : QActive(Q_STATE_CAST(0)) {} }; -static QXKIdleThread l_idleThread; //**************************************************************************** /// @description /// 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). /// /// @note QF::init() clears the internal QF variables, so that the framework /// 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) { + static QXKIdleThread s_idleThread; + QF_maxPool_ = static_cast(0); QF_subscrList_ = static_cast(0); QF_maxPubSignal_ = static_cast(0); @@ -87,13 +88,13 @@ void QF::init(void) { bzero(&timeEvtHead_[0], static_cast(sizeof(timeEvtHead_))); bzero(&active_[0], static_cast(sizeof(active_))); bzero(&QXK_attr_, static_cast(sizeof(QXK_attr_))); - bzero(&l_idleThread, static_cast(sizeof(l_idleThread))); + bzero(&s_idleThread, static_cast(sizeof(s_idleThread))); // setup the QXK scheduler as initially locked and not running QXK_attr_.lockPrio = static_cast(QF_MAX_ACTIVE + 1); // 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(0); // set idle thread prio #ifdef QXK_INIT @@ -131,9 +132,8 @@ static void initial_events(void) { //**************************************************************************** /// @description -/// QP::QF::run() is typically called from your startup code after you -/// initialize the QF and start at least one basic- or extended-thread -/// (with QP::QActive::start() or QP::QXThread::start(), respectively). +/// QF::run() is typically called from main() after you initialize +/// the QF and start at least one active object with QActive::start(). /// /// @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, QEvt const * const ie) { - /// @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 not need per-AO stacks. - /// - Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) - && (static_cast(0) < prio) - && (prio <= static_cast(QF_MAX_ACTIVE)) - && (stkSto == static_cast(0)) - && (stkSize == static_cast(0))); + /// @pre AO cannot be started: + /// - from an ISR; + /// - the priority must be in range; + /// - the stack storage must NOT be provided (because the QXK kernel does + /// not need per-AO stacks). + Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) + && (static_cast(0) < prio) + && (prio <= static_cast(QF_MAX_ACTIVE)) + && (stkSto == static_cast(0)) + && (stkSize == static_cast(0))); m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO - m_osObject = static_cast(0); // no private stack for AO - m_prio = prio; // set the QF priority of this AO - - QF_CRIT_STAT_ - QF_CRIT_ENTRY_(); + m_prio = prio; // set the QF priority of this AO + m_startPrio = prio; // set the start QF priority 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) QS_FLUSH(); // flush the trace buffer to the host // see if this AO needs to be scheduled in case QXK is running + QF_CRIT_STAT_ QF_CRIT_ENTRY_(); if (QXK_sched_() != static_cast(0)) { // activation needed? 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. // void QActive::stop(void) { - /// @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! */ - && (this == QXK_attr_.curr)); + /// @pre QActive::stop() must be called from the AO that wants to stop. + Q_REQUIRE_ID(300, (this == QF::active_[QXK_attr_.actPrio])); QF::remove_(this); // remove this active object from the QF @@ -232,6 +229,115 @@ void QActive::stop(void) { 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(QXK_attr_.lockPrio << 8); + QXK_attr_.lockPrio = ceiling; + + QS_BEGIN_NOCRIT_(QS_SCHED_LOCK, + static_cast(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(stat), /* the previous lock prio */ + static_cast(QXK_attr_.lockPrio)); // new lock prio + QS_END_NOCRIT_() + + // add the previous lock holder priority + stat |= static_cast(QXK_attr_.lockHolder); + QXK_attr_.lockHolder = + (QXK_attr_.curr != static_cast(0)) + ? QXK_attr_.curr->m_prio + : static_cast(0); + } + else { + stat = static_cast(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(0xFF)) { + uint_fast8_t lockPrio = QXK_attr_.lockPrio; // volatilie into tmp + uint_fast8_t prevPrio = static_cast(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(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(lockPrio),/* prio before unlocking */ + static_cast(prevPrio));// prio after unlocking + QS_END_NOCRIT_() + + // restore the previous lock priority and lock holder + QXK_attr_.lockPrio = prevPrio; + QXK_attr_.lockHolder = + static_cast(stat & static_cast(0xFF)); + + // find the highest-prio thread ready to run + if (QXK_sched_() != static_cast(0)) { // priority found? + QXK_activate_(); // activate any unlocked basic threads + } + + QF_CRIT_EXIT_(); + } +} + } // namespace QP @@ -261,7 +367,7 @@ uint_fast8_t QXK_sched_(void) { QP::QActive *next = QP::QF::active_[p]; // the thread found must be registered in QF - //Q_ASSERT_ID(610, next != static_cast(0)); + Q_ASSERT_ID(610, next != static_cast(0)); // is the current thread a basic-thread? if (QXK_attr_.curr == static_cast(0)) { @@ -296,6 +402,7 @@ uint_fast8_t QXK_sched_(void) { // is the new prio different from the current prio? if (p != QXK_attr_.curr->m_prio) { + QS_BEGIN_NOCRIT_(QP::QS_SCHED_NEXT, QP::QS::priv_.locFilter[QP::QS::AO_OBJ], QXK_attr_.next) @@ -326,8 +433,8 @@ uint_fast8_t QXK_sched_(void) { /// returns with interrupts **disabled**. /// 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 p = QXK_attr_.next->m_prio; QP::QActive *a; // QS tracing or thread-local storage? @@ -377,12 +484,12 @@ void QXK_activate_(void) { p = QXK_attr_.readySet.findMax(); 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]; // the AO must be registered in QF - //Q_ASSERT_ID(710, a != static_cast(0)); + Q_ASSERT_ID(710, a != static_cast(0)); // is the next an AO-thread? if (a->m_osObject == static_cast(0)) { @@ -400,8 +507,8 @@ void QXK_activate_(void) { QP::QS::priv_.locFilter[QP::QS::AO_OBJ], QXK_attr_.next) QS_TIME_(); // timestamp - QS_2U8_(static_cast(p), // prio of the next thread - static_cast( // prio of the curent thread + QS_2U8_(static_cast(p), /* prio of the next thr */ + static_cast( /* prio of the curent thr */ QXK_attr_.actPrio)); QS_END_NOCRIT_() @@ -440,6 +547,11 @@ QP::QActive *QXK_current(void) { QF_CRIT_STAT_ QF_CRIT_ENTRY_(); + + /// @pre the QXK kernel must be running + Q_REQUIRE_ID(800, + QXK_attr_.lockPrio <= static_cast(QF_MAX_ACTIVE)); + curr = QXK_attr_.curr; if (curr == static_cast(0)) { // basic thread? curr = QP::QF::active_[QXK_attr_.actPrio]; @@ -447,7 +559,7 @@ QP::QActive *QXK_current(void) { QF_CRIT_EXIT_(); //! @post the current thread must be valid - Q_ENSURE_ID(900, curr != static_cast(0)); + Q_ENSURE_ID(890, curr != static_cast(0)); return curr; } diff --git a/source/qxk_mutex.cpp b/source/qxk_mutex.cpp index 3f1caeed..103ad863 100644 --- a/source/qxk_mutex.cpp +++ b/source/qxk_mutex.cpp @@ -1,12 +1,11 @@ /// @file -/// @brief QP::QXMutex::init(), QP::QXMutex::lock(), and QP::QXMutex::unlock() -/// definitions. +/// @brief Priority-ceiling blocking mutex QP::QXMutex class definition /// @ingroup qxk /// @cond ///*************************************************************************** /// Product: QK/C++ -/// Last updated for version 5.9.6 -/// Last updated on 2017-07-27 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-19 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -57,147 +56,331 @@ namespace QP { Q_DEFINE_THIS_MODULE("qxk_mutex") -enum { - MUTEX_UNUSED = 0xFF -}; - -//**************************************************************************** +//****************************************************************************/ /// @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 -/// A mutex must be initialized before it can be locked or unlocked. -/// -/// @sa QP::QXMutex::lock(), QP::QXMutex::unlock() +/// The ceiling priority must be unused by any thread. The ceiling +/// priority must be higher than priority of any thread that uses the +/// protected resource. /// /// @usage -/// The following example shows how to initialize, lock and unlock QXK mutex: /// @include qxk_mux.cpp /// -void QXMutex::init(uint_fast8_t const prio) { - m_lockPrio = prio; - m_prevPrio = static_cast(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) { +void QXMutex::init(uint_fast8_t ceiling) { QF_CRIT_STAT_ + 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(0) < ceiling) + && (ceiling <= static_cast(QF_MAX_ACTIVE)) + && (QF::active_[ceiling] == static_cast(0))); - /// @pre The mutex cannot be locked from the ISR context - /// and the mutex must be unused - Q_REQUIRE_ID(700, (!QXK_ISR_CONTEXT_()) - && (m_prevPrio == static_cast(MUTEX_UNUSED))); + m_ceiling = ceiling; + m_lockNest = static_cast(0); + QF::bzero(&m_waitSet, static_cast(sizeof(m_waitSet))); - m_prevPrio = QXK_attr_.lockPrio; // save previous lock prio - m_prevHolder = QXK_attr_.lockHolder; // save previous lock holder - - if (QXK_attr_.lockPrio < m_lockPrio) { // raising the lock prio? - QXK_attr_.lockPrio = m_lockPrio; - } - QXK_attr_.lockHolder = - (QXK_attr_.curr != static_cast(0)) - ? QXK_attr_.curr->m_prio - : static_cast(0); - - QS_BEGIN_NOCRIT_(QS_SCHED_LOCK, - static_cast(0), static_cast(0)) - QS_TIME_(); // timestamp - QS_2U8_(static_cast(m_prevPrio), /* previous lock prio */ - static_cast(QXK_attr_.lockPrio)); // new lock prio - QS_END_NOCRIT_() + // reserve the ceiling priority level for this mutex + QF::active_[ceiling] = reinterpret_cast(this); QF_CRIT_EXIT_(); } //**************************************************************************** +/// /// @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 -/// A mutex must be initialized before it can be locked or unlocked. -/// -/// @note -/// QP::QXMutex::unlock() must always follow the corresponding -/// QP::QXMutex::lock(). -/// -/// @sa QP::QXMutex::init(), QP::QXMutex::lock() +/// 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() must be ballanced by the matching call to +/// QXMutex::unlock(). +/// +/// @usage +/// @include qxk_mux.cpp +/// +bool QXMutex::lock(uint_fast16_t const nTicks) { + QXThread *thr; + QF_CRIT_STAT_ + + QF_CRIT_ENTRY_(); + thr = static_cast(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(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(0))); // not blocked + + // is the mutex available? + if (m_lockNest == static_cast(0)) { + m_lockNest = static_cast(1); + + // the priority slot must be set to this mutex */ + Q_ASSERT_ID(210, + QF::active_[m_ceiling] == reinterpret_cast(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(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(thr->m_startPrio), /* start prio */ + static_cast(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(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(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(this); + thr->teArm_(static_cast(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(this)); + thr->m_temp.obj = static_cast(0); // clear + } + QF_CRIT_EXIT_(); + + // signal of non-zero means that the time event has not expired + return thr->m_timeEvt.sig != static_cast(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(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(QF_MAX_ACTIVE)) + && (curr != static_cast(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(0)) { + m_lockNest = static_cast(1); + + // the priority slot must be set to this mutex + Q_ASSERT_ID(310, + QF::active_[m_ceiling] == reinterpret_cast(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(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(curr->m_startPrio), /* start prio */ + static_cast(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(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(0)); + curr = static_cast(0); // means that mutex is NOT available + } + QF_CRIT_EXIT_(); + + return curr != static_cast(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 -/// The following example shows how to initialize, lock and unlock QXK mutex: /// @include qxk_mux.cpp /// void QXMutex::unlock(void) { + QActive *curr; QF_CRIT_STAT_ + QF_CRIT_ENTRY_(); + curr = static_cast(QXK_attr_.curr); + if (curr == static_cast(0)) { // called from a basic thread? + curr = QF::active_[QXK_attr_.actPrio]; + } - /// @pre The mutex cannot be unlocked from the ISR context - /// and the mutex must NOT be unused - Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_()) - && (m_prevPrio != static_cast(MUTEX_UNUSED))); + /// @pre this function must: + /// - NOT be called from an ISR; + /// - the calling thread must be valid; + /// - 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(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(0)));//locked at least once - uint_fast8_t p = m_prevPrio; // the previouis lock prio - m_prevPrio = static_cast(MUTEX_UNUSED); - QXK_attr_.lockHolder = m_prevHolder; // restore previous lock holder + // is this the last nesting level? + if (m_lockNest == static_cast(1)) { - QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, - static_cast(0), static_cast(0)) - QS_TIME_(); // timestamp - if (QXK_attr_.lockPrio > p) { - QS_2U8_(static_cast(QXK_attr_.lockPrio), /* prev lock */ - static_cast(p)); // new lock prio - } - else { - p = QXK_attr_.lockPrio; - QS_2U8_(static_cast(p), /* prev lock prio */ - static_cast(p)); // new lock prio - } - QS_END_NOCRIT_() + // restore the holding thread's priority to the original + curr->m_prio = curr->m_startPrio; - 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(0), static_cast(0)) - QS_TIME_(); // timestamp - QS_2U8_(static_cast(QXK_attr_.lockPrio), /* prev lock */ - static_cast(p)); // new lock prio + QS_TIME_(); // timestamp + QS_2U8_(static_cast(curr->m_startPrio), /* start prio */ + static_cast(m_ceiling)); // the mutex ceiling QS_END_NOCRIT_() - QXK_attr_.lockPrio = p; // restore the previous lock prio - // find the highest-prio thread ready to run - if (QXK_sched_() != static_cast(0)) { // priority found? - QXK_activate_(); // activate any unlocked basic threads + // are any other threads waiting for this mutex? + if (m_waitSet.notEmpty()) { + + // find the highest-priority waiting thread + uint_fast8_t p = m_waitSet.findMax(); + QXThread *thr = static_cast(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(0)) /* extended thread */ + && (!QXK_attr_.readySet.hasElement(p)) + && (thr->m_prio == thr->m_startPrio) + && (thr->m_temp.obj == reinterpret_cast(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(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(thr->m_startPrio),/*start prio*/ + static_cast(thr->m_prio)); // ceiling prio + QS_END_NOCRIT_() + } + else { // no threads are waiting for this mutex + m_lockNest = static_cast(0); + + // put the mutex at the priority ceiling slot + QF::active_[m_ceiling] = reinterpret_cast(this); + } + + // schedule the next thread if multitasking started + if (QXK_sched_() != static_cast(0)) { + QXK_activate_(); // activate a basic thread } } - else { - QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, - static_cast(0), static_cast(0)) - QS_TIME_(); // timestamp - p = QXK_attr_.lockPrio; - QS_2U8_(static_cast(p), /* prev lock */ - static_cast(p)); // new lock prio - QS_END_NOCRIT_() + else { // releasing the mutex + --m_lockNest; // release one level } QF_CRIT_EXIT_(); } diff --git a/source/qxk_pkg.h b/source/qxk_pkg.h index 03770916..c7671780 100644 --- a/source/qxk_pkg.h +++ b/source/qxk_pkg.h @@ -3,8 +3,8 @@ /// @ingroup qxk /// @cond ///*************************************************************************** -/// Last updated for version 5.7.2 -/// Last updated on 2016-09-28 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-19 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -54,7 +54,7 @@ enum QXK_Timeouts { extern "C" { //! 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); //! called when a thread function returns diff --git a/source/qxk_sema.cpp b/source/qxk_sema.cpp index 1e6138c7..a128ae60 100644 --- a/source/qxk_sema.cpp +++ b/source/qxk_sema.cpp @@ -3,8 +3,8 @@ /// @ingroup qxk /// @cond ////************************************************************************** -/// Last updated for version 5.9.6 -/// Last updated on 2017-07-27 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-20 /// /// 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 /// QXTHREAD_NO_TIMEOUT indicates that no timeout will /// occur and the semaphore will wait indefinitely. -/// @param[in] tickRate system clock tick rate serviced in this call. -/// /// @returns /// true if the semaphore has been signaled, and false if the timeout occured. /// /// @note /// Multiple extended threads can wait for a given semahpre. /// -bool QXSemaphore::wait(uint_fast16_t const nTicks, - uint_fast8_t const tickRate) -{ +bool QXSemaphore::wait(uint_fast16_t const nTicks) { QF_CRIT_STAT_ 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 */ && (thr != static_cast(0)) /* current must be extended */ && (QXK_attr_.lockPrio == static_cast(0)) /* no lock */ - && (thr->m_temp.obj == static_cast(0))); // !blocked + && (thr->m_temp.obj == static_cast(0))); // !blocked if (m_count > static_cast(0)) { --m_count; @@ -131,7 +127,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks, else { // remember the blocking object thr->m_temp.obj = reinterpret_cast(this); - thr->teArm_(static_cast(QXK_SEMA_SIG), nTicks, tickRate); + thr->teArm_(static_cast(QXK_SEMA_SIG), nTicks); m_waitSet.insert(thr->m_prio); QXK_attr_.readySet.remove(thr->m_prio); (void)QXK_sched_(); @@ -142,7 +138,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks, // the blocking object must be this semaphore Q_ASSERT_ID(210, thr->m_temp.obj == reinterpret_cast(this)); - thr->m_temp.obj = static_cast(0); // clear + thr->m_temp.obj = static_cast(0); // clear } QF_CRIT_EXIT_(); @@ -150,6 +146,40 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks, return (thr->m_timeEvt.sig != static_cast(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(0))); + + QF_CRIT_ENTRY_(); + // is the semaphore available? + if (m_count > static_cast(0)) { + --m_count; + isAvailable = true; + } + else { // the semaphore is NOT available (would block) + isAvailable = false; + } + QF_CRIT_EXIT_(); + + return isAvailable; +} + //**************************************************************************** /// @description /// 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 QF_CRIT_STAT_ + /// @pre the semaphore must be initialized + Q_REQUIRE_ID(400, (m_max_count > (uint_fast16_t)0)); + QF_CRIT_ENTRY_(); if (m_waitSet.notEmpty()) { uint_fast8_t p = m_waitSet.findMax(); @@ -180,7 +213,7 @@ bool QXSemaphore::signal(void) { QXThread *thr = static_cast(QF::active_[p]); // the thread must be extended and the semaphore count must be zero - Q_ASSERT_ID(210, (thr != static_cast(0)) /* registered */ + Q_ASSERT_ID(410, (thr != static_cast(0)) /* registered */ && (thr->m_osObject != static_cast(0)) /* extended */ && (m_count == static_cast(0))); // not signaled diff --git a/source/qxk_xthr.cpp b/source/qxk_xthr.cpp index da213f6d..0c2d92e6 100644 --- a/source/qxk_xthr.cpp +++ b/source/qxk_xthr.cpp @@ -3,8 +3,8 @@ /// @ingroup qxk /// @cond ///*************************************************************************** -/// Last updated for version 5.9.6 -/// Last updated on 2017-07-27 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-19 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -69,7 +69,7 @@ Q_DEFINE_THIS_MODULE("qxk_xthr") /// @usage /// The following example illustrates how to invoke the QXThread ctor in the /// main() function -/// @include qxk_xthread_ctor.cpp +/// @include qxk_xctor.cpp /// QXThread::QXThread(QXThreadHandler const handler, uint_fast8_t const tickRate) : 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] ie pointer to the initial event (not used). /// -/// @note This function should be called via the macro QXTHREAD_START(). -/// /// @usage /// 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, - QEvt const *qSto[], uint_fast16_t const qLen, - void * const stkSto, uint_fast16_t const stkSize, - QEvt const * const /*ie*/) + QEvt const *qSto[], uint_fast16_t const qLen, + void * const stkSto, uint_fast16_t const stkSize, + 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(QF_MAX_ACTIVE)) && (stkSto != static_cast(0)) && (stkSize != static_cast(0)) @@ -135,6 +138,7 @@ void QXThread::start(uint_fast8_t const prio, stkSto, stkSize); m_prio = prio; + m_startPrio = prio; 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 /// 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 -/// situation when the post() operation is assumed to succeed (event delivery -/// guarantee). An assertion fires, when the event cannot be delivered in -/// this case. +/// @note +/// The zero value of the @p margin parameter is special and denotes +/// situation when the QXThread::post_() operation is assumed to succeed +/// (event delivery guarantee). An assertion fires, when the event cannot be +/// delivered in this case. /// #ifndef Q_SPY 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::priv_.QS::priv_.locFilter[QS::AO_OBJ], this) - QS_TIME_(); // timestamp - QS_OBJ_(sender); // the sender object - QS_SIG_(e->sig); // the signal of the event - QS_OBJ_(this); // this active object + QS_TIME_(); // timestamp + QS_OBJ_(sender); // the sender object + QS_SIG_(e->sig); // the signal of the event + QS_OBJ_(this); // this active object 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_END_NOCRIT_() @@ -318,16 +324,12 @@ void QXThread::postLIFO(QEvt const * const /*e*/) { /// to wait for the event to arrive. The value of /// QXTHREAD_NO_TIMEOUT indicates that no timeout will /// occur and the queue will block indefinitely. -/// @param[in] tickRate system clock tick rate serviced in this call. -/// /// @returns /// Returns pointer to the event. If the pointer is not NULL, the event /// was delivered. Otherwise the event pointer of NULL indicates that the /// queue has timed out. /// -QEvt const *QXThread::queueGet(uint_fast16_t const nTicks, - uint_fast8_t const tickRate) -{ +QEvt const *QXThread::queueGet(uint_fast16_t const nTicks) { QEQueueCtr nFree; QEvt const *e; QF_CRIT_STAT_ @@ -336,13 +338,13 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks, QXThread *thr = static_cast(QXK_attr_.curr); /// @pre this function must: - /// (1) NOT be called from an ISR; (2) be called from an extended thread; - /// (3) the thread must NOT be holding a mutex and - /// (4) the thread must NOT be already blocked on any object. - /// + /// - NOT be called from an ISR; + /// - be called from an extended thread; + /// - 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 */ && (thr != static_cast(0)) /* current must be extended */ - && (QXK_attr_.lockPrio == static_cast(0)) /* !locked */ + && (QXK_attr_.lockHolder != thr->m_prio) /* not holding a lock */ && (thr->m_temp.obj == static_cast(0))); // !blocked // 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) thr->m_temp.obj = reinterpret_cast(&thr->m_eQueue); - thr->teArm_(static_cast(QXK_QUEUE_SIG), nTicks, tickRate); + thr->teArm_(static_cast(QXK_QUEUE_SIG), nTicks); QXK_attr_.readySet.remove(thr->m_prio); (void)QXK_sched_(); QF_CRIT_EXIT_(); @@ -425,7 +427,7 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks, /// void QXThread::block_(void) const { /// @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); (void)QXK_sched_(); } @@ -455,10 +457,7 @@ void QXThread::unblock_(void) const { /// @note /// must be called from within a critical section /// -void QXThread::teArm_(enum_t const sig, - uint_fast16_t const nTicks, - uint_fast8_t const tickRate) -{ +void QXThread::teArm_(enum_t const sig, uint_fast16_t const nTicks) { /// @pre the time event must be unused Q_REQUIRE_ID(700, m_timeEvt.m_ctr == static_cast(0)); @@ -471,11 +470,12 @@ void QXThread::teArm_(enum_t const sig, // is the time event unlinked? // 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, - // because un-linking is performed exclusively in QF_tickX(). - // + // because un-linking is performed exclusively in QF::tickX(). if ((m_timeEvt.refCtr_ & static_cast(0x80)) == static_cast(0)) { + uint_fast8_t tickRate = + static_cast(m_timeEvt.refCtr_); m_timeEvt.refCtr_ |= static_cast(0x80); // mark as linked // The time event is initially inserted into the separate @@ -515,35 +515,32 @@ bool QXThread::teDisarm_(void) { //**************************************************************************** //! delay (timed block) the current extended thread -bool QXThread::delay(uint_fast16_t const nTicks, - uint_fast8_t const tickRate) -{ +bool QXThread::delay(uint_fast16_t const nTicks) { QF_CRIT_STAT_ QF_CRIT_ENTRY_(); QXThread *thr = static_cast(QXK_attr_.curr); /// @pre this function must: - /// (1) NOT be called from an ISR; (2) be called from an extended thread; - /// (3) the thread must NOT be holding a mutex and - /// (4) the thread must NOT be already blocked on any object. - /// - Q_REQUIRE_ID(900, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ + /// - NOT be called from an ISR; + /// - be called from an extended thread; + /// - the thread must NOT be holding a scheduler lock and; + /// - the thread must NOT be already blocked on any object. + Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ && (thr != static_cast(0)) /* current must be extended */ - && (QXK_attr_.lockPrio == static_cast(0)) /* !locked */ + && (QXK_attr_.lockHolder != thr->m_prio) /* not holding a lock */ && (thr->m_temp.obj == static_cast(0))); // !blocked - // remember the blocking object thr->m_temp.obj = reinterpret_cast(&thr->m_timeEvt); - thr->teArm_(static_cast(QXK_DELAY_SIG), nTicks, tickRate); + thr->teArm_(static_cast(QXK_DELAY_SIG), nTicks); thr->block_(); QF_CRIT_EXIT_(); QF_CRIT_EXIT_NOP(); // BLOCK here QF_CRIT_ENTRY_(); // 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(&thr->m_timeEvt)); thr->m_temp.obj = static_cast(0); // clear QF_CRIT_EXIT_(); diff --git a/src/qk/qk.cpp b/src/qk/qk.cpp index 675ba954..242e81d3 100644 --- a/src/qk/qk.cpp +++ b/src/qk/qk.cpp @@ -3,8 +3,8 @@ /// @ingroup qk /// @cond ///*************************************************************************** -/// Last updated for version 5.9.0 -/// Last updated on 2017-05-04 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-18 /// /// 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? if (QK_sched_() != static_cast(0)) { - QK_activate_(); // process all events produced so far + QK_activate_(); // activate AOs to process all events posted so far } } //**************************************************************************** -// @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::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 -// 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(). -// +/// @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::QActive::start(). +/// +/// @returns In QK, the QP::QF::run() function does not return. +/// int_t QF::run(void) { QF_INT_DISABLE(); initial_events(); // process all events posted during initialization @@ -144,7 +137,7 @@ int_t QF::run(void) { // the QK idle loop... for (;;) { - QK::onIdle(); // invoke the QK on-idle callback + QK::onIdle(); // application-specific QK on-idle callback } #ifdef __GNUC__ // GNU compiler? return static_cast(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 /// and the stack storage must not be provided, because the QK kernel does /// not need per-AO stacks. - /// - Q_REQUIRE_ID(500, (!QK_ISR_CONTEXT_()) + Q_REQUIRE_ID(300, (!QK_ISR_CONTEXT_()) && (static_cast(0) < prio) && (prio <= static_cast(QF_MAX_ACTIVE)) && (stkSto == static_cast(0))); - m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO - m_prio = prio; // set the QF priority of this AO + m_eQueue.init(qSto, qLen); // initialize the built-in queue - 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) QS_FLUSH(); // flush the trace buffer to the host @@ -201,20 +193,20 @@ void QActive::start(uint_fast8_t const prio, } //**************************************************************************** -// @description -// The preferred way of calling this function is from within the active -// object that needs to stop. In other words, an active object should stop -// itself rather than being stopped by someone else. This policy works -// best, because only the active object itself "knows" when it has reached -// the appropriate state for the shutdown. -// -// @note -// 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. -// +/// @description +/// This function must be called from within the AO that needs to stop. +/// In other words, an AO should stop itself rather than being stopped by +/// someone else. This policy works best, because only the AO itself "knows" +/// when it has reached the appropriate state for the shutdown. +/// +/// @note +/// 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. +/// 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 @@ -227,6 +219,115 @@ void QActive::stop(void) { 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(QK_attr_.lockPrio << 8); + QK_attr_.lockPrio = ceiling; + + QS_BEGIN_NOCRIT_(QS_SCHED_LOCK, + static_cast(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(stat), /* the previous lock prio */ + static_cast(QK_attr_.lockPrio)); // new lock prio + QS_END_NOCRIT_() + + // add the previous lock holder priority + stat |= static_cast(QK_attr_.lockHolder); + + QK_attr_.lockHolder = QK_attr_.actPrio; + } + else { + stat = static_cast(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(0xFF)) { + uint_fast8_t lockPrio = QK_attr_.lockPrio; // volatilie into tmp + uint_fast8_t prevPrio = static_cast(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(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(lockPrio),/* prio before unlocking */ + static_cast(prevPrio));// prio after unlocking + QS_END_NOCRIT_() + + // restore the previous lock priority and lock holder + QK_attr_.lockPrio = prevPrio; + QK_attr_.lockHolder = + static_cast(stat & static_cast(0xFF)); + + // find the highest-prio thread ready to run + if (QK_sched_() != static_cast(0)) { // priority found? + QK_activate_(); // activate any unlocked basic threads + } + + QF_CRIT_EXIT_(); + } +} + } // namespace QP //============================================================================ @@ -234,16 +335,16 @@ extern "C" { //**************************************************************************** /// @description -/// This function finds out the priority of the highest-priority active object -/// 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, -/// if mutex is configured in the port. +/// 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 +/// current priority. /// /// @returns the 1-based priority of the the active object, or zero if /// no eligible active object is ready to run. /// -/// @attention QK_sched_() must be always called with interrupts -/// __disabled__ and returns with interrupts __disabled__. +/// @attention +/// QK_sched_() must be always called with interrupts **disabled** and +/// returns with interrupts **disabled**. /// uint_fast8_t QK_sched_(void) { // find the highest-prio AO with non-empty event queue diff --git a/src/qk/qk_mutex.cpp b/src/qk/qk_mutex.cpp index 02ea39bf..bd4d2769 100644 --- a/src/qk/qk_mutex.cpp +++ b/src/qk/qk_mutex.cpp @@ -1,12 +1,11 @@ /// @file -/// @brief QP::QMutex::init(), QP::QMutex::lock(), and QP::QMutex::unlock() -/// definitions. +/// @brief QK mutex implementation (obsolete). /// @ingroup qk /// @cond ///*************************************************************************** /// Product: QK/C++ -/// Last updated for version 5.9.0 -/// Last updated on 2017-05-09 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-18 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -37,138 +36,3 @@ /// mailto:info@state-machine.com ///*************************************************************************** /// @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(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(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(0), static_cast(0)) - QS_TIME_(); // timestamp - QS_2U8_(static_cast(m_prevPrio), /* previous lock prio */ - static_cast(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(MUTEX_UNUSED))); - - uint_fast8_t p = m_prevPrio; - m_prevPrio = static_cast(MUTEX_UNUSED); - - QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, - static_cast(0), static_cast(0)) - QS_TIME_(); // timestamp - QS_2U8_(static_cast(QK_attr_.lockPrio), /* prev lock prio */ - (QK_attr_.lockPrio > p) /* the new lock prio */ - ? static_cast(p) - : static_cast(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(0)) { // priority found? - QK_activate_(); // activate any unlocked AOs - } - } - QF_CRIT_EXIT_(); -} - -} // namespace QP diff --git a/src/qxk/qxk.cpp b/src/qxk/qxk.cpp index 2772a119..9d8ae6e2 100644 --- a/src/qxk/qxk.cpp +++ b/src/qxk/qxk.cpp @@ -4,8 +4,8 @@ /// @ingroup qxk /// @cond ///*************************************************************************** -/// Last updated for version 5.9.6 -/// Last updated on 2017-07-27 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-20 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -67,19 +67,20 @@ public: QXKIdleThread() : QActive(Q_STATE_CAST(0)) {} }; -static QXKIdleThread l_idleThread; //**************************************************************************** /// @description /// 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). /// /// @note QF::init() clears the internal QF variables, so that the framework /// 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) { + static QXKIdleThread s_idleThread; + QF_maxPool_ = static_cast(0); QF_subscrList_ = static_cast(0); QF_maxPubSignal_ = static_cast(0); @@ -87,13 +88,13 @@ void QF::init(void) { bzero(&timeEvtHead_[0], static_cast(sizeof(timeEvtHead_))); bzero(&active_[0], static_cast(sizeof(active_))); bzero(&QXK_attr_, static_cast(sizeof(QXK_attr_))); - bzero(&l_idleThread, static_cast(sizeof(l_idleThread))); + bzero(&s_idleThread, static_cast(sizeof(s_idleThread))); // setup the QXK scheduler as initially locked and not running QXK_attr_.lockPrio = static_cast(QF_MAX_ACTIVE + 1); // 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(0); // set idle thread prio #ifdef QXK_INIT @@ -131,9 +132,8 @@ static void initial_events(void) { //**************************************************************************** /// @description -/// QP::QF::run() is typically called from your startup code after you -/// initialize the QF and start at least one basic- or extended-thread -/// (with QP::QActive::start() or QP::QXThread::start(), respectively). +/// QF::run() is typically called from main() after you initialize +/// the QF and start at least one active object with QActive::start(). /// /// @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, QEvt const * const ie) { - /// @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 not need per-AO stacks. - /// - Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) - && (static_cast(0) < prio) - && (prio <= static_cast(QF_MAX_ACTIVE)) - && (stkSto == static_cast(0)) - && (stkSize == static_cast(0))); + /// @pre AO cannot be started: + /// - from an ISR; + /// - the priority must be in range; + /// - the stack storage must NOT be provided (because the QXK kernel does + /// not need per-AO stacks). + Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) + && (static_cast(0) < prio) + && (prio <= static_cast(QF_MAX_ACTIVE)) + && (stkSto == static_cast(0)) + && (stkSize == static_cast(0))); m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO - m_osObject = static_cast(0); // no private stack for AO - m_prio = prio; // set the QF priority of this AO - - QF_CRIT_STAT_ - QF_CRIT_ENTRY_(); + m_prio = prio; // set the QF priority of this AO + m_startPrio = prio; // set the start QF priority 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) QS_FLUSH(); // flush the trace buffer to the host // see if this AO needs to be scheduled in case QXK is running + QF_CRIT_STAT_ QF_CRIT_ENTRY_(); if (QXK_sched_() != static_cast(0)) { // activation needed? 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. // void QActive::stop(void) { - /// @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! */ - && (this == QXK_attr_.curr)); + /// @pre QActive::stop() must be called from the AO that wants to stop. + Q_REQUIRE_ID(300, (this == QF::active_[QXK_attr_.actPrio])); QF::remove_(this); // remove this active object from the QF @@ -232,6 +229,115 @@ void QActive::stop(void) { 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(QXK_attr_.lockPrio << 8); + QXK_attr_.lockPrio = ceiling; + + QS_BEGIN_NOCRIT_(QS_SCHED_LOCK, + static_cast(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(stat), /* the previous lock prio */ + static_cast(QXK_attr_.lockPrio)); // new lock prio + QS_END_NOCRIT_() + + // add the previous lock holder priority + stat |= static_cast(QXK_attr_.lockHolder); + QXK_attr_.lockHolder = + (QXK_attr_.curr != static_cast(0)) + ? QXK_attr_.curr->m_prio + : static_cast(0); + } + else { + stat = static_cast(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(0xFF)) { + uint_fast8_t lockPrio = QXK_attr_.lockPrio; // volatilie into tmp + uint_fast8_t prevPrio = static_cast(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(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(lockPrio),/* prio before unlocking */ + static_cast(prevPrio));// prio after unlocking + QS_END_NOCRIT_() + + // restore the previous lock priority and lock holder + QXK_attr_.lockPrio = prevPrio; + QXK_attr_.lockHolder = + static_cast(stat & static_cast(0xFF)); + + // find the highest-prio thread ready to run + if (QXK_sched_() != static_cast(0)) { // priority found? + QXK_activate_(); // activate any unlocked basic threads + } + + QF_CRIT_EXIT_(); + } +} + } // namespace QP @@ -261,7 +367,7 @@ uint_fast8_t QXK_sched_(void) { QP::QActive *next = QP::QF::active_[p]; // the thread found must be registered in QF - //Q_ASSERT_ID(610, next != static_cast(0)); + Q_ASSERT_ID(610, next != static_cast(0)); // is the current thread a basic-thread? if (QXK_attr_.curr == static_cast(0)) { @@ -296,6 +402,7 @@ uint_fast8_t QXK_sched_(void) { // is the new prio different from the current prio? if (p != QXK_attr_.curr->m_prio) { + QS_BEGIN_NOCRIT_(QP::QS_SCHED_NEXT, QP::QS::priv_.locFilter[QP::QS::AO_OBJ], QXK_attr_.next) @@ -326,8 +433,8 @@ uint_fast8_t QXK_sched_(void) { /// returns with interrupts **disabled**. /// 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 p = QXK_attr_.next->m_prio; QP::QActive *a; // QS tracing or thread-local storage? @@ -377,12 +484,12 @@ void QXK_activate_(void) { p = QXK_attr_.readySet.findMax(); 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]; // the AO must be registered in QF - //Q_ASSERT_ID(710, a != static_cast(0)); + Q_ASSERT_ID(710, a != static_cast(0)); // is the next an AO-thread? if (a->m_osObject == static_cast(0)) { @@ -400,8 +507,8 @@ void QXK_activate_(void) { QP::QS::priv_.locFilter[QP::QS::AO_OBJ], QXK_attr_.next) QS_TIME_(); // timestamp - QS_2U8_(static_cast(p), // prio of the next thread - static_cast( // prio of the curent thread + QS_2U8_(static_cast(p), /* prio of the next thr */ + static_cast( /* prio of the curent thr */ QXK_attr_.actPrio)); QS_END_NOCRIT_() @@ -440,6 +547,11 @@ QP::QActive *QXK_current(void) { QF_CRIT_STAT_ QF_CRIT_ENTRY_(); + + /// @pre the QXK kernel must be running + Q_REQUIRE_ID(800, + QXK_attr_.lockPrio <= static_cast(QF_MAX_ACTIVE)); + curr = QXK_attr_.curr; if (curr == static_cast(0)) { // basic thread? curr = QP::QF::active_[QXK_attr_.actPrio]; @@ -447,7 +559,7 @@ QP::QActive *QXK_current(void) { QF_CRIT_EXIT_(); //! @post the current thread must be valid - Q_ENSURE_ID(900, curr != static_cast(0)); + Q_ENSURE_ID(890, curr != static_cast(0)); return curr; } diff --git a/src/qxk/qxk_mutex.cpp b/src/qxk/qxk_mutex.cpp index 3f1caeed..103ad863 100644 --- a/src/qxk/qxk_mutex.cpp +++ b/src/qxk/qxk_mutex.cpp @@ -1,12 +1,11 @@ /// @file -/// @brief QP::QXMutex::init(), QP::QXMutex::lock(), and QP::QXMutex::unlock() -/// definitions. +/// @brief Priority-ceiling blocking mutex QP::QXMutex class definition /// @ingroup qxk /// @cond ///*************************************************************************** /// Product: QK/C++ -/// Last updated for version 5.9.6 -/// Last updated on 2017-07-27 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-19 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -57,147 +56,331 @@ namespace QP { Q_DEFINE_THIS_MODULE("qxk_mutex") -enum { - MUTEX_UNUSED = 0xFF -}; - -//**************************************************************************** +//****************************************************************************/ /// @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 -/// A mutex must be initialized before it can be locked or unlocked. -/// -/// @sa QP::QXMutex::lock(), QP::QXMutex::unlock() +/// The ceiling priority must be unused by any thread. The ceiling +/// priority must be higher than priority of any thread that uses the +/// protected resource. /// /// @usage -/// The following example shows how to initialize, lock and unlock QXK mutex: /// @include qxk_mux.cpp /// -void QXMutex::init(uint_fast8_t const prio) { - m_lockPrio = prio; - m_prevPrio = static_cast(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) { +void QXMutex::init(uint_fast8_t ceiling) { QF_CRIT_STAT_ + 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(0) < ceiling) + && (ceiling <= static_cast(QF_MAX_ACTIVE)) + && (QF::active_[ceiling] == static_cast(0))); - /// @pre The mutex cannot be locked from the ISR context - /// and the mutex must be unused - Q_REQUIRE_ID(700, (!QXK_ISR_CONTEXT_()) - && (m_prevPrio == static_cast(MUTEX_UNUSED))); + m_ceiling = ceiling; + m_lockNest = static_cast(0); + QF::bzero(&m_waitSet, static_cast(sizeof(m_waitSet))); - m_prevPrio = QXK_attr_.lockPrio; // save previous lock prio - m_prevHolder = QXK_attr_.lockHolder; // save previous lock holder - - if (QXK_attr_.lockPrio < m_lockPrio) { // raising the lock prio? - QXK_attr_.lockPrio = m_lockPrio; - } - QXK_attr_.lockHolder = - (QXK_attr_.curr != static_cast(0)) - ? QXK_attr_.curr->m_prio - : static_cast(0); - - QS_BEGIN_NOCRIT_(QS_SCHED_LOCK, - static_cast(0), static_cast(0)) - QS_TIME_(); // timestamp - QS_2U8_(static_cast(m_prevPrio), /* previous lock prio */ - static_cast(QXK_attr_.lockPrio)); // new lock prio - QS_END_NOCRIT_() + // reserve the ceiling priority level for this mutex + QF::active_[ceiling] = reinterpret_cast(this); QF_CRIT_EXIT_(); } //**************************************************************************** +/// /// @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 -/// A mutex must be initialized before it can be locked or unlocked. -/// -/// @note -/// QP::QXMutex::unlock() must always follow the corresponding -/// QP::QXMutex::lock(). -/// -/// @sa QP::QXMutex::init(), QP::QXMutex::lock() +/// 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() must be ballanced by the matching call to +/// QXMutex::unlock(). +/// +/// @usage +/// @include qxk_mux.cpp +/// +bool QXMutex::lock(uint_fast16_t const nTicks) { + QXThread *thr; + QF_CRIT_STAT_ + + QF_CRIT_ENTRY_(); + thr = static_cast(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(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(0))); // not blocked + + // is the mutex available? + if (m_lockNest == static_cast(0)) { + m_lockNest = static_cast(1); + + // the priority slot must be set to this mutex */ + Q_ASSERT_ID(210, + QF::active_[m_ceiling] == reinterpret_cast(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(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(thr->m_startPrio), /* start prio */ + static_cast(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(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(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(this); + thr->teArm_(static_cast(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(this)); + thr->m_temp.obj = static_cast(0); // clear + } + QF_CRIT_EXIT_(); + + // signal of non-zero means that the time event has not expired + return thr->m_timeEvt.sig != static_cast(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(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(QF_MAX_ACTIVE)) + && (curr != static_cast(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(0)) { + m_lockNest = static_cast(1); + + // the priority slot must be set to this mutex + Q_ASSERT_ID(310, + QF::active_[m_ceiling] == reinterpret_cast(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(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(curr->m_startPrio), /* start prio */ + static_cast(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(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(0)); + curr = static_cast(0); // means that mutex is NOT available + } + QF_CRIT_EXIT_(); + + return curr != static_cast(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 -/// The following example shows how to initialize, lock and unlock QXK mutex: /// @include qxk_mux.cpp /// void QXMutex::unlock(void) { + QActive *curr; QF_CRIT_STAT_ + QF_CRIT_ENTRY_(); + curr = static_cast(QXK_attr_.curr); + if (curr == static_cast(0)) { // called from a basic thread? + curr = QF::active_[QXK_attr_.actPrio]; + } - /// @pre The mutex cannot be unlocked from the ISR context - /// and the mutex must NOT be unused - Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_()) - && (m_prevPrio != static_cast(MUTEX_UNUSED))); + /// @pre this function must: + /// - NOT be called from an ISR; + /// - the calling thread must be valid; + /// - 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(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(0)));//locked at least once - uint_fast8_t p = m_prevPrio; // the previouis lock prio - m_prevPrio = static_cast(MUTEX_UNUSED); - QXK_attr_.lockHolder = m_prevHolder; // restore previous lock holder + // is this the last nesting level? + if (m_lockNest == static_cast(1)) { - QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, - static_cast(0), static_cast(0)) - QS_TIME_(); // timestamp - if (QXK_attr_.lockPrio > p) { - QS_2U8_(static_cast(QXK_attr_.lockPrio), /* prev lock */ - static_cast(p)); // new lock prio - } - else { - p = QXK_attr_.lockPrio; - QS_2U8_(static_cast(p), /* prev lock prio */ - static_cast(p)); // new lock prio - } - QS_END_NOCRIT_() + // restore the holding thread's priority to the original + curr->m_prio = curr->m_startPrio; - 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(0), static_cast(0)) - QS_TIME_(); // timestamp - QS_2U8_(static_cast(QXK_attr_.lockPrio), /* prev lock */ - static_cast(p)); // new lock prio + QS_TIME_(); // timestamp + QS_2U8_(static_cast(curr->m_startPrio), /* start prio */ + static_cast(m_ceiling)); // the mutex ceiling QS_END_NOCRIT_() - QXK_attr_.lockPrio = p; // restore the previous lock prio - // find the highest-prio thread ready to run - if (QXK_sched_() != static_cast(0)) { // priority found? - QXK_activate_(); // activate any unlocked basic threads + // are any other threads waiting for this mutex? + if (m_waitSet.notEmpty()) { + + // find the highest-priority waiting thread + uint_fast8_t p = m_waitSet.findMax(); + QXThread *thr = static_cast(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(0)) /* extended thread */ + && (!QXK_attr_.readySet.hasElement(p)) + && (thr->m_prio == thr->m_startPrio) + && (thr->m_temp.obj == reinterpret_cast(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(0), static_cast(0)) + QS_TIME_(); // timestamp + QS_2U8_(static_cast(thr->m_startPrio),/*start prio*/ + static_cast(thr->m_prio)); // ceiling prio + QS_END_NOCRIT_() + } + else { // no threads are waiting for this mutex + m_lockNest = static_cast(0); + + // put the mutex at the priority ceiling slot + QF::active_[m_ceiling] = reinterpret_cast(this); + } + + // schedule the next thread if multitasking started + if (QXK_sched_() != static_cast(0)) { + QXK_activate_(); // activate a basic thread } } - else { - QS_BEGIN_NOCRIT_(QS_SCHED_UNLOCK, - static_cast(0), static_cast(0)) - QS_TIME_(); // timestamp - p = QXK_attr_.lockPrio; - QS_2U8_(static_cast(p), /* prev lock */ - static_cast(p)); // new lock prio - QS_END_NOCRIT_() + else { // releasing the mutex + --m_lockNest; // release one level } QF_CRIT_EXIT_(); } diff --git a/src/qxk/qxk_sema.cpp b/src/qxk/qxk_sema.cpp index 1e6138c7..a128ae60 100644 --- a/src/qxk/qxk_sema.cpp +++ b/src/qxk/qxk_sema.cpp @@ -3,8 +3,8 @@ /// @ingroup qxk /// @cond ////************************************************************************** -/// Last updated for version 5.9.6 -/// Last updated on 2017-07-27 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-20 /// /// 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 /// QXTHREAD_NO_TIMEOUT indicates that no timeout will /// occur and the semaphore will wait indefinitely. -/// @param[in] tickRate system clock tick rate serviced in this call. -/// /// @returns /// true if the semaphore has been signaled, and false if the timeout occured. /// /// @note /// Multiple extended threads can wait for a given semahpre. /// -bool QXSemaphore::wait(uint_fast16_t const nTicks, - uint_fast8_t const tickRate) -{ +bool QXSemaphore::wait(uint_fast16_t const nTicks) { QF_CRIT_STAT_ 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 */ && (thr != static_cast(0)) /* current must be extended */ && (QXK_attr_.lockPrio == static_cast(0)) /* no lock */ - && (thr->m_temp.obj == static_cast(0))); // !blocked + && (thr->m_temp.obj == static_cast(0))); // !blocked if (m_count > static_cast(0)) { --m_count; @@ -131,7 +127,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks, else { // remember the blocking object thr->m_temp.obj = reinterpret_cast(this); - thr->teArm_(static_cast(QXK_SEMA_SIG), nTicks, tickRate); + thr->teArm_(static_cast(QXK_SEMA_SIG), nTicks); m_waitSet.insert(thr->m_prio); QXK_attr_.readySet.remove(thr->m_prio); (void)QXK_sched_(); @@ -142,7 +138,7 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks, // the blocking object must be this semaphore Q_ASSERT_ID(210, thr->m_temp.obj == reinterpret_cast(this)); - thr->m_temp.obj = static_cast(0); // clear + thr->m_temp.obj = static_cast(0); // clear } QF_CRIT_EXIT_(); @@ -150,6 +146,40 @@ bool QXSemaphore::wait(uint_fast16_t const nTicks, return (thr->m_timeEvt.sig != static_cast(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(0))); + + QF_CRIT_ENTRY_(); + // is the semaphore available? + if (m_count > static_cast(0)) { + --m_count; + isAvailable = true; + } + else { // the semaphore is NOT available (would block) + isAvailable = false; + } + QF_CRIT_EXIT_(); + + return isAvailable; +} + //**************************************************************************** /// @description /// 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 QF_CRIT_STAT_ + /// @pre the semaphore must be initialized + Q_REQUIRE_ID(400, (m_max_count > (uint_fast16_t)0)); + QF_CRIT_ENTRY_(); if (m_waitSet.notEmpty()) { uint_fast8_t p = m_waitSet.findMax(); @@ -180,7 +213,7 @@ bool QXSemaphore::signal(void) { QXThread *thr = static_cast(QF::active_[p]); // the thread must be extended and the semaphore count must be zero - Q_ASSERT_ID(210, (thr != static_cast(0)) /* registered */ + Q_ASSERT_ID(410, (thr != static_cast(0)) /* registered */ && (thr->m_osObject != static_cast(0)) /* extended */ && (m_count == static_cast(0))); // not signaled diff --git a/src/qxk/qxk_xthr.cpp b/src/qxk/qxk_xthr.cpp index da213f6d..0c2d92e6 100644 --- a/src/qxk/qxk_xthr.cpp +++ b/src/qxk/qxk_xthr.cpp @@ -3,8 +3,8 @@ /// @ingroup qxk /// @cond ///*************************************************************************** -/// Last updated for version 5.9.6 -/// Last updated on 2017-07-27 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-19 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -69,7 +69,7 @@ Q_DEFINE_THIS_MODULE("qxk_xthr") /// @usage /// The following example illustrates how to invoke the QXThread ctor in the /// main() function -/// @include qxk_xthread_ctor.cpp +/// @include qxk_xctor.cpp /// QXThread::QXThread(QXThreadHandler const handler, uint_fast8_t const tickRate) : 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] ie pointer to the initial event (not used). /// -/// @note This function should be called via the macro QXTHREAD_START(). -/// /// @usage /// 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, - QEvt const *qSto[], uint_fast16_t const qLen, - void * const stkSto, uint_fast16_t const stkSize, - QEvt const * const /*ie*/) + QEvt const *qSto[], uint_fast16_t const qLen, + void * const stkSto, uint_fast16_t const stkSize, + 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(QF_MAX_ACTIVE)) && (stkSto != static_cast(0)) && (stkSize != static_cast(0)) @@ -135,6 +138,7 @@ void QXThread::start(uint_fast8_t const prio, stkSto, stkSize); m_prio = prio; + m_startPrio = prio; 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 /// 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 -/// situation when the post() operation is assumed to succeed (event delivery -/// guarantee). An assertion fires, when the event cannot be delivered in -/// this case. +/// @note +/// The zero value of the @p margin parameter is special and denotes +/// situation when the QXThread::post_() operation is assumed to succeed +/// (event delivery guarantee). An assertion fires, when the event cannot be +/// delivered in this case. /// #ifndef Q_SPY 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::priv_.QS::priv_.locFilter[QS::AO_OBJ], this) - QS_TIME_(); // timestamp - QS_OBJ_(sender); // the sender object - QS_SIG_(e->sig); // the signal of the event - QS_OBJ_(this); // this active object + QS_TIME_(); // timestamp + QS_OBJ_(sender); // the sender object + QS_SIG_(e->sig); // the signal of the event + QS_OBJ_(this); // this active object 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_END_NOCRIT_() @@ -318,16 +324,12 @@ void QXThread::postLIFO(QEvt const * const /*e*/) { /// to wait for the event to arrive. The value of /// QXTHREAD_NO_TIMEOUT indicates that no timeout will /// occur and the queue will block indefinitely. -/// @param[in] tickRate system clock tick rate serviced in this call. -/// /// @returns /// Returns pointer to the event. If the pointer is not NULL, the event /// was delivered. Otherwise the event pointer of NULL indicates that the /// queue has timed out. /// -QEvt const *QXThread::queueGet(uint_fast16_t const nTicks, - uint_fast8_t const tickRate) -{ +QEvt const *QXThread::queueGet(uint_fast16_t const nTicks) { QEQueueCtr nFree; QEvt const *e; QF_CRIT_STAT_ @@ -336,13 +338,13 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks, QXThread *thr = static_cast(QXK_attr_.curr); /// @pre this function must: - /// (1) NOT be called from an ISR; (2) be called from an extended thread; - /// (3) the thread must NOT be holding a mutex and - /// (4) the thread must NOT be already blocked on any object. - /// + /// - NOT be called from an ISR; + /// - be called from an extended thread; + /// - 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 */ && (thr != static_cast(0)) /* current must be extended */ - && (QXK_attr_.lockPrio == static_cast(0)) /* !locked */ + && (QXK_attr_.lockHolder != thr->m_prio) /* not holding a lock */ && (thr->m_temp.obj == static_cast(0))); // !blocked // 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) thr->m_temp.obj = reinterpret_cast(&thr->m_eQueue); - thr->teArm_(static_cast(QXK_QUEUE_SIG), nTicks, tickRate); + thr->teArm_(static_cast(QXK_QUEUE_SIG), nTicks); QXK_attr_.readySet.remove(thr->m_prio); (void)QXK_sched_(); QF_CRIT_EXIT_(); @@ -425,7 +427,7 @@ QEvt const *QXThread::queueGet(uint_fast16_t const nTicks, /// void QXThread::block_(void) const { /// @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); (void)QXK_sched_(); } @@ -455,10 +457,7 @@ void QXThread::unblock_(void) const { /// @note /// must be called from within a critical section /// -void QXThread::teArm_(enum_t const sig, - uint_fast16_t const nTicks, - uint_fast8_t const tickRate) -{ +void QXThread::teArm_(enum_t const sig, uint_fast16_t const nTicks) { /// @pre the time event must be unused Q_REQUIRE_ID(700, m_timeEvt.m_ctr == static_cast(0)); @@ -471,11 +470,12 @@ void QXThread::teArm_(enum_t const sig, // is the time event unlinked? // 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, - // because un-linking is performed exclusively in QF_tickX(). - // + // because un-linking is performed exclusively in QF::tickX(). if ((m_timeEvt.refCtr_ & static_cast(0x80)) == static_cast(0)) { + uint_fast8_t tickRate = + static_cast(m_timeEvt.refCtr_); m_timeEvt.refCtr_ |= static_cast(0x80); // mark as linked // The time event is initially inserted into the separate @@ -515,35 +515,32 @@ bool QXThread::teDisarm_(void) { //**************************************************************************** //! delay (timed block) the current extended thread -bool QXThread::delay(uint_fast16_t const nTicks, - uint_fast8_t const tickRate) -{ +bool QXThread::delay(uint_fast16_t const nTicks) { QF_CRIT_STAT_ QF_CRIT_ENTRY_(); QXThread *thr = static_cast(QXK_attr_.curr); /// @pre this function must: - /// (1) NOT be called from an ISR; (2) be called from an extended thread; - /// (3) the thread must NOT be holding a mutex and - /// (4) the thread must NOT be already blocked on any object. - /// - Q_REQUIRE_ID(900, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ + /// - NOT be called from an ISR; + /// - be called from an extended thread; + /// - the thread must NOT be holding a scheduler lock and; + /// - the thread must NOT be already blocked on any object. + Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */ && (thr != static_cast(0)) /* current must be extended */ - && (QXK_attr_.lockPrio == static_cast(0)) /* !locked */ + && (QXK_attr_.lockHolder != thr->m_prio) /* not holding a lock */ && (thr->m_temp.obj == static_cast(0))); // !blocked - // remember the blocking object thr->m_temp.obj = reinterpret_cast(&thr->m_timeEvt); - thr->teArm_(static_cast(QXK_DELAY_SIG), nTicks, tickRate); + thr->teArm_(static_cast(QXK_DELAY_SIG), nTicks); thr->block_(); QF_CRIT_EXIT_(); QF_CRIT_EXIT_NOP(); // BLOCK here QF_CRIT_ENTRY_(); // 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(&thr->m_timeEvt)); thr->m_temp.obj = static_cast(0); // clear QF_CRIT_EXIT_(); diff --git a/src/qxk_pkg.h b/src/qxk_pkg.h index 03770916..c7671780 100644 --- a/src/qxk_pkg.h +++ b/src/qxk_pkg.h @@ -3,8 +3,8 @@ /// @ingroup qxk /// @cond ///*************************************************************************** -/// Last updated for version 5.7.2 -/// Last updated on 2016-09-28 +/// Last updated for version 5.9.7 +/// Last updated on 2017-08-19 /// /// Q u a n t u m L e a P s /// --------------------------- @@ -54,7 +54,7 @@ enum QXK_Timeouts { extern "C" { //! 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); //! called when a thread function returns diff --git a/version-5.9.6 b/version-5.9.6 deleted file mode 100644 index 5b4ec075..00000000 --- a/version-5.9.6 +++ /dev/null @@ -1,2 +0,0 @@ -QP/C++ 5.9.6 -2017-08-04 diff --git a/version-5.9.7 b/version-5.9.7 new file mode 100644 index 00000000..15abe188 --- /dev/null +++ b/version-5.9.7 @@ -0,0 +1,2 @@ +QP/C++ 5.9.7 +2017-08-18